日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

shiro权限框架

發(fā)布時(shí)間:2025/3/20 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 shiro权限框架 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.入門案例

導(dǎo)入maven依賴

shiro-core:核心包 shiro-web:主要用于整合web項(xiàng)目 shiro-pring:主要用于整合spring框架 shiro-quartz:主要用于整合任務(wù)調(diào)度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

認(rèn)證代碼:

? ?@Testpublic void loginTest(){//認(rèn)證操作//加載資源文件Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:config/shiro.ini");//創(chuàng)建安全管理器SecurityManager securityManager = factory.getInstance();//把安全管理器設(shè)置到SecurityUtils中SecurityUtils.setSecurityManager(securityManager);//通過安全工具類創(chuàng)建當(dāng)前Subject主體對(duì)象Subject subject = SecurityUtils.getSubject();//創(chuàng)建用戶認(rèn)證用的令牌UsernamePasswordToken token=new UsernamePasswordToken("admin","admin");//通過login方法進(jìn)行認(rèn)證try {subject.login(token);System.out.println("通過驗(yàn)證,可以登陸");} catch (AuthenticationException e) {System.out.println("登陸失敗");}//判斷認(rèn)證結(jié)果boolean authenticated = subject.isAuthenticated();System.out.println("認(rèn)證結(jié)果:"+authenticated);//退出系統(tǒng)subject.logout();}

認(rèn)證成功:

通過驗(yàn)證,可以登陸 認(rèn)證結(jié)果:true

認(rèn)證失敗:

登陸失敗 認(rèn)證結(jié)果:false
  • 原理分析

  • 通過加載shiro.ini配置文件創(chuàng)建securityManager

  • 通過subject.login方法提交認(rèn)證,提交token封裝的用戶信息

  • securityManager進(jìn)行認(rèn)證,securityManager最終由ModularRealmAuthenticator進(jìn)行認(rèn)證

  • ModularRealmAuthenticator通過調(diào)用iniRealm去ini配置文件中查詢用戶信息

  • iniRealm根據(jù)輸入的token從ini配置文件中查詢用戶信息,根據(jù)帳號(hào)查詢用戶信息(用戶名和密碼),如果查詢到用戶信息,就返回用戶信息,查詢不到,返回null

  • ModularRealmAuthenticator根據(jù)iniRealm返回的認(rèn)證信息,如果是null,拋出異常。如果不是null,說明找到了用戶,將返回的用戶密碼和token中的密碼進(jìn)行對(duì)比,如果不一致則拋出異常

1.自定義realm認(rèn)證

實(shí)際開發(fā)過程中,realm域主要用于數(shù)據(jù)庫的交互,我們可以自定義realm類,從數(shù)據(jù)庫中獲取信息

自定義realm的步驟:

  • 自定義realm類繼承AuthorizingRealm

  • 重寫驗(yàn)證方法,連接數(shù)據(jù)庫,獲取數(shù)據(jù)

  • 自定義ini配置文件

  • 通過junit進(jìn)行測(cè)試

  • MyRealm.java

    public class MyRealm extends AuthorizingRealm { ?/*** 授權(quán)方法* @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {return null;} ?/*** 認(rèn)證方法* @param authenticationToken* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {//通過token令牌獲取用戶賬戶信息String username = (String)authenticationToken.getPrincipal();//根據(jù)用戶名從數(shù)據(jù)庫中查詢用戶密碼String password="admin";if(password==null||"".equals(password)){return null;}//把用戶名密碼和域的簡(jiǎn)寫類封裝到SimpleAuthenticationInforeturn new SimpleAuthenticationInfo(username,password,"myRealm");} }

    shiro-realm.ini

    [main] authRealm=com.yfy.realm.MyRealm securityManager.realms=$authRealm

    Test.java

    ? ?@Testpublic void loginTest1(){//認(rèn)證操作//加載資源文件Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:config/shiro-realm.ini");//創(chuàng)建安全管理器SecurityManager securityManager = factory.getInstance();//把安全管理器設(shè)置到SecurityUtils中SecurityUtils.setSecurityManager(securityManager);//通過安全工具類創(chuàng)建當(dāng)前Subject主體對(duì)象Subject subject = SecurityUtils.getSubject();//創(chuàng)建用戶認(rèn)證用的令牌UsernamePasswordToken token=new UsernamePasswordToken("admin","admin");//通過login方法進(jìn)行認(rèn)證try {subject.login(token);System.out.println("通過驗(yàn)證,可以登陸");} catch (AuthenticationException e) {System.out.println("登陸失敗");}//判斷認(rèn)證結(jié)果boolean authenticated = subject.isAuthenticated();System.out.println("認(rèn)證結(jié)果:"+authenticated);//退出系統(tǒng)subject.logout();}

    3.散列加密算法

    在實(shí)際開發(fā)過程中,一般密碼都是以密文的形式進(jìn)行保存的。shiro也對(duì)數(shù)據(jù)加密提供了支持,常見的加密算法有:md5,sha等

    1.Md5Hash類 :通過帶參構(gòu)造器可以實(shí)現(xiàn)帶驗(yàn)證的加密

    2.SimpleHash類:通過帶參構(gòu)造器可以指定加密方式

    ? ?/*** md5和sha的加密算法*/@Testpublic void testMd5(){String password="admin";String salt="123456";int times=1;//參數(shù):原始密碼的明文,鹽值隨機(jī)數(shù),數(shù)列次數(shù)Md5Hash md=new Md5Hash(password,salt,times);System.out.println(md);System.out.println("---------------");//參數(shù):加密方式,原始密碼的明文,鹽值隨機(jī)數(shù),數(shù)列次數(shù)SimpleHash sh=new SimpleHash("sha",password,salt,times);System.out.println(sh);}

    4.散列加密算法實(shí)現(xiàn)步驟

  • 數(shù)據(jù)插入到數(shù)據(jù)庫的時(shí)候,先根據(jù)加密算法加密后再保存

  • 自定義realm類,繼承AuthorizingRealm抽象類

  • 重寫驗(yàn)證方法,根據(jù)用戶名查詢加密后的用戶密碼和鹽值

  • 編寫ini配置文件,設(shè)置匹配器

  • Md5AutoRealm.java

    public class Md5AuthRealm extends AuthorizingRealm { ?@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}/*** 認(rèn)證方法*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//通過token對(duì)象獲取用戶賬號(hào),用戶自己輸入的賬號(hào)String username = token.getPrincipal().toString();//根據(jù)獲取到的用戶賬號(hào)查詢數(shù)據(jù)表中對(duì)應(yīng)密碼和鹽值 加密后的密碼值String password = "50317b958ee25a1e14449aeb95db5245";//密碼加密到數(shù)據(jù)庫時(shí)使用的鹽值String salt = "abcd";//封裝到SimpleAuthenticationInfo實(shí)現(xiàn)類對(duì)象中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 #定義散列次數(shù) credentialsMatcher.hashIterations=1 #將憑證匹配器設(shè)置到域 md5AuthRealm=com.yfy.realm.Md5AuthRealm md5AuthRealm.credentialsMatcher=$credentialsMatcher securityManager.realms=$md5AuthRealm

    5.shiro通過ini配置文件授權(quán)

    shiro-perm.ini

    [users] #用戶admin的密碼是admin,此用戶具有role1和role2兩個(gè)角色 admin=admin,role1,role2 #用戶test的密碼是test,此用戶具有role2角色 test=test,role2 ? [roles] #角色role1對(duì)資源user擁有create、update權(quán)限 role1=user:create,user:update #角色role2對(duì)資源user擁有create、delete權(quán)限 role2=user:create,user:delete ? #配置文件中的內(nèi)容屬于靜態(tài)的資源配置定義,動(dòng)態(tài)的數(shù)據(jù)配置需要從數(shù)據(jù)庫中獲取 #user:*代表通配符,匹配所有user操作權(quán)限

    Test.java

    ? ?@Testpublic void testPerm() {// 加載資源文件Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:config/shiro-perm.ini");// 創(chuàng)建安全管理器SecurityManager securityManager = factory.getInstance();// 把安全管理器設(shè)置到SecurityUtilsSecurityUtils.setSecurityManager(securityManager);// 通過安全工具類創(chuàng)建subject主體對(duì)象Subject subject = SecurityUtils.getSubject();// 創(chuàng)建用戶認(rèn)證用的令牌UsernamePasswordToken token = new UsernamePasswordToken("test", "test");try {// 通過subject主體的login方法來進(jìn)行認(rèn)證subject.login(token);System.out.println("通過驗(yàn)證,可以登錄系統(tǒng)");} catch (Exception e) {System.out.println("驗(yàn)證失敗。。。。");e.printStackTrace();}// 判斷認(rèn)證結(jié)果boolean authenticated = subject.isAuthenticated();System.out.println(authenticated); ?// 判斷當(dāng)前主體對(duì)象是否屬于指定的角色boolean hasRole = subject.hasRole("role1");System.out.println("當(dāng)前主體是否擁有role1 :" + hasRole); ?// 判斷是否具有自定的權(quán)限boolean permitted = subject.isPermitted("test");System.out.println("當(dāng)前主體具有創(chuàng)建用戶的權(quán)限:" + permitted); ?// 多角色判斷boolean flag = subject.hasAllRoles(Arrays.asList("role1", "role2", "role3"));System.out.println("當(dāng)前主體具有role1和role2兩個(gè)角色:" + flag);// 多權(quán)限判斷boolean ppflag = subject.isPermittedAll("user:create", "user:delete");System.out.println("ppflag:" + ppflag);}

    輸出結(jié)果:

    通過驗(yàn)證,可以登錄系統(tǒng) true admin的輸入role1 :false 當(dāng)前主體具有創(chuàng)建用戶的權(quán)限:false 當(dāng)前主體具有role1和role2兩個(gè)角色:false ppflag:true

    6.自定義realm授權(quán)

    • 自定義realm授權(quán)的目的是為了訪問數(shù)據(jù)庫,操作數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行驗(yàn)證、授權(quán)判斷

    MyPermRealm.java

    public class MyPermRealm extends AuthorizingRealm { ?/*** 授權(quán)操作*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {// 獲取用戶名String username = principals.getPrimaryPrincipal().toString();List<String> perms = new ArrayList<String>();//根據(jù)用戶名從數(shù)據(jù)庫中獲取角色信息String[] roles = {"role1","role2"};//遍歷角色,根據(jù)角色獲取每一個(gè)角色具有權(quán)限信息for(String role : roles){//獲取權(quán)限信息,并且保存到權(quán)限列表中perms.add("user:create");perms.add("user:delete");perms.add("user:update");}//把權(quán)限列表封裝到SimpleAuthorizationInfo對(duì)象中SimpleAuthorizationInfo saif = new SimpleAuthorizationInfo();saif.addStringPermissions(perms);saif.addRoles(Arrays.asList(roles));return saif;} ?/*** 認(rèn)證方法*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = token.getPrincipal().toString();//根據(jù)用戶獲取用戶密碼String password = "admin"; //從數(shù)據(jù)庫中獲取到的密碼的值//把用戶名和密碼封裝到AuthenticationInfo的實(shí)現(xiàn)類對(duì)象中SimpleAuthenticationInfo shinfo = new SimpleAuthenticationInfo(username,password,"authRealm");return shinfo;} ? }

    shiro-perm-realm.ini

    [main] authRealm=com.yfy.realm.MyPermRealm securityManager.realms=$authRealm

    Test.java

    ? ?@Testpublic void testPermRealm() {// 加載資源文件Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:config/shiro-perm-realm.ini");// 創(chuàng)建安全管理器SecurityManager securityManager = factory.getInstance();// 把安全管理器設(shè)置到SecurityUtilsSecurityUtils.setSecurityManager(securityManager);// 通過安全工具類創(chuàng)建subject主體對(duì)象Subject subject = SecurityUtils.getSubject();// 創(chuàng)建用戶認(rèn)證用的令牌UsernamePasswordToken token = new UsernamePasswordToken("admin", "admin");try {// 通過subject主體的login方法來進(jìn)行認(rèn)證subject.login(token);System.out.println("通過驗(yàn)證,可以登錄系統(tǒng)");} catch (Exception e) {System.out.println("驗(yàn)證失敗。。。。");e.printStackTrace();}// 判斷認(rèn)證結(jié)果boolean authenticated = subject.isAuthenticated();System.out.println(authenticated);if (authenticated) {// 判斷當(dāng)前主體對(duì)象是否屬于指定的角色//boolean hasRole = subject.hasRole("role1");//System.out.println("admin的輸入role1 :" + hasRole); ?// 判斷是否具有自定的權(quán)限boolean permitted = subject.isPermitted("user:create");System.out.println("當(dāng)前主體具有創(chuàng)建用戶的權(quán)限:" + permitted); ?// 多角色判斷boolean flag = subject.hasAllRoles(Arrays.asList("role1", "role2"));System.out.println("當(dāng)前主體具有role1和role2兩個(gè)角色:" + flag);// 多權(quán)限判斷boolean ppflag = subject.isPermittedAll("user:create", "user:delete");System.out.println("ppflag:" + ppflag);}}

    輸出結(jié)果:

    通過驗(yàn)證,可以登錄系統(tǒng) true 當(dāng)前主體具有創(chuàng)建用戶的權(quán)限:true 當(dāng)前主體具有role1和role2兩個(gè)角色:true ppflag:true

    ?

    《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

    總結(jié)

    以上是生活随笔為你收集整理的shiro权限框架的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。