zoukankan      html  css  js  c++  java
  • 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到线程 否则对下次测试造成影响
        }
  • 相关阅读:
    XML错误信息Referenced file contains errors (http://www.springframework.org/schema/beans/spring-beans-4.0.xsd). For more information, right click on the message in the Problems View ...
    Description Resource Path Location Type Cannot change version of project facet Dynamic Web Module to 2.3.
    maven创建web报错Cannot read lifecycle mapping metadata for artifact org.apache.maven.plugins:maven-compiler-plugin:maven-compiler-plugin:3.5.1:runtime Cause: error in opening zip file
    AJAX跨域
    JavaWeb学习总结(转载)
    JDBC学习笔记
    Java动态代理之JDK实现和CGlib实现
    (转)看懂UML类图
    spring boot配置使用fastjson
    python3下django连接mysql数据库
  • 原文地址:https://www.cnblogs.com/weizhen/p/5971949.html
Copyright © 2011-2022 走看看