shiro权限框架
1.入門案例
導入maven依賴
shiro-core:核心包 shiro-web:主要用于整合web項目 shiro-pring:主要用于整合spring框架 shiro-quartz:主要用于整合任務調度quartz shiro-ehcache:主要用于整合ehcache緩存pom.xml
? ? ? ?<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.3.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency> <dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency>shiro.ini
[users] admin=123456認證代碼:
? ?@Testpublic void loginTest(){//認證操作//加載資源文件Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:config/shiro.ini");//創建安全管理器SecurityManager securityManager = factory.getInstance();//把安全管理器設置到SecurityUtils中SecurityUtils.setSecurityManager(securityManager);//通過安全工具類創建當前Subject主體對象Subject subject = SecurityUtils.getSubject();//創建用戶認證用的令牌UsernamePasswordToken token=new UsernamePasswordToken("admin","admin");//通過login方法進行認證try {subject.login(token);System.out.println("通過驗證,可以登陸");} catch (AuthenticationException e) {System.out.println("登陸失敗");}//判斷認證結果boolean authenticated = subject.isAuthenticated();System.out.println("認證結果:"+authenticated);//退出系統subject.logout();}認證成功:
通過驗證,可以登陸 認證結果:true認證失敗:
登陸失敗 認證結果:false-
原理分析
-
通過加載shiro.ini配置文件創建securityManager
-
通過subject.login方法提交認證,提交token封裝的用戶信息
-
securityManager進行認證,securityManager最終由ModularRealmAuthenticator進行認證
-
ModularRealmAuthenticator通過調用iniRealm去ini配置文件中查詢用戶信息
-
iniRealm根據輸入的token從ini配置文件中查詢用戶信息,根據帳號查詢用戶信息(用戶名和密碼),如果查詢到用戶信息,就返回用戶信息,查詢不到,返回null
-
ModularRealmAuthenticator根據iniRealm返回的認證信息,如果是null,拋出異常。如果不是null,說明找到了用戶,將返回的用戶密碼和token中的密碼進行對比,如果不一致則拋出異常
1.自定義realm認證
實際開發過程中,realm域主要用于數據庫的交互,我們可以自定義realm類,從數據庫中獲取信息
自定義realm的步驟:
自定義realm類繼承AuthorizingRealm
重寫驗證方法,連接數據庫,獲取數據
自定義ini配置文件
通過junit進行測試
MyRealm.java
public class MyRealm extends AuthorizingRealm { ?/*** 授權方法* @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {return null;} ?/*** 認證方法* @param authenticationToken* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {//通過token令牌獲取用戶賬戶信息String username = (String)authenticationToken.getPrincipal();//根據用戶名從數據庫中查詢用戶密碼String password="admin";if(password==null||"".equals(password)){return null;}//把用戶名密碼和域的簡寫類封裝到SimpleAuthenticationInforeturn new SimpleAuthenticationInfo(username,password,"myRealm");} }shiro-realm.ini
[main] authRealm=com.yfy.realm.MyRealm securityManager.realms=$authRealmTest.java
? ?@Testpublic void loginTest1(){//認證操作//加載資源文件Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:config/shiro-realm.ini");//創建安全管理器SecurityManager securityManager = factory.getInstance();//把安全管理器設置到SecurityUtils中SecurityUtils.setSecurityManager(securityManager);//通過安全工具類創建當前Subject主體對象Subject subject = SecurityUtils.getSubject();//創建用戶認證用的令牌UsernamePasswordToken token=new UsernamePasswordToken("admin","admin");//通過login方法進行認證try {subject.login(token);System.out.println("通過驗證,可以登陸");} catch (AuthenticationException e) {System.out.println("登陸失敗");}//判斷認證結果boolean authenticated = subject.isAuthenticated();System.out.println("認證結果:"+authenticated);//退出系統subject.logout();}3.散列加密算法
在實際開發過程中,一般密碼都是以密文的形式進行保存的。shiro也對數據加密提供了支持,常見的加密算法有:md5,sha等
1.Md5Hash類 :通過帶參構造器可以實現帶驗證的加密
2.SimpleHash類:通過帶參構造器可以指定加密方式
? ?/*** md5和sha的加密算法*/@Testpublic void testMd5(){String password="admin";String salt="123456";int times=1;//參數:原始密碼的明文,鹽值隨機數,數列次數Md5Hash md=new Md5Hash(password,salt,times);System.out.println(md);System.out.println("---------------");//參數:加密方式,原始密碼的明文,鹽值隨機數,數列次數SimpleHash sh=new SimpleHash("sha",password,salt,times);System.out.println(sh);}4.散列加密算法實現步驟
數據插入到數據庫的時候,先根據加密算法加密后再保存
自定義realm類,繼承AuthorizingRealm抽象類
重寫驗證方法,根據用戶名查詢加密后的用戶密碼和鹽值
編寫ini配置文件,設置匹配器
Md5AutoRealm.java
public class Md5AuthRealm extends AuthorizingRealm { ?@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}/*** 認證方法*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//通過token對象獲取用戶賬號,用戶自己輸入的賬號String username = token.getPrincipal().toString();//根據獲取到的用戶賬號查詢數據表中對應密碼和鹽值 加密后的密碼值String password = "50317b958ee25a1e14449aeb95db5245";//密碼加密到數據庫時使用的鹽值String salt = "abcd";//封裝到SimpleAuthenticationInfo實現類對象中SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,ByteSource.Util.bytes(salt),"md5AuthRealm");return authenticationInfo;} ? }shiro-md5.ini
[main] #定義憑證匹配器 credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher #定義散列算法 credentialsMatcher.hashAlgorithmName=md5 #定義散列次數 credentialsMatcher.hashIterations=1 #將憑證匹配器設置到域 md5AuthRealm=com.yfy.realm.Md5AuthRealm md5AuthRealm.credentialsMatcher=$credentialsMatcher securityManager.realms=$md5AuthRealm5.shiro通過ini配置文件授權
shiro-perm.ini
[users] #用戶admin的密碼是admin,此用戶具有role1和role2兩個角色 admin=admin,role1,role2 #用戶test的密碼是test,此用戶具有role2角色 test=test,role2 ? [roles] #角色role1對資源user擁有create、update權限 role1=user:create,user:update #角色role2對資源user擁有create、delete權限 role2=user:create,user:delete ? #配置文件中的內容屬于靜態的資源配置定義,動態的數據配置需要從數據庫中獲取 #user:*代表通配符,匹配所有user操作權限Test.java
? ?@Testpublic void testPerm() {// 加載資源文件Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:config/shiro-perm.ini");// 創建安全管理器SecurityManager securityManager = factory.getInstance();// 把安全管理器設置到SecurityUtilsSecurityUtils.setSecurityManager(securityManager);// 通過安全工具類創建subject主體對象Subject subject = SecurityUtils.getSubject();// 創建用戶認證用的令牌UsernamePasswordToken token = new UsernamePasswordToken("test", "test");try {// 通過subject主體的login方法來進行認證subject.login(token);System.out.println("通過驗證,可以登錄系統");} catch (Exception e) {System.out.println("驗證失敗。。。。");e.printStackTrace();}// 判斷認證結果boolean authenticated = subject.isAuthenticated();System.out.println(authenticated); ?// 判斷當前主體對象是否屬于指定的角色boolean hasRole = subject.hasRole("role1");System.out.println("當前主體是否擁有role1 :" + hasRole); ?// 判斷是否具有自定的權限boolean permitted = subject.isPermitted("test");System.out.println("當前主體具有創建用戶的權限:" + permitted); ?// 多角色判斷boolean flag = subject.hasAllRoles(Arrays.asList("role1", "role2", "role3"));System.out.println("當前主體具有role1和role2兩個角色:" + flag);// 多權限判斷boolean ppflag = subject.isPermittedAll("user:create", "user:delete");System.out.println("ppflag:" + ppflag);}輸出結果:
通過驗證,可以登錄系統 true admin的輸入role1 :false 當前主體具有創建用戶的權限:false 當前主體具有role1和role2兩個角色:false ppflag:true6.自定義realm授權
-
自定義realm授權的目的是為了訪問數據庫,操作數據庫中的數據進行驗證、授權判斷
MyPermRealm.java
public class MyPermRealm extends AuthorizingRealm { ?/*** 授權操作*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {// 獲取用戶名String username = principals.getPrimaryPrincipal().toString();List<String> perms = new ArrayList<String>();//根據用戶名從數據庫中獲取角色信息String[] roles = {"role1","role2"};//遍歷角色,根據角色獲取每一個角色具有權限信息for(String role : roles){//獲取權限信息,并且保存到權限列表中perms.add("user:create");perms.add("user:delete");perms.add("user:update");}//把權限列表封裝到SimpleAuthorizationInfo對象中SimpleAuthorizationInfo saif = new SimpleAuthorizationInfo();saif.addStringPermissions(perms);saif.addRoles(Arrays.asList(roles));return saif;} ?/*** 認證方法*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = token.getPrincipal().toString();//根據用戶獲取用戶密碼String password = "admin"; //從數據庫中獲取到的密碼的值//把用戶名和密碼封裝到AuthenticationInfo的實現類對象中SimpleAuthenticationInfo shinfo = new SimpleAuthenticationInfo(username,password,"authRealm");return shinfo;} ? }shiro-perm-realm.ini
[main] authRealm=com.yfy.realm.MyPermRealm securityManager.realms=$authRealmTest.java
? ?@Testpublic void testPermRealm() {// 加載資源文件Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:config/shiro-perm-realm.ini");// 創建安全管理器SecurityManager securityManager = factory.getInstance();// 把安全管理器設置到SecurityUtilsSecurityUtils.setSecurityManager(securityManager);// 通過安全工具類創建subject主體對象Subject subject = SecurityUtils.getSubject();// 創建用戶認證用的令牌UsernamePasswordToken token = new UsernamePasswordToken("admin", "admin");try {// 通過subject主體的login方法來進行認證subject.login(token);System.out.println("通過驗證,可以登錄系統");} catch (Exception e) {System.out.println("驗證失敗。。。。");e.printStackTrace();}// 判斷認證結果boolean authenticated = subject.isAuthenticated();System.out.println(authenticated);if (authenticated) {// 判斷當前主體對象是否屬于指定的角色//boolean hasRole = subject.hasRole("role1");//System.out.println("admin的輸入role1 :" + hasRole); ?// 判斷是否具有自定的權限boolean permitted = subject.isPermitted("user:create");System.out.println("當前主體具有創建用戶的權限:" + permitted); ?// 多角色判斷boolean flag = subject.hasAllRoles(Arrays.asList("role1", "role2"));System.out.println("當前主體具有role1和role2兩個角色:" + flag);// 多權限判斷boolean ppflag = subject.isPermittedAll("user:create", "user:delete");System.out.println("ppflag:" + ppflag);}}輸出結果:
通過驗證,可以登錄系統 true 當前主體具有創建用戶的權限:true 當前主體具有role1和role2兩個角色:true ppflag:true?
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
- 上一篇: Hibernate之检索方式(HQL/Q
- 下一篇: SSM整合shiro权限框架