shiro 获取请求头中的 rememberMe

前言:

  上一篇提到了, 将 sessionId 放到请求头中去, 那rememberMe是否也能够放到请求头中去呢.html

  其实无论是sessionId仍是rememberMe, shiro都会默认往cookie里面放, 那么rememberMe确定也是能够放到请求头中去的.java

  有兴趣的朋友能够去看看 org.apache.shiro.web.mgt.CookieRememberMeManager 的实现. web

  废话很少说了, 直接上实现吧.spring

一. 实现  

import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.AbstractRememberMeManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.SubjectContext;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.subject.WebSubjectContext;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HeaderRememberMeManager extends AbstractRememberMeManager {

    private static final Logger log = LoggerFactory.getLogger(HeaderRememberMeManager.class);

    // header 中 固定使用的 key
    public static final String DEFAULT_REMEMBER_ME_HEADER_NAME = "remember-me";


    @Override
    protected void rememberSerializedIdentity(Subject subject, byte[] serialized) {
        if (!WebUtils.isHttp(subject)) {
            if (log.isDebugEnabled()) {
                String msg = "Subject argument is not an HTTP-aware instance.  This is required to obtain a servlet request and response in order to set the rememberMe cookie. Returning immediately and ignoring rememberMe operation.";
                log.debug(msg);
            }

        } else {
            HttpServletResponse response = WebUtils.getHttpResponse(subject);
            String base64 = Base64.encodeToString(serialized);
            // 设置 rememberMe 信息到 response header 中
            response.setHeader(DEFAULT_REMEMBER_ME_HEADER_NAME, base64);
        }
    }

    private boolean isIdentityRemoved(WebSubjectContext subjectContext) {
        ServletRequest request = subjectContext.resolveServletRequest();
        if (request == null) {
            return false;
        } else {
            Boolean removed = (Boolean) request.getAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY);
            return removed != null && removed;
        }
    }

    @Override
    protected byte[] getRememberedSerializedIdentity(SubjectContext subjectContext) {
        if (!WebUtils.isHttp(subjectContext)) {
            if (log.isDebugEnabled()) {
                String msg = "SubjectContext argument is not an HTTP-aware instance.  This is required to obtain a servlet request and response in order to retrieve the rememberMe cookie. Returning immediately and ignoring rememberMe operation.";
                log.debug(msg);
            }

            return null;
        } else {
            WebSubjectContext wsc = (WebSubjectContext) subjectContext;
            if (this.isIdentityRemoved(wsc)) {
                return null;
            } else {
                HttpServletRequest request = WebUtils.getHttpRequest(wsc);
                // 在request header 中获取 rememberMe信息
                String base64 = request.getHeader(DEFAULT_REMEMBER_ME_HEADER_NAME);
                if ("deleteMe".equals(base64)) {
                    return null;
                } else if (base64 != null) {
                    base64 = this.ensurePadding(base64);
                    if (log.isTraceEnabled()) {
                        log.trace("Acquired Base64 encoded identity [" + base64 + "]");
                    }

                    byte[] decoded = Base64.decode(base64);
                    if (log.isTraceEnabled()) {
                        log.trace("Base64 decoded byte array length: " + (decoded != null ? decoded.length : 0) + " bytes.");
                    }

                    return decoded;
                } else {
                    return null;
                }
            }
        }
    }

    private String ensurePadding(String base64) {
        int length = base64.length();
        if (length % 4 != 0) {
            StringBuilder sb = new StringBuilder(base64);

            for (int i = 0; i < length % 4; ++i) {
                sb.append('=');
            }

            base64 = sb.toString();
        }

        return base64;
    }

    @Override
    protected void forgetIdentity(Subject subject) {
        if (WebUtils.isHttp(subject)) {
            HttpServletRequest request = WebUtils.getHttpRequest(subject);
            HttpServletResponse response = WebUtils.getHttpResponse(subject);
            this.forgetIdentity(request, response);
        }

    }

    @Override
    public void forgetIdentity(SubjectContext subjectContext) {
        if (WebUtils.isHttp(subjectContext)) {
            HttpServletRequest request = WebUtils.getHttpRequest(subjectContext);
            HttpServletResponse response = WebUtils.getHttpResponse(subjectContext);
            this.forgetIdentity(request, response);
        }
    }

    private void forgetIdentity(HttpServletRequest request, HttpServletResponse response) {
        //设置删除标示
        response.setHeader(DEFAULT_REMEMBER_ME_HEADER_NAME, "deleteMe");
    }
}

 

二. 配置

  <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <property name="hashAlgorithmName" value="MD5"/>
        <property name="hashIterations" value="1"/>
        <property name="storedCredentialsHexEncoded" value="true"/>
    </bean>

    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"/>

    <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"/>

    <bean id="rememberMeManager" class="web.shiro.headtoken.HeaderRememberMeManager">
        <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>
       <!-- <property name="cookie" ref="rememberMeCookie" />-->
    </bean>

    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg value="rememberMe"/>
        <property name="httpOnly" value="true"/>
        <property name="maxAge" value="2592000"/><!-- 30天 -->
    </bean>

    <bean id="sessionManager" class="web.shiro.headtoken.DefaultHeaderSessionManager">
        <property name="sessionDAO" ref="sessionDAO"/>
       <!-- <property name="sessionIdCookie" ref="sessionIdCookie"/>-->
        <property name="globalSessionTimeout" value="3600000"/>
        <property name="sessionValidationInterval" value="3600000"/>
    </bean>

    <bean id="shiroRealm" class="web.shiro.ShiroRealm">
        <property name="credentialsMatcher" ref="credentialsMatcher"/>
        <property name="authenticationCachingEnabled" value="true"/>
        <property name="authenticationCacheName" value="authenticationCache"/>
        <property name="authorizationCachingEnabled" value="true"/>
        <property name="authorizationCacheName" value="authorizationCache"/>
    </bean>

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="sessionManager" ref="sessionManager"/>
        <property name="realm" ref="shiroRealm"/>
        <property name="cacheManager" ref="cacheManager"/>
        <!-- 定义RememberMe的管理器 -->
        <property name="rememberMeManager" ref="rememberMeManager"/>
    </bean>

    <bean name="loginFilter" class="web.shiro.filter.JsonAuthLoginFilter" />
    
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="loginUrl" value="${shiro.loginUrl}"/>
        <property name="filters">
            <map>
                <entry key="login" value-ref="loginFilter" />
            </map>
        </property>
        <property name="filterChainDefinitions">
            <value>
                /logout=logout
                /user/retrievePwd = anon
                /user/signOut = anon
                /user/loginGet = anon
                /swagger-ui.html = anon
                /swagger-resources = anon
                /swagger-resources/** = anon
                /v2/api-docs = anon
                /webjars/** = anon
                /webjars/springfox-swagger-ui/** = anon
                /user/login = anon
                /user/register = anon
                /** = login
            </value>
        </property>
    </bean>

    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor"/>

    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

 

三. 测试方法

1. 经过浏览器登陆, 获取到rememberMeapache

2. 经过postman, 访问接口api

 这里其实有个问题, 之前这里用cookie的时候, 还能有个cookie的过时时间影响, 好比cookie只保持30天, 那么过了30天以后, 这个cookie不能再使用了, rememberMe就不能使用了. 浏览器

 可是在这里, 却没有这个功能了, 若是想把这个功能加上去, 就必须重写更多的方法来实现这个功能. cookie

  好比, 咱们能够将过时时间, 加入到 rememberMe中去, 固然, 必需要通过编码才行, 不能太明显. 这样, 来保证rememberMe的过时后, 须要再去登陆.session

相关文章
相关标签/搜索