(四)自定義多個Realm以及Authenticator與AuthenticationStrategy


  • Realm配置

    #聲明一個realm  
    myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1  
    myRealm2=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm2  
    #指定securityManager的realms實現  
    securityManager.realms=$myRealm1,$myRealm2   
  1. securityManager會按照realms指定的順序進行身份認證。此處我們使用顯示指定順序的方式指定了Realm的順序,如果刪除“securityManager.realms=$myRealm1,$myRealm2”,那么securityManager會按照realm聲明的順序進行使用(即無需設置realms屬性,其會自動發現),當我們顯示指定realm后,其他沒有指定realm將被忽略,如“securityManager.realms=$myRealm1”,那么myRealm2不會被自動設置進去
  2. 1、變量名=全限定類名會自動創建一個類實例

    2、變量名.屬性=值 自動調用相應的setter方法進行賦值

    3、$變量名 引用之前的一個對象實例

  •   AuthenticatorAuthenticationStrategy

  1. Authenticator的職責是驗證用戶帳號,是Shiro API中身份驗證核心的入口點:

 

    public AuthenticationInfo authenticate(AuthenticationToken authenticationToken)  
                throws AuthenticationException;   

 

 

  • SecurityManager接口繼承了Authenticator,另外還有一個ModularRealmAuthenticator實現(ModularRealmAuthenticator默認使用AtLeastOneSuccessfulStrategy策略。),其委托給多個Realm進行驗證,驗證規則通過AuthenticationStrategy接口指定,默認提供的實現:
  • FirstSuccessfulStrategy:只要有一個Realm驗證成功即可,只返回第一個Realm身份驗證成功的認證信息,其他的忽略;
  • AtLeastOneSuccessfulStrategy:只要有一個Realm驗證成功即可,和FirstSuccessfulStrategy不同,返回所有Realm身份驗證成功的認證信息;
  • AllSuccessfulStrategy:所有Realm驗證成功才算成功,且返回所有Realm身份驗證成功的認證信息,如果有一個失敗就失敗了。

 

 

 

一、案例

  • 需求:

    假設我們有三個realm:

    myRealm1: 用戶名/密碼為zhang/123時成功,且返回身份/憑據為zhang/123;

    myRealm2: 用戶名/密碼為wang/123時成功,且返回身份/憑據為wang/123;

    myRealm3: 用戶名/密碼為zhang/123時成功,且返回身份/憑據為zhang@163.com/123,和myRealm1不同的是返回時的身份變了;

 

  • pom.xml依賴省略,可查看前幾章
  • 配置shiro.ini文件
[main]
#指定securityManager的authenticator實現  authenticator
=org.apache.shiro.authc.pam.ModularRealmAuthenticator securityManager.authenticator=$authenticator

#指定securityManager.authenticator的authenticationStrategy allSuccessfulStrategy
=org.apache.shiro.authc.pam.FirstSuccessfulStrategy securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy
myRealm1
=realms.MyRealm1 myRealm2=realms.MyRealm2 myRealm3=realms.MyRealm3 securityManager.realms=$myRealm1,$myRealm2,$myRealm3 [users] zhang=123 wang=123
    •   認證策略為FirstSuccessfulStrategy ,只要有一個Realm驗證成功即可,只返回第一個Realm身份驗證成功的認證信息,其他的忽略
  • MyRealm1.java
package realms;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAccount;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class MyRealm1 extends AuthorizingRealm{

    /**
     * 判斷授權的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * 判斷認證的
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String userName=token.getPrincipal().toString();
        String passWord=new String((char[])token.getCredentials());
        
        if(!userName.equals("zhang")) throw new UnknownAccountException("Realm1 用戶名錯誤");
        if(!passWord.equals("123")) throw new IncorrectCredentialsException("Realm1 密碼錯誤");
        
        return new SimpleAccount(userName, passWord, getName());
    }

}
  • MyRealm2.java
package realms;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAccount;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class MyRealm2 extends AuthorizingRealm{
    /**
     * 判斷授權的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * 判斷認證的
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String userName=token.getPrincipal().toString();
        String passWord=new String((char[])token.getCredentials());
        
        if(!userName.equals("wang")) throw new UnknownAccountException("Realm2 用戶名錯誤");
        if(!passWord.equals("123")) throw new IncorrectCredentialsException("Realm2 密碼錯誤");
        
        return new SimpleAccount(userName, passWord, getName());
    }

}
  • MyRealm3.java
package realms;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAccount;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class MyRealm3 extends AuthorizingRealm{
    /**
     * 判斷授權的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * 判斷認證的
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String userName=token.getPrincipal().toString();
        String passWord=new String((char[])token.getCredentials());
        
        if(!userName.equals("zhang")) throw new UnknownAccountException("Realm3 用戶名錯誤");
        if(!passWord.equals("123")) throw new IncorrectCredentialsException("Realm4 密碼錯誤");
        
        return new SimpleAccount("zhang@163.com", passWord, getName());
    }

}
  • 測試
package test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;

public class TestMain {
    public static void main(String[] args) {
        SecurityManager securityManager=new IniSecurityManagerFactory("classpath:shiro.ini").getInstance(); 
        SecurityUtils.setSecurityManager(securityManager);
        
        Subject subject=SecurityUtils.getSubject();
    
        AuthenticationToken token=new UsernamePasswordToken("zhang","123");
        try {
            subject.login(token);
            PrincipalCollection ps=subject.getPrincipals();
            System.out.println(ps.asList());
            
            System.out.println(ps.getRealmNames());
            System.out.println(subject.getPrincipal().toString());
            
        } catch (UnknownAccountException e) {
            System.out.println(e.getMessage());
        }catch(IncorrectCredentialsException e){
            System.out.println(e.getMessage());
        }
        
    }
}

 

  • 結果:

因為是FirstSuccessfulStrategy策略,myRealm1認證成功,所以只返回這個Realm的認證信息,其他的省略。

 

  • 修改shiro.ini,認證策略修改為AtLeastOneSuccessfulStrategy ,其他文件均不變
[main]
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator  
securityManager.authenticator=$authenticator  
atLeastOneSuccessfulStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy securityManager.authenticator.authenticationStrategy=$atLeastOneSuccessfulStrategy  
myRealm1=realms.MyRealm1  
myRealm2=realms.MyRealm2  
myRealm3=realms.MyRealm3  
securityManager.realms=$myRealm1,$myRealm2,$myRealm3  

[users]
zhang=123
wang=123

 

  •  修改shiro.ini,認證策略修改為AllSuccessfulStrategy,其他文件均不變
[main]
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator  
securityManager.authenticator=$authenticator  
atLeastOneSuccessfulStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy  
securityManager.authenticator.authenticationStrategy=$atLeastOneSuccessfulStrategy  
myRealm1=realms.MyRealm1  
myRealm2=realms.MyRealm2  
myRealm3=realms.MyRealm3  
securityManager.realms=$myRealm1,$myRealm2,$myRealm3  

[users]
zhang=123
wang=123

 


免責聲明!

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



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