• (四)自定义多个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

  • 相关阅读:
    if __name__ == 'main': 的作用和原理
    第四篇、Python文件处理
    第二篇*2、Python字符串格式化
    第三篇、Python函数
    第二篇*1、Python基本数据类型
    ping包,支持ip录入
    layui之弹出层--从父窗口传递数据到子窗口
    动态调用WebService
    c# 类的反射实例 (GetType().Invoke().GetMethod().CreateInstance())
    ASP.Net UpdatePanel控件 局部刷新 && 弹出提示信息
  • 原文地址:https://www.cnblogs.com/shyroke/p/7808812.html
Copyright © 2020-2023  润新知