• 32、shiro 框架入门三


    1、AuthenticationStrategy实现

    //在所有Realm验证之前调用
    AuthenticationInfo beforeAllAttempts(
    Collection<? extends Realm> realms, AuthenticationToken token) 
    throws AuthenticationException;
    //在每个Realm之前调用
    AuthenticationInfo beforeAttempt(
    Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) 
    throws AuthenticationException;
    //在每个Realm之后调用
    AuthenticationInfo afterAttempt(
    Realm realm, AuthenticationToken token, 
    AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t)
    throws AuthenticationException;
    //在所有Realm之后调用
    AuthenticationInfo afterAllAttempts(
    AuthenticationToken token, AuthenticationInfo aggregate) 
    throws AuthenticationException;

          因为每个AuthenticationStrategy实例都是无状态的,所有每次都通过接口将相应的认证信息传入下一次流程;通过如上接口可以进行如合并/返回第一个验证成功的认证信息。

      自定义实现时一般继承org.apache.shiro.authc.pam.AbstractAuthenticationStrategy

     下边这个OnlyOneAuthenticatorStrategy只允许一个成功的验证信息,进行返回,否则会报AuthenticationException,只返回第一个验证成功的Realm的认证信息

    public class OnlyOneAuthenticatorStrategy extends AbstractAuthenticationStrategy {
    
        @Override
        public AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException {
            return new SimpleAuthenticationInfo();//返回一个权限的认证信息,在进行验证之前返回的信息,不对权限信息进行处理
        }
    
        @Override
        public AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
            return aggregate;//返回之前合并的,在进行验证之前返回的信息,不对权限信息进行处理
      }
      @Override
      
    public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
         AuthenticationInfo info;
         if (singleRealmInfo == null)
         {
           info
    = aggregateInfo;
         }
    else
        {
          
    if (aggregateInfo == null) {
           info
    = singleRealmInfo;
         }
    else {
           info
    = merge(singleRealmInfo, aggregateInfo);
           if(info.getPrincipals().getRealmNames().size() > 1)
           {
             System.out.println(info.getPrincipals().getRealmNames());
            
    throw new AuthenticationException("Authentication token of type [" + token.getClass() + "] " +
            "could not be authenticated by any configured realms. Please ensure that only one realm can " +
             "authenticate these tokens.");
           }
         }
       }
        
    return info;
    }
    @Override
    public AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException
    {
        return aggregate;
    }

    }

    这里的shiro主要就是将多个AuthenticationToken信息合并在一起,

    2、AbstractAuthenticationStrategy中的merge方法,主要就是先检查该

    AuthenticationInfo 是不是可以merge的类型,如果是则将其转换为可以merge的类型,然后调用merge方法
    /**
         * Merges the specified <code>info</code> argument into the <code>aggregate</code> argument and then returns an
         * aggregate for continued use throughout the login process.
         * <p/>
         * This implementation merely checks to see if the specified <code>aggregate</code> argument is an instance of
         * {@link org.apache.shiro.authc.MergableAuthenticationInfo MergableAuthenticationInfo}, and if so, calls
         * <code>aggregate.merge(info)</code>  If it is <em>not</em> an instance of
         * <code>MergableAuthenticationInfo</code>, an {@link IllegalArgumentException IllegalArgumentException} is thrown.
         * Can be overridden by subclasses for custom merging behavior if implementing the
         * {@link org.apache.shiro.authc.MergableAuthenticationInfo MergableAuthenticationInfo} is not desired for some reason.
         */
        protected AuthenticationInfo merge(AuthenticationInfo info, AuthenticationInfo aggregate) {
            if( aggregate instanceof MergableAuthenticationInfo ) {
                ((MergableAuthenticationInfo)aggregate).merge(info);
                return aggregate;
            } else {
                throw new IllegalArgumentException( "Attempt to merge authentication info from multiple realms, but aggregate " +
                          "AuthenticationInfo is not of type MergableAuthenticationInfo." );
            }
        }

    可以进行多个AuthenticationInfo信息进行merge的功能如下所示,返回所有验证成功的Realm的认证信息

    public class AtLeastTwoAuthenticatorStrategy extends AbstractAuthenticationStrategy {
    
        @Override
        public AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException {
            return new SimpleAuthenticationInfo();//返回一个权限的认证信息
        }
    
        @Override
        public AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
            return aggregate;//返回之前合并的
        }
    
        @Override
        public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
            AuthenticationInfo info;
            if (singleRealmInfo == null) {
                info = aggregateInfo;
            } else {
                if (aggregateInfo == null) {
                    info = singleRealmInfo;
                } else {
                    info = merge(singleRealmInfo, aggregateInfo);
                }
            }
    
            return info;
        }
    
        @Override
        public AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
            if (aggregate == null || CollectionUtils.isEmpty(aggregate.getPrincipals()) || aggregate.getPrincipals().getRealmNames().size() < 2) {
                throw new AuthenticationException("Authentication token of type [" + token.getClass() + "] " +
                        "could not be authenticated by any configured realms.  Please ensure that at least two realm can " +
                        "authenticate these tokens.");
            }
    
            return aggregate;
        }

    3、对于Subject线程进行解绑

    @After
        public void tearDown() throws Exception {
            ThreadContext.unbindSubject();//退出时请解除绑定Subject到线程 否则对下次测试造成影响
        }
  • 相关阅读:
    CSS3 Flex布局整理(二)-容器属性
    CSS3 Flex布局整理(一)
    .Net Core中文编码问题整理
    Karma:1. 集成 Karma 和 Jasmine 进行单元测试
    Protractor
    翻译: TypeScript 1.8 Beta 发布
    webpack 插件: html-webpack-plugin
    How I came to find Linux
    翻译:Angular 2
    在 Angular 中实现搜索关键字高亮
  • 原文地址:https://www.cnblogs.com/weizhen/p/5971949.html
Copyright © 2020-2023  润新知