禁用cookie情况下,前端传递当前登录人信息给shiro

有个springboot项目,登录和权限采用shiro管理。某天前端开发人员突然说小程序页面里面无法把cookie 传递给后端, 导致服务器获取登录人信息空指针。百度了一圈不知道怎么搞,最后请教了老大,算是解决了。下面把解决方案记下来

  • 前端用问号传参方式传递sessionid
  • 后端重写shiro获取sessionid方法

原来的 shiro配置DefaultWebSessionManager 如下:

    @Bean
    public DefaultWebSessionManager SessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        SimpleCookie simpleCookie = new SimpleCookie("jsid");
        simpleCookie.setPath("/");
        sessionManager.setSessionIdCookie(simpleCookie);
        sessionManager.setSessionDAO(redisSessionDAO());
        return sessionManager;
    }

需要改成自定义DefaultWebSessionManager ,配置如下:

    @Bean
    public DefaultWebSessionManager SessionManager(){
        MyDefaultWebSessionManager sessionManager = new MyDefaultWebSessionManager();
        SimpleCookie simpleCookie = new SimpleCookie("jsid");
        simpleCookie.setPath("/");
        sessionManager.setSessionIdCookie(simpleCookie);
        sessionManager.setSessionDAO(redisSessionDAO());
        return sessionManager;
    }

下面贴上MyDefaultWebSessionManager的代码

 package com.yx.tsenglish.common.shiro;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;

/**
 * 重写获取sessionid逻辑,使得shrio支持通过url维持session,默认使用sessionid名称为mysessionid
 * Created by lcf on 2018/3/26.
 */
public class MyDefaultWebSessionManager extends DefaultWebSessionManager {

    public final static Logger log = LoggerFactory.getLogger(MyDefaultWebSessionManager.class);

    @Override
    public Serializable getSessionId(ServletRequest request, ServletResponse response) {
        String name = this.getSessionIdName();
        String id = request.getParameter("mysessionid"); // this.getUriPathSegmentParamValue(request, "mysessionid");
        log.debug("mysessionid:"+ id);
        if (!StringUtils.isEmpty(id)){
            return id;
        }
        return super.getSessionId(request, response);
    }

    private String getSessionIdName() {
        String name = this.getSessionIdCookie() != null?this.getSessionIdCookie().getName():null;
        if(name == null) {
            name = "JSESSIONID";
        }

        return name;
    }

    private String getSessionIdCookieValue(ServletRequest request, ServletResponse response) {
        if(!this.isSessionIdCookieEnabled()) {
            log.debug("Session ID cookie is disabled - session id will not be acquired from a request cookie.");
            return null;
        } else if(!(request instanceof HttpServletRequest)) {
            log.debug("Current request is not an HttpServletRequest - cannot get session ID cookie.  Returning null.");
            return null;
        } else {
            HttpServletRequest httpRequest = (HttpServletRequest)request;
            return this.getSessionIdCookie().readValue(httpRequest, WebUtils.toHttp(response));
        }
    }

    private String getUriPathSegmentParamValue(ServletRequest servletRequest, String paramName) {
        if(!(servletRequest instanceof HttpServletRequest)) {
            return null;
        } else {
            HttpServletRequest request = (HttpServletRequest)servletRequest;
            String uri = request.getRequestURI();
            if(uri == null) {
                return null;
            } else {
                int queryStartIndex = uri.indexOf(63);
                if(queryStartIndex >= 0) {
                    uri = uri.substring(0, queryStartIndex);
                }

                int index = uri.indexOf(59);
                if(index < 0) {
                    return null;
                } else {
                    String TOKEN = paramName + "=";
                    uri = uri.substring(index + 1);
                    index = uri.lastIndexOf(TOKEN);
                    if(index < 0) {
                        return null;
                    } else {
                        uri = uri.substring(index + TOKEN.length());
                        index = uri.indexOf(59);
                        if(index >= 0) {
                            uri = uri.substring(0, index);
                        }

                        return uri;
                    }
                }
            }
        }
    }

    private Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) {
        String id = this.getSessionIdCookieValue(request, response);
        if(id != null) {
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "cookie");
        } else {
            id = this.getUriPathSegmentParamValue(request, "JSESSIONID");
            if(id == null) {
                String name = this.getSessionIdName();
                id = request.getParameter(name);
                if(id == null) {
                    id = request.getParameter(name.toLowerCase());
                }
            }

            if(id != null) {
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "url");
            }
        }

        if(id != null) {
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
        }

        request.setAttribute(ShiroHttpServletRequest.SESSION_ID_URL_REWRITING_ENABLED, Boolean.valueOf(this.isSessionIdUrlRewritingEnabled()));
        return id;
    }


}

  • 咳咳…下面讲下原理

重写了Serializable getSessionId(ServletRequest request, ServletResponse response)方法,如下图
禁用cookie情况下,前端传递当前登录人信息给shiro_第1张图片
在shiro自身的获取sessionid逻辑之前加入了从request里面获取mysessionid的操作。如果取到是空,继续走shiro自己的逻辑,完美兼容了前端使用cookie的情况。

    @Override
    public Serializable getSessionId(ServletRequest request, ServletResponse response) {
        String name = this.getSessionIdName();
        String id = request.getParameter("mysessionid"); // this.getUriPathSegmentParamValue(request, "mysessionid");
        log.debug("mysessionid:"+ id);
        if (!StringUtils.isEmpty(id)){
            return id;
        }
        return super.getSessionId(request, response);
    }

你可能感兴趣的:(java,web)