標籤:shiro java authrentication
網上大多數介紹Apache Shiro的資料都是使用ini檔案的簡單配置為例,很少用講到如何配合資料庫來實現使用者認證的。我也是剛剛開始接觸Shiro,在這裡介紹一個入門層級的Shiro+Mysql的配置方法,這個方法僅僅是個開始,並沒有和Web,Spring,Mybatis等架構進行整合,後續我還會繼續和大家分享我的學習過程及心得。
now we can start the things that we really care about.
資料庫中建立一個使用者表,欄位可以很簡單。
CREATE TABLE `sec_user` ( `user_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_name` varchar(64) COLLATE utf8_bin DEFAULT NULL, `password` varchar(128) COLLATE utf8_bin DEFAULT NULL, `created_time` datetime DEFAULT NULL, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`user_id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
在表中插入一條記錄,使用者名稱:[email protected],密碼:cmao
在resources目錄下建立一個ini檔案,配置Shiro(後續檔案會將此檔案內容移至XML檔案中)。在這個設定檔中我們要設定資料來源,以及使用者認證時使用資料庫查詢語句。這裡用到了Shiro中內建的JdbcRealm類。
[main] dataSource=org.springframework.jdbc.datasource.DriverManagerDataSourcedataSource.driverClassName=com.mysql.jdbc.DriverdataSource.url=jdbc:mysql://127.0.0.1:3306/YOUR_DATABASE_NAMEdataSource.username=YOUR_USERNAMEdataSource.password=YOUR_PASSWORDjdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealmjdbcRealm.permissionsLookupEnabled = true jdbcRealm.dataSource=$dataSourcejdbcRealm.authenticationQuery = SELECT password FROM sec_user WHERE user_name = ? jdbcRealm.userRolesQuery = SELECT role_name FROM sec_role WHERE role_name = ?jdbcRealm.permissionsQuery = SELECT permission FROM sec_role_permissions WHERE role_name = ? securityManager.realms=$jdbcRealm
設定檔寫好後,我們就可以動手寫個測試方法,來驗證是否可以實現使用者認證功能了。
package com.emerons.learning;import static org.junit.Assert.*;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.DisabledAccountException;import org.apache.shiro.authc.ExcessiveAttemptsException;import org.apache.shiro.authc.ExpiredCredentialsException;import org.apache.shiro.authc.IncorrectCredentialsException;import org.apache.shiro.authc.LockedAccountException;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory;import org.junit.After;import org.junit.Before;import org.junit.Test;public class JdbcRealmTest {@Beforepublic void setUp() throws Exception {}@Afterpublic void tearDown() throws Exception {}@Testpublic void test() {// 1.擷取SecurityManager工廠,此處使用ini設定檔初始化SecurityManagerFactory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini");// 2.擷取SecurityManager執行個體,並綁定到SecurityUtilsSecurityManager sm = factory.getInstance();SecurityUtils.setSecurityManager(sm);// 3.得到SubjectSubject subject = SecurityUtils.getSubject();// 4.建立使用者登入憑證UsernamePasswordToken token = new UsernamePasswordToken("[email protected]", "chrismao");// 5.登入,如果登入失敗會拋出不同的異常,根據異常輸出失敗原因try {subject.login(token);// 6.判斷是否成功登入assertEquals(true, subject.isAuthenticated());System.out.println("登入成功!!");// 7.登出使用者subject.logout();} catch (IncorrectCredentialsException e) {System.out.println("登入密碼錯誤. Password for account " + token.getPrincipal() + " was incorrect.");} catch (ExcessiveAttemptsException e) {System.out.println("登入失敗次數過多");} catch (LockedAccountException e) {System.out.println("帳號已被鎖定. The account for username " + token.getPrincipal() + " was locked.");} catch (DisabledAccountException e) {System.out.println("帳號已被禁用. The account for username " + token.getPrincipal() + " was disabled.");} catch (ExpiredCredentialsException e) {System.out.println("帳號已到期. the account for username " + token.getPrincipal() + " was expired.");} catch (UnknownAccountException e) {System.out.println("帳號不存在. There is no user with username of " + token.getPrincipal());}}}
運行測試代碼,得到如下輸出:
INFO : org.springframework.jdbc.datasource.DriverManagerDataSource - Loaded JDBC driver: com.mysql.jdbc.DriverINFO : org.apache.shiro.realm.AuthorizingRealm - No cache or cacheManager properties have been set. Authorization cache cannot be obtained.INFO : org.apache.shiro.config.IniSecurityManagerFactory - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.INFO : org.apache.shiro.session.mgt.AbstractValidatingSessionManager - Enabling session validation scheduler...登入成功!!INFO : org.apache.shiro.realm.AuthorizingRealm - No cache or cacheManager properties have been set. Authorization cache cannot be obtained.
我們從日誌上可以看到,程式載入了Jdbc驅動,明確指定了realm,這說明我們的Shiro設定檔載入成功。最後看到輸出了“登入成功”說明這個認證功能已經實現了。大家也可以試著修改測試代碼用的使用者名稱或是密碼,可以在控制台看到類似下面的輸出,說明也可以拋出正確的異常。
INFO : org.springframework.jdbc.datasource.DriverManagerDataSource - Loaded JDBC driver: com.mysql.jdbc.DriverINFO : org.apache.shiro.realm.AuthorizingRealm - No cache or cacheManager properties have been set. Authorization cache cannot be obtained.INFO : org.apache.shiro.config.IniSecurityManagerFactory - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.登入密碼錯誤. Password for account [email protected] was incorrect.
至此,使用Shiro + Mysql實現使用者認證(Authentication)的功能已經完成。大家可以在這個基礎上,完善實現角色授權(Authroization),操作允可(Permission)等功能。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Shiro系列之Shiro+Mysql實現使用者認證(Authentication)