-
多Realm配置
#聲明一個realm myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1 myRealm2=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm2 #指定securityManager的realms實現 securityManager.realms=$myRealm1,$myRealm2
- securityManager會按照realms指定的順序進行身份認證。此處我們使用顯示指定順序的方式指定了Realm的順序,如果刪除“securityManager.realms=$myRealm1,$myRealm2”,那么securityManager會按照realm聲明的順序進行使用(即無需設置realms屬性,其會自動發現),當我們顯示指定realm后,其他沒有指定realm將被忽略,如“securityManager.realms=$myRealm1”,那么myRealm2不會被自動設置進去
-
1、變量名=全限定類名會自動創建一個類實例
2、變量名.屬性=值 自動調用相應的setter方法進行賦值
3、$變量名 引用之前的一個對象實例
-
Authenticator及AuthenticationStrategy
- 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