shiro認證流程


創建測試工程

加入shiro-core的jar包及其依賴包

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

 

<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-quartz</artifactId>
            <version>1.3.2</version>
        </dependency>

也可以通過引入shiro-all包括shiro所有的包:
    <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-all</artifactId>
            <version>1.3.2</version>
        </dependency>
shiro各jar包的maven坐標

 

創建工程目錄

shiro.ini

通過Shiro.ini配置文件初始化SecurityManager環境。

 配置 eclipse支持ini文件編輯:

 

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

[users]
zhang=111111

認證代碼

public class TestAhentication {

    @Test
    public void testLoginAndLogout() {
        
        // 構建SecurityManager工廠,IniSecurityManagerFactory可以從ini文件中初始化SecurityManager環境
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
        
        // 通過工廠創建SecurityManager
        SecurityManager securityManager = factory.getInstance();
        
        // 將securityManager設置到運行環境中
        SecurityUtils.setSecurityManager(securityManager);
        
        // 創建一個Subject實例,該實例認證要使用上邊創建的securityManager進行
        Subject subject = SecurityUtils.getSubject();
        
//        AuthenticationToken arg0
        UsernamePasswordToken token = new UsernamePasswordToken("zhang","111111");
        
            try {
                subject.login(token);
            } catch (AuthenticationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        
        // 用戶認證狀態
        boolean isAuthenticated = subject.isAuthenticated();
        System.out.println("用戶登錄認證結果:"+isAuthenticated);
        
        //密碼錯誤異常   org.apache.shiro.authc.IncorrectCredentialsException
        //賬號錯誤異常 org.apache.shiro.authc.UnknownAccountException
        
        subject.logout();
        System.out.println("用戶退出認證結果"+subject.isAuthenticated());
    }
}

常見的異常

 UnknownAccountException

賬號不存在異常如下:

org.apache.shiro.authc.UnknownAccountException: Realm [org.apache.shiro.realm.text.IniRealm@7c75222b] was unable to find account data for the submitted AuthenticationToken [org.apache.shiro.authc.UsernamePasswordToken - zhang, rememberMe=false].

IncorrectCredentialsException

當輸入密碼錯誤會拋此異常,如下:

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

更多異常

 

認證執行流程

1、 創建token令牌,token中有用戶提交的認證信息即賬號和密碼

2、 執行subject.login(token),提交給securityManager (安全管理器),安全管理器在通過Authenticator進行認證,

3、 Authenticator 安排ModularRealmAuthenticator調用realmini配置文件取用戶真實的賬號和密碼,這里使用的是IniRealmshiro自帶)

 

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

通過token獲取user的過程

 

 

密碼匹配的過程源碼

 

 

自定義Realm實現通過數據庫查詢數據

  上邊的程序使用的是Shiro自帶的IniRealmIniRealmini配置文件中讀取用戶的信息,大部分情況下需要從系統的數據庫中讀取用戶信息,所以需要自定義realm

 shiro提供的realm

 

 

最基礎的是Realm接口,CachingRealm負責緩存處理,AuthenticationRealm負責認證,AuthorizingRealm負責授權,通常自定義的realm繼承AuthorizingRealm

 創建自定義realm類

public class CustomRealm extends AuthorizingRealm

 

 

 

 

public class CustomRealm extends AuthorizingRealm{

    public void setName() {
        super.setName("customRealm");
    }
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token){

        //獲取認證憑證
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        
        if (username == null) {
            throw new AuthenticationException("賬號為空");
        }
        //進行數據庫查詢賬號信息
        
        //模擬數據庫查詢信息
        if (!username.equals("zhangsan1")) {
            return null;
        }
        //用戶存在 獲取到數據庫的密碼  返回出去
        //假設密碼是1111
        String password = "1111";
        
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());
        
        return info;
    }
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // TODO Auto-generated method stub
        return null;
    }
}

shiro-customRealm.ini

[main]
#自定義 realm
customRealm=com.td.shiro.realm.CustomRealm
#將realm設置到securityManager
securityManager.realms=$customRealm

進行測試

@Test
    public void testLoginAndLogout1() {        
        // 構建SecurityManager工廠,IniSecurityManagerFactory可以從ini文件中初始化SecurityManager環境
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-customRealm.ini");
        // 通過工廠創建SecurityManager
        SecurityManager securityManager = factory.getInstance();
        // 將securityManager設置到運行環境中
        SecurityUtils.setSecurityManager(securityManager);
        // 創建一個Subject實例,該實例認證要使用上邊創建的securityManager進行
        Subject subject = SecurityUtils.getSubject();
//        AuthenticationToken arg0
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","1111");
            try {
                subject.login(token);
            } catch (AuthenticationException e) {
                e.printStackTrace();
            }
        
        // 用戶認證狀態
        boolean isAuthenticated = subject.isAuthenticated();
        System.out.println("用戶登錄認證結果:"+isAuthenticated);
        //密碼錯誤異常   org.apache.shiro.authc.IncorrectCredentialsException
        //賬號錯誤異常 org.apache.shiro.authc.UnknownAccountException    
        subject.logout();
        System.out.println("用戶退出認證結果"+subject.isAuthenticated());
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM