溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

shiro教程(2)- shiro介紹

發(fā)布時間:2020-07-13 13:19:03 來源:網(wǎng)絡(luò) 閱讀:906 作者:歐陽思海 欄目:數(shù)據(jù)庫

shiro教程系列

shiro教程(3)-shiro授權(quán)






shiro介紹 

1.1 什么是shiro

Shiroapache旗下一個開源框架,它將軟件系統(tǒng)的安全認(rèn)證相關(guān)的功能抽取出來,實(shí)現(xiàn)用戶身份認(rèn)證,權(quán)限授權(quán)、加密、會話管理等功能,組成了一個通用的安全認(rèn)證框架。

1.2 為什么要學(xué)shiro

既然shiro將安全認(rèn)證相關(guān)的功能抽取出來組成一個框架,使用shiro就可以非??焖俚耐瓿烧J(rèn)證、授權(quán)等功能的開發(fā),降低系統(tǒng)成本。

shiro使用廣泛,shiro可以運(yùn)行在web應(yīng)用,非web應(yīng)用,集群分布式應(yīng)用中越來越多的用戶開始使用shiro。

Java領(lǐng)域中spring security(原名Acegi)也是一個開源的權(quán)限管理框架,但是spring security依賴spring運(yùn)行,而shiro就相對獨(dú)立,最主要是因?yàn)?/span>shiro使用簡單、靈活,所以現(xiàn)在越來越多的用戶選擇shiro。

 

1.3 Shiro架構(gòu)

 

  shiro教程(2)- shiro介紹

 

 

1.3.1 Subject

Subject即主體,外部應(yīng)用與subject進(jìn)行交互,subject記錄了當(dāng)前操作用戶,將用戶的概念理解為當(dāng)前操作的主體,可能是一個通過瀏覽器請求的用戶,也可能是一個運(yùn)行的程序。 Subjectshiro中是一個接口,接口中定義了很多認(rèn)證授相關(guān)的方法,外部程序通過subject進(jìn)行認(rèn)證授,而subject是通過SecurityManager安全管理器進(jìn)行認(rèn)證授權(quán)

 

1.3.2 SecurityManager 

SecurityManager即安全管理器,對全部的subject進(jìn)行安全管理,它是shiro的核心,負(fù)責(zé)對所有的subject進(jìn)行安全管理。通過SecurityManager可以完成subject的認(rèn)證、授權(quán)等,實(shí)質(zhì)上SecurityManager是通過Authenticator進(jìn)行認(rèn)證,通過Authorizer進(jìn)行授權(quán),通過SessionManager進(jìn)行會話管理等。

SecurityManager是一個接口,繼承了Authenticator, Authorizer, SessionManager這三個接口。


 

1.3.3 Authenticator

Authenticator即認(rèn)證器,對用戶身份進(jìn)行認(rèn)證,Authenticator是一個接口,shiro提供ModularRealmAuthenticator實(shí)現(xiàn)類,通過ModularRealmAuthenticator基本上可以滿足大多數(shù)需求,也可以自定義認(rèn)證器。


1.3.4 Authorizer

Authorizer即授權(quán)器,用戶通過認(rèn)證器認(rèn)證通過,在訪問功能時需要通過授權(quán)器判斷用戶是否有此功能的操作權(quán)限。


 

1.3.5 realm

Realm即領(lǐng)域,相當(dāng)于datasource數(shù)據(jù)源,securityManager進(jìn)行安全認(rèn)證需要通過Realm獲取用戶權(quán)限數(shù)據(jù),比如:如果用戶身份數(shù)據(jù)在數(shù)據(jù)庫那么realm就需要從數(shù)據(jù)庫獲取用戶身份信息。

注意:不要把realm理解成只是從數(shù)據(jù)源取數(shù)據(jù),在realm中還有認(rèn)證授權(quán)校驗(yàn)的相關(guān)的代碼。

 

1.3.6 sessionManager

sessionManager即會話管理,shiro框架定義了一套會話管理,它不依賴web容器的session,所以shiro可以使用在非web應(yīng)用上,也可以將分布式應(yīng)用的會話集中在一點(diǎn)管理,此特性可使它實(shí)現(xiàn)單點(diǎn)登錄。

1.3.7 SessionDAO

SessionDAO會話dao,是對session會話操作的一套接口,比如要將session存儲到數(shù)據(jù)庫,可以通過jdbc將會話存儲到數(shù)據(jù)庫。

1.3.8 CacheManager

CacheManager即緩存管理,將用戶權(quán)限數(shù)據(jù)存儲在緩存,這樣可以提高性能。

1.3.9 Cryptography

Cryptography即密碼管理,shiro提供了一套加密/解密的組件,方便開發(fā)。比如提供常用的散列、加/解密等功能。

 

1.4 shirojar

與其它java開源框架類似,將shirojar包加入項(xiàng)目就可以使用shiro提供的功能了。shiro-core是核心包必須選用,還提供了與web整合的shiro-web、與spring整合的shiro-spring、與任務(wù)調(diào)度quartz整合的shiro-quartz等,下邊是shirojar包的maven坐標(biāo)。

 

[html] view plain copy print? shiro教程(2)- shiro介紹  shiro教程(2)- shiro介紹

  1. <dependency>  

  2.   

  3. <groupId>org.apache.shiro</groupId>  

  4.   

  5. <artifactId>shiro-core</artifactId>  

  6.   

  7. <version>1.2.3</version>  

  8.   

  9. </dependency>  

  10.   

  11. <dependency>  

  12.   

  13. <groupId>org.apache.shiro</groupId>  

  14.   

  15. <artifactId>shiro-web</artifactId>  

  16.   

  17. <version>1.2.3</version>  

  18.   

  19. </dependency>  

  20.   

  21. <dependency>  

  22.   

  23. <groupId>org.apache.shiro</groupId>  

  24.   

  25. <artifactId>shiro-spring</artifactId>  

  26.   

  27. <version>1.2.3</version>  

  28.   

  29. </dependency>  

  30.   

  31. <dependency>  

  32.   

  33. <groupId>org.apache.shiro</groupId>  

  34.   

  35. <artifactId>shiro-ehcache</artifactId>  

  36.   

  37. <version>1.2.3</version>  

  38.   

  39. </dependency>  

  40.   

  41. <dependency>  

  42.   

  43. <groupId>org.apache.shiro</groupId>  

  44.   

  45. <artifactId>shiro-quartz</artifactId>  

  46.   

  47. <version>1.2.3</version>  

  48.   

  49. </dependency>  

  50.   

  51.    

  52.   

  53. 也可以通過引入shiro-all包括shiro所有的包:  

  54.   

  55. <dependency>  

  56.   

  57. <groupId>org.apache.shiro</groupId>  

  58.   

  59. <artifactId>shiro-all</artifactId>  

  60.   

  61. <version>1.2.3</version>  

  62.   

  63. </dependency>  



 

 

參考lib目錄 :

  shiro教程(2)- shiro介紹

 

 

 

shiro認(rèn)證

2.1 認(rèn)證流程

 shiro教程(2)- shiro介紹

 

2.2 入門程序(用戶登陸和退出)

2.2.1 創(chuàng)建java工程

jdk版本:1.7.0_72

eclipseelipse-indigo

 

2.2.2 加入shiro-coreJar包及依賴包

  shiro教程(2)- shiro介紹

 

 

2.2.3 log4j.properties日志配置文件

log4j.rootLogger=debug, stdout

 

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n

 

 

2.2.4 shiro.ini

通過Shiro.ini配置文件初始化SecurityManager環(huán)境。

 

配置 eclipse支持ini文件編輯:


 shiro教程(2)- shiro介紹

 

eclipse配置后,在classpath創(chuàng)建shiro.ini配置文件,為了方便測試將用戶名和密碼配置的shiro.ini配置文件中:

 

[users]

zhang=123

lisi=123

 

 

2.2.5 認(rèn)證代碼

 

[java] view plain copy print? shiro教程(2)- shiro介紹  shiro教程(2)- shiro介紹

  1. // 用戶登陸、用戶退出  

  2.   

  3. @Test  

  4.   

  5. public void testLoginLogout() {  

  6.   

  7.    

  8.   

  9. // 構(gòu)建SecurityManager工廠,IniSecurityManagerFactory可以從ini文件中初始化SecurityManager環(huán)境  

  10.   

  11. Factory<SecurityManager> factory = new IniSecurityManagerFactory(  

  12.   

  13. "classpath:shiro.ini");  

  14.   

  15.    

  16.   

  17. // 通過工廠創(chuàng)建SecurityManager  

  18.   

  19. SecurityManager securityManager = factory.getInstance();  

  20.   

  21. // 將securityManager設(shè)置到運(yùn)行環(huán)境中  

  22.   

  23. SecurityUtils.setSecurityManager(securityManager);  

  24.   

  25.    

  26.   

  27. // 創(chuàng)建一個Subject實(shí)例,該實(shí)例認(rèn)證要使用上邊創(chuàng)建的securityManager進(jìn)行  

  28.   

  29. Subject subject = SecurityUtils.getSubject();  

  30.   

  31.    

  32.   

  33. // 創(chuàng)建token令牌,記錄用戶認(rèn)證的身份和憑證即賬號和密碼  

  34.   

  35. UsernamePasswordToken token = new UsernamePasswordToken("zhang""123");  

  36.   

  37.    

  38.   

  39. try {  

  40.   

  41. // 用戶登陸  

  42.   

  43. subject.login(token);  

  44.   

  45. catch (AuthenticationException e) {  

  46.   

  47. // TODO Auto-generated catch block  

  48.   

  49. e.printStackTrace();  

  50.   

  51. }  

  52.   

  53.    

  54.   

  55. // 用戶認(rèn)證狀態(tài)  

  56.   

  57.    

  58.   

  59. Boolean isAuthenticated = subject.isAuthenticated();  

  60.   

  61.    

  62.   

  63. System.out.println("用戶認(rèn)證狀態(tài):" + isAuthenticated);  

  64.   

  65.    

  66.   

  67. // 用戶退出  

  68.   

  69.    

  70.   

  71. subject.logout();  

  72.   

  73.    

  74.   

  75. isAuthenticated = subject.isAuthenticated();  

  76.   

  77.    

  78.   

  79. System.out.println("用戶認(rèn)證狀態(tài):" + isAuthenticated);  

  80.   

  81.    

  82.   

  83. }  

  84.   

  85.    



 

2.2.6 認(rèn)證執(zhí)行流程

 

1、 創(chuàng)建token令牌,token中有用戶提交的認(rèn)證信息即賬號和密碼

2、 執(zhí)行subject.login(token),最終由securityManager通過Authenticator進(jìn)行認(rèn)證

3、 Authenticator的實(shí)現(xiàn)ModularRealmAuthenticator調(diào)用realmini配置文件取用戶真實(shí)的賬號和密碼,這里使用的是IniRealmshiro自帶)

4、 IniRealm先根據(jù)token中的賬號去ini中找該賬號,如果找不到則給ModularRealmAuthenticator返回null,如果找到則匹配密碼,匹配密碼成功則認(rèn)證通過。

 

2.2.7 常見的異常

UnknownAccountException

賬號不存在異常如下:

org.apache.shiro.authc.UnknownAccountException: No account found for user。。。。

 

 

IncorrectCredentialsException

當(dāng)輸入密碼錯誤會拋此異常,如下:

org.apache.shiro.authc.IncorrectCredentialsException: Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - zhangsan, rememberMe=false] did not match the expected credentials.

 

 

更多如下:

DisabledAccountException(帳號被禁用)

LockedAccountException(帳號被鎖定)

ExcessiveAttemptsException(登錄失敗次數(shù)過多)

ExpiredCredentialsException(憑證過期)等

 

 

 

2.3 自定義Realm

上邊的程序使用的是Shiro自帶的IniRealm,IniRealmini配置文件中讀取用戶的信息,大部分情況下需要從系統(tǒng)的數(shù)據(jù)庫中讀取用戶信息,所以需要自定義realm。

 

2.3.1 shiro提供的realm

 shiro教程(2)- shiro介紹


 

 

 

最基礎(chǔ)的是Realm接口,CachingRealm負(fù)責(zé)緩存處理,AuthenticationRealm負(fù)責(zé)認(rèn)證,AuthorizingRealm負(fù)責(zé)授權(quán),通常自定義的realm繼承AuthorizingRealm。

 

2.3.2 自定義Realm

 

[java] view plain copy print? shiro教程(2)- shiro介紹  shiro教程(2)- shiro介紹

  1. public class CustomRealm1 extends AuthorizingRealm {  

  2.   

  3.    

  4.   

  5. @Override  

  6.   

  7. public String getName() {  

  8.   

  9. return "customRealm1";  

  10.   

  11. }  

  12.   

  13.    

  14.   

  15. //支持UsernamePasswordToken  

  16.   

  17. @Override  

  18.   

  19. public boolean supports(AuthenticationToken token) {  

  20.   

  21. return token instanceof UsernamePasswordToken;  

  22.   

  23. }  

  24.   

  25.    

  26.   

  27. //認(rèn)證  

  28.   

  29. @Override  

  30.   

  31. protected AuthenticationInfo doGetAuthenticationInfo(  

  32.   

  33. AuthenticationToken token) throws AuthenticationException {  

  34.   

  35. //從token中 獲取用戶身份信息  

  36.   

  37. String username = (String) token.getPrincipal();  

  38.   

  39. //拿username從數(shù)據(jù)庫中查詢  

  40.   

  41. //....  

  42.   

  43. //如果查詢不到則返回null  

  44.   

  45. if(!username.equals("zhang")){//這里模擬查詢不到  

  46.   

  47. return null;  

  48.   

  49. }  

  50.   

  51. //獲取從數(shù)據(jù)庫查詢出來的用戶密碼  

  52.   

  53. String password = "123";//這里使用靜態(tài)數(shù)據(jù)模擬。。  

  54.   

  55. //返回認(rèn)證信息由父類AuthenticatingRealm進(jìn)行認(rèn)證  

  56.   

  57. SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(  

  58.   

  59. username, password, getName());  

  60.   

  61.    

  62.   

  63. return simpleAuthenticationInfo;  

  64.   

  65. }  

  66.   

  67.    

  68.   

  69. //授權(quán)  

  70.   

  71. @Override  

  72.   

  73. protected AuthorizationInfo doGetAuthorizationInfo(  

  74.   

  75. PrincipalCollection principals) {  

  76.   

  77. // TODO Auto-generated method stub  

  78.   

  79. return null;  

  80.   

  81. }  

  82.   

  83.    

  84.   

  85. }  

  86.   

  87.    



2.3.3 shiro-realm.ini

[html] view plain copy print? shiro教程(2)- shiro介紹  shiro教程(2)- shiro介紹

  1. [main]  

  2.   

  3. #自定義 realm  

  4.   

  5. customRealm=com.sihai.shiro.authentication.realm.CustomRealm1  

  6.   

  7. #將realm設(shè)置到securityManager  

  8.   

  9. securityManager.realms=$customRealm  

  10.   

  11.    




 

2.3.4 測試代碼

 

測試代碼同入門程序,將ini的地址修改為shiro-realm.ini。

 

分別模擬賬號不存在、密碼錯誤、賬號和密碼正確進(jìn)行測試。

 

2.4 散列算法

散列算法一般用于生成一段文本的摘要信息,散列算法不可逆,將內(nèi)容可以生成摘要,無法將摘要轉(zhuǎn)成原始內(nèi)容。散列算法常用于對密碼進(jìn)行散列,常用的散列算法有MD5SHA。

一般散列算法需要提供一個salt(鹽)與原始內(nèi)容生成摘要信息,這樣做的目的是為了安全性,比如:111111md5值是:96e79218965eb72c92a549dd5a330112,拿著“96e79218965eb72c92a549dd5a330112”去md5破解網(wǎng)站很容易進(jìn)行破解,如果要是對111111salt(鹽,一個隨機(jī)數(shù))進(jìn)行散列,這樣雖然密碼都是111111加不同的鹽會生成不同的散列值。

 

2.4.1 例子

 

[java] view plain copy print? shiro教程(2)- shiro介紹  shiro教程(2)- shiro介紹

  1. //md5加密,不加鹽  

  2.   

  3. String password_md5 = new Md5Hash("111111").toString();  

  4.   

  5. System.out.println("md5加密,不加鹽="+password_md5);  

  6.   

  7. //md5加密,加鹽,一次散列  

  8.   

  9. String password_md5_sale_1 = new Md5Hash("111111""eteokues"1).toString();  

  10.   

  11. System.out.println("password_md5_sale_1="+password_md5_sale_1);  

  12.   

  13. String password_md5_sale_2 = new Md5Hash("111111""uiwueylm"1).toString();  

  14.   

  15. System.out.println("password_md5_sale_2="+password_md5_sale_2);  

  16.   

  17. //兩次散列相當(dāng)于md5(md5())  

  18.   

  19.    

  20.   

  21. //使用SimpleHash  

  22.   

  23. String simpleHash = new SimpleHash("MD5""111111""eteokues",1).toString();  

  24.   

  25. System.out.println(simpleHash);  

  26.   

  27.    



 

 

2.4.2 realm中使用

 

實(shí)際應(yīng)用是將鹽和散列后的值存在數(shù)據(jù)庫中,自動realm從數(shù)據(jù)庫取出鹽和加密后的值由shiro完成密碼校驗(yàn)。

 

2.4.2.1 自定義realm

 

[java] view plain copy print? shiro教程(2)- shiro介紹  shiro教程(2)- shiro介紹

  1. @Override  

  2.   

  3. protected AuthenticationInfo doGetAuthenticationInfo(  

  4.   

  5. AuthenticationToken token) throws AuthenticationException {  

  6.   

  7. //用戶賬號  

  8.   

  9. String username = (String) token.getPrincipal();  

  10.   

  11. //根據(jù)用戶賬號從數(shù)據(jù)庫取出鹽和加密后的值  

  12.   

  13. //..這里使用靜態(tài)數(shù)據(jù)  

  14.   

  15. //如果根據(jù)賬號沒有找到用戶信息則返回null,shiro拋出異?!百~號不存在”  

  16.   

  17. //按照固定規(guī)則加密碼結(jié)果 ,此密碼 要在數(shù)據(jù)庫存儲,原始密碼 是111111,鹽是eteokues  

  18.   

  19. String password = "cb571f7bd7a6f73ab004a70322b963d5";  

  20.   

  21. //鹽,隨機(jī)數(shù),此隨機(jī)數(shù)也在數(shù)據(jù)庫存儲  

  22.   

  23. String salt = "eteokues";  

  24.   

  25. //返回認(rèn)證信息  

  26.   

  27. SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(  

  28.   

  29. username, password, ByteSource.Util.bytes(salt),getName());  

  30.   

  31.    

  32.   

  33. return simpleAuthenticationInfo;  

  34.   

  35. }  



 

2.4.2.2 realm配置

 

配置shiro-cryptography.ini

 

[html] view plain copy print? shiro教程(2)- shiro介紹  shiro教程(2)- shiro介紹

  1. [main]  

  2.   

  3. #定義憑證匹配器  

  4.   

  5. credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher  

  6.   

  7. #散列算法  

  8.   

  9. credentialsMatcher.hashAlgorithmName=md5  

  10.   

  11. #散列次數(shù)  

  12.   

  13. credentialsMatcher.hashIterations=1  

  14.   

  15.    

  16.   

  17. #將憑證匹配器設(shè)置到realm  

  18.   

  19. customRealm=com.sihai.shiro.authentication.realm.CustomRealm2  

  20.   

  21. customRealm.credentialsMatcher=$credentialsMatcher  

  22.   

  23. securityManager.realms=$customRealm  



 

2.4.2.3 測試代碼

測試代碼同上個章節(jié),注意修改ini路徑。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI