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