Shiro框架:Shiro简介、登陆认证入门程序、认证执行流程、使用自定义Realm进行登陆认证、Shiro的MD5散列算法
一、Shiro介紹:
1、什么是shiro:
(1)shiro是apache的一個開源框架,是一個權限管理的框架,實現用戶認證、用戶授權。
(2)spring中有spring security,是一個權限框架,但是它和spring依賴過于緊密,沒有shiro使用簡單。shiro不依賴于spring,shiro不僅可以實現 web應用的權限管理,還可以實現c/s系統,分布式系統權限管理,shiro屬于輕量框架,越來越多企業項目開始使用shiro。
(3)使用shiro實現系統 的權限管理,有效提高開發效率,從而降低開發成本。
2、shiro架構:
(1)subject:主體,可以是用戶也可以是程序,主體要訪問系統,系統需要對主體進行認證、授權。
(2)securityManager:安全管理器,主體進行認證和授權都 是通過securityManager進行。
(3)authenticator:認證器,主體進行認證最終通過authenticator進行的。
(4)authorizer:授權器,主體進行授權最終通過authorizer進行的。
(5)sessionManager:web應用中一般是用web容器對session進行管理,shiro也提供一套session管理的方式。
(6)SessionDao: ?通過SessionDao管理session數據,針對個性化的session數據存儲需要使用sessionDao。
(7)cache Manager:緩存管理器,主要對session和授權數據進行緩存,比如將授權數據通過cacheManager進行緩存管理,和ehcache整合對緩存數據進行管理。
(8)realm:域,領域,相當于數據源,通過realm存取認證、授權相關數據。在realm中存儲授權和認證的邏輯。
(9)cryptography:密碼管理,提供了一套加密/解密的組件,方便開發。比如提供常用的散列、加/解密等功能。比如 md5散列算法。
3、相關jar包依賴:
與其它java開源框架類似,將shiro的jar包加入項目就可以使用shiro提供的功能了。shiro-core是核心包必須選用,還提供了與web整合的shiro-web、與spring整合的shiro-spring、與任務調度quartz整合的shiro-quartz等
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.4.0</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-web</artifactId><version>1.4.0</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>1.4.0</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-quartz</artifactId><version>1.4.0</version></dependency>也可以通過引入shiro-all包括shiro所有的包:
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-all</artifactId><version>1.4.0</version> </dependency>?
?
二、Shiro認證入門程序搭建:
1、shiro認證流程:
2、導入jar包依賴:shiro-core.jar
3、工程結構:
4、編寫shiro-first.ini配置文件:
通過此配置文件創建securityManager工廠。
#對用戶信息進行配置 [users] #用戶賬戶和密碼 zhangsan=111111 lisi=2222225、Authentication類:
//shiro入門程序測試類: public class Authentication {//用戶登陸和退出測試@Testpublic void testLogin(){//1、創建securityManager工廠,通過ini配置文件創建securityManager工廠Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro-first.ini");//2、創建securityManagerSecurityManager securityManager=factory.getInstance();//3、將SecurityManager設置在當前運行環境中SecurityUtils.setSecurityManager(securityManager);//4、從SecurityUtils里面 創建一個subject;Subject subject=SecurityUtils.getSubject();//5、在認證提交前準備token(令牌)UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","111111");try{//6、執行認證提交;subject.login(token);}catch (AuthenticationException e) {e.printStackTrace();}//7、是否認證通過boolean isAuthenticated = subject.isAuthenticated();System.out.println("是否認證通過:"+isAuthenticated);//8、退出操作subject.logout();isAuthenticated = subject.isAuthenticated();System.out.println("是否認證通過:"+isAuthenticated);} }6、運行結果:
至此,一個簡單的shiro入門程序就搭建完成了。
?
?
三、shiro的執行流程:
1、通過ini配置文件創建securityManager;
2、調用subject.login方法主體提交認證,提交的token;
3、securityManager進行認證,securityManager最終由ModularRealmAuthenticator進行認證;
4、ModularRealmAuthenticator調用IniRealm(給realm傳入token) 去ini配置文件中查詢用戶信息;
5、IniRealm根據輸入的token(UsernamePasswordToken)從 shiro-first.ini查詢用戶信息,根據賬號查詢用戶信息(賬號和密碼):
(1)如果查詢到用戶信息,就給ModularRealmAuthenticator返回用戶信息(賬號和密碼)
(2)如果查詢不到,就給ModularRealmAuthenticator返回null
6、ModularRealmAuthenticator接收IniRealm返回Authentication認證信息
(1)如果返回的認證信息是null,ModularRealmAuthenticator拋出異常(org.apache.shiro.authc.UnknownAccountException)
(2)如果返回的認證信息不是null(說明inirealm找到了用戶),對IniRealm返回用戶密碼 (在ini文件中存在)和 token中的密碼 進行對比,如果不一致拋出異常(org.apache.shiro.authc.IncorrectCredentialsException)
小結:
ModularRealmAuthenticator的作用是進行認證,需要調用realm查詢用戶信息(在數據庫中存在用戶信息),
ModularRealmAuthenticator進行密碼對比(認證過程)。
realm:需要根據token中的身份信息去查詢數據庫(入門程序使用ini配置文件),如果查到用戶返回認證信息,如果查詢不到返回null。
?
?
四、自定義Reaml進行用戶認證:
實際開發需要realm從數據庫中查詢用戶信息。
1、繼承realm接口:
2、自定義realm的示例:
工程結構:
3、自定義realm:
//自定義的Realm,需要繼承AuthorizingRealm public class CustomRealm extends AuthorizingRealm{// 設置realm的名稱@Overridepublic void setName(String name) {super.setName("customRealm");}// 用于認證@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {// token是用戶輸入的// 第一步從token中取出身份信息String userCode = (String) token.getPrincipal();// 第二步:根據用戶輸入的userCode從數據庫查詢// ....// 如果查詢不到返回null//這個例子中假設數據庫中用戶賬號是zhangsansanif(!userCode.equals("zhangsan")){//return null;}// 模擬從數據庫查詢到密碼是111111String password = "111111";// 如果查詢到返回認證信息AuthenticationInfoSimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userCode, password, this.getName());return simpleAuthenticationInfo;}// 用于授權@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {// TODO Auto-generated method stubreturn null;} }4、配置realm:
需要在shiro-realm.ini配置realm注入到securityManager中:
[main] #自定義的realm customRealm=com.zwp.shiro.realm.CustomRealm #將realm設置到securityManager,相當于spring中的注入 securityManager.realms=$customRealm5、測試:
@Testpublic void testCustomRealm() {//1、創建securityManager工廠,通過ini配置文件創建securityManager工廠Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro-realm.ini");//2、創建securityManagerSecurityManager securityManager=factory.getInstance();//3、將SecurityManager設置在當前運行環境中SecurityUtils.setSecurityManager(securityManager);//4、從SecurityUtils里面 創建一個subject;Subject subject=SecurityUtils.getSubject();//5、在認證提交前準備token(令牌)UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","111111");try{//6、執行認證提交;subject.login(token);}catch (AuthenticationException e) {e.printStackTrace();}//7、是否認證通過boolean isAuthenticated = subject.isAuthenticated();System.out.println("是否認證通過:"+isAuthenticated);//8、退出操作subject.logout();isAuthenticated = subject.isAuthenticated();System.out.println("是否認證通過:"+isAuthenticated);}6、測試結果:
至此,Realm的配置就完成了。
?
?
五、Shiro的MD5加密算法:
1、散列算法:
在項目中,通常需要對密碼進行散列,常用的有MD5、SHA。
(1)對md5密碼,如果知道散列后的值可以通過窮舉算法,得到md5密碼對應的明文。因此,建議對md5進行散列時加salt(鹽),進行加密相當于對原始密碼+鹽進行散列。
(2)正常使用時散列方法:
在程序中對原始密碼+鹽進行散列,將散列值存儲到數據庫中,并且還要將鹽也要存儲在數據庫中。
(3)如果進行密碼對比時,使用相同方法,將原始密碼+鹽進行散列,進行比對。
2、MD5散列測試程序:
public class MD5Test {public static void main(String[] args) {//原始 密碼 String source = "111111";//鹽String salt = "qwerty";//散列次數int hashIterations = 2;//上邊散列1次:f3694f162729b7d0254c6e40260bf15c//上邊散列2次:36f2dfa24d0a9fa97276abbe13e596fc//構造方法中://第一個參數:明文,原始密碼 //第二個參數:鹽,通過使用隨機數//第三個參數:散列的次數,比如散列兩次,相當 于md5(md5(''))Md5Hash md5Hash = new Md5Hash(source, salt, hashIterations);String password_md5 = md5Hash.toString();System.out.println(password_md5);//第一個參數:散列算法 SimpleHash simpleHash = new SimpleHash("md5", source, salt, hashIterations);System.out.println(simpleHash.toString());} }3、自定義realm支持散列算法:
需求:實際開發時,realm要進行MD5值(明文散列后的值)的對比;
(1)項目結構:
(2)新建realm:(CustomRealmMd5.java)
//自定義realm支持散列算法: public class CustomRealmMd5 extends AuthorizingRealm {// 設置realm的名稱@Overridepublic void setName(String name) {super.setName("customRealmMd5");}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {// token是用戶輸入的// 第一步從token中取出身份信息String userCode = (String) token.getPrincipal();// 第二步:根據用戶輸入的userCode從數據庫查詢// ....// 如果查詢不到返回null// 數據庫中用戶賬號是zhangsansanif(!userCode.equals("zhangsan")){return null; }// 模擬從數據庫查詢到密碼,散列值String password = "13f79dafcbbedc313273e2b891ac84d3";// 從數據庫獲取saltString salt = "qwerty";//上邊散列值和鹽對應的明文:123456 散列次數2// 如果查詢到返回認證信息AuthenticationInfoSimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userCode, password, ByteSource.Util.bytes(salt), this.getName());return simpleAuthenticationInfo;}@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;} }(3)在realm的ini文件中配置憑證匹配器:
[main] #定義憑證匹配器: credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher #散列算法: credentialsMatcher.hashAlgorithmName=md5 #散列次數: credentialsMatcher.hashIterations=2#將憑證匹配器設置到realm customRealm=com.zwp.shiro.realm.CustomRealmMd5 customRealm.credentialsMatcher=$credentialsMatcher securityManager.realms=$customRealm(4)測試類:
//自定義realm支持散列算法測試:@Testpublic void testCustomRealmMd5() {//1、創建securityManager工廠,通過ini配置文件創建securityManager工廠Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro-realm-md5.ini");//2、創建securityManagerSecurityManager securityManager=factory.getInstance();//3、將SecurityManager設置在當前運行環境中SecurityUtils.setSecurityManager(securityManager);//4、從SecurityUtils里面 創建一個subject;Subject subject=SecurityUtils.getSubject();//5、在認證提交前準備token(令牌)UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","123456");try{//6、執行認證提交;subject.login(token);}catch (AuthenticationException e) {e.printStackTrace();}//7、是否認證通過boolean isAuthenticated = subject.isAuthenticated();System.out.println("是否認證通過:"+isAuthenticated);//8、退出操作subject.logout();isAuthenticated = subject.isAuthenticated();System.out.println("是否認證通過:"+isAuthenticated);}至此,自定義realm支持散列算法的就完成了。
?
?
總結
以上是生活随笔為你收集整理的Shiro框架:Shiro简介、登陆认证入门程序、认证执行流程、使用自定义Realm进行登陆认证、Shiro的MD5散列算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hibernate进阶之如何使用Hql内
- 下一篇: Shiro框架:授权流程、授权方式、Sh