shiro web 登陆流程
博客专区 > 4rnold 的博客 > 博客详情
shiro web 登陆流程
4rnold 发表于3个月前
shiro web 登陆流程
  • 发表于 3个月前
  • 阅读 7
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

web.xml 注册filter

<!-- shiro 安全过滤器 -->
<filter>
  <filter-name>shiroFilter</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  <async-supported>true</async-supported>
  <init-param>
    <param-name>targetFilterLifecycle</param-name>
    <param-value>true</param-value>
  </init-param>
</filter>

此处只是配置一个shiroFilterFactory,真正的filter在spring中配置

> ps:这样配置将原本需要配置在web.xml中的filter配置在了spring.xml中

spring-config-shiro.xml

<!-- Shiro的Web过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  <property name="securityManager" ref="securityManager"/>
  <property name="loginUrl" value="/login"/>
  <property name="filters">
    <util:map>
      <!--shiroFilter-->
      <entry key="authc" value-ref="formAuthenticationFilter"/>
      <entry key="sysUser" value-ref="sysUserFilter"/>
    </util:map>
  </property>
  <property name="filterChainDefinitions">
    <value>
      /login = authc
      /logout = logout
      /authenticated = authc
      /** = user,sysUser
    </value>
  </property>
</bean>

其中配置了formAuthenticationFilter

public class FormAuthenticationFilter extends AuthenticatingFilter {}
//MyFormAuthenticationFilter.java
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        if(request.getAttribute(getFailureKeyAttribute()) != null) {
            return true;
        }
        return super.onAccessDenied(request, response, mappedValue);
    }
}

如果之前的filter(验证码filter)错误了,不再继续执行 return true;

之前没错则执行onAccessDenied()。 ShiroFilterFactoryBean 具有拦截filter的能力,filters首先按web.xml配置的顺序执行,执行到ShiroFilterFactoryBean,注册shiro自己的filters,率先执行自己的filters,之后再接着执行web.xml中的filter

在FormAuthenticationFilter.onAccessDenied()

​ -> AuthenticatingFilter.executeLogin()执行登陆。

> AuthenticatingFilter提供create(request,response)

> AccessControlFilter提供getSubject(request,response)

​ -> (DelegatingSubject)subject.login(token)

​ -> DelegatingSubject#securityManager.login() 登陆后对subject中的属性做一些赋值

​ -> AuthenticatingSecurityManager#authenticator.authenticate()

​ -> ModularRealmAuthenticator#realms.getAuthenticationInfo()

最终落到realms上

<bean id="credentialsMatcher" class="com.github.zhangkaitao.shiro.chapter16.credentials.RetryLimitHashedCredentialsMatcher">
        <constructor-arg ref="cacheManager"/>
        <property name="hashAlgorithmName" value="md5"/>
        <property name="hashIterations" value="2"/>
        <property name="storedCredentialsHexEncoded" value="true"/>
    </bean>

    <!-- Realm实现 -->
    <bean id="userRealm" class="com.github.zhangkaitao.shiro.chapter16.realm.UserRealm">
        <property name="credentialsMatcher" ref="credentialsMatcher"/>
        <property name="cachingEnabled" value="false"/>
        <!--<property name="authenticationCachingEnabled" value="true"/>-->
        <!--<property name="authenticationCacheName" value="authenticationCache"/>-->
        <!--<property name="authorizationCachingEnabled" value="true"/>-->
        <!--<property name="authorizationCacheName" value="authorizationCache"/>-->
    </bean>

realm可以配置credentialsMatcher 在哪用?

//ModularRealmAuthenticator.java
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {

        //策略
        AuthenticationStrategy strategy = getAuthenticationStrategy();

        AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);

        if (log.isTraceEnabled()) {
            log.trace("Iterating through {} realms for PAM authentication", realms.size());
        }

        for (Realm realm : realms) {

            aggregate = strategy.beforeAttempt(realm, token, aggregate);

            if (realm.supports(token)) {

                log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm);

                AuthenticationInfo info = null;
                Throwable t = null;
                try {
                    info = realm.getAuthenticationInfo(token);  //试用CredentialsMatcher匹配 
                } catch (Throwable throwable) {
                    t = throwable;
                    if (log.isDebugEnabled()) {
                        String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:";
                        log.debug(msg, t);
                    }
                }

                aggregate = strategy.afterAttempt(realm, token, info, aggregate, t);

            } else {
                log.debug("Realm [{}] does not support token {}.  Skipping realm.", realm, token);
            }
        }

        aggregate = strategy.afterAllAttempts(token, aggregate);

        return aggregate;
    }
标签: shiro
共有 人打赏支持
粉丝 0
博文 22
码字总数 10597
×
4rnold
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: