package com.se.common.redis.shiro;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.ExpiredSessionException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.DelegatingSession;
import org.apache.shiro.session.mgt.SessionContext;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.servlet.ShiroHttpSession;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.WebSessionKey;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
/**
* @author yuduojia
* @date 2018/9/27 10:54
*/
@Component
publicclass StatelessSessionManager extends DefaultWebSessionManager {
publicfinalstatic String TOKEN_NAME = "TOKEN";
publicfinalstatic String HEADER_TOKEN_NAME = "token";
publicfinalstatic Logger LOG = LoggerFactory.getLogger(StatelessSessionManager.class);
privatestaticfinal String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
@Override
protected Serializable getSessionId(ServletRequest request, ServletResponse response){
String id = WebUtils.toHttp(request).getParameter(HEADER_TOKEN_NAME);
if(StringUtils.isEmpty(id)){
returnsuper.getSessionId(request, response);
}else{
if (WebUtils.isTrue(request, "_cookie")){
HttpServletRequest rq = (HttpServletRequest)request;
HttpServletResponse rs = (HttpServletResponse)response;
Cookie template = getSessionIdCookie();
Cookie cookie = new SimpleCookie(template);
cookie.setValue(id);
cookie.saveTo(rq, rs);
}
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,REFERENCED_SESSION_ID_SOURCE);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID,id);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID,Boolean.TRUE);
return id;
}
}
privatestaticfinal Logger log = LoggerFactory.getLogger(DefaultWebSessionManager.class);
private Cookie sessionIdCookie;
privateboolean sessionIdCookieEnabled;
public StatelessSessionManager() {
Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
cookie.setHttpOnly(true); // more secure, protects against XSS attacksthis.sessionIdCookie = cookie;
this.sessionIdCookieEnabled = true;
}
public Cookie getSessionIdCookie() {
return sessionIdCookie;
}
publicvoid setSessionIdCookie(Cookie sessionIdCookie) {
this.sessionIdCookie = sessionIdCookie;
}
publicboolean isSessionIdCookieEnabled() {
return sessionIdCookieEnabled;
}
publicvoid setSessionIdCookieEnabled(boolean sessionIdCookieEnabled) {
this.sessionIdCookieEnabled = sessionIdCookieEnabled;
}
privatevoid storeSessionId(Serializable currentId, HttpServletRequest request, HttpServletResponse response) {
if (currentId == null) {
String msg = "sessionId cannot be null when persisting for subsequent requests.";
thrownew IllegalArgumentException(msg);
}
Cookie template = getSessionIdCookie();
Cookie cookie = new SimpleCookie(template);
String idString = currentId.toString();
cookie.setValue(idString);
cookie.saveTo(request, response);
log.trace("Set session ID cookie for session with id {}", idString);
}
privatevoid removeSessionIdCookie(HttpServletRequest request, HttpServletResponse response) {
getSessionIdCookie().removeFrom(request, response);
}
private String getSessionIdCookieValue(ServletRequest request, ServletResponse response) {
if (!isSessionIdCookieEnabled()) {
log.debug("Session ID cookie is disabled - session id will not be acquired from a request cookie.");
returnnull;
}
if (!(request instanceof HttpServletRequest)) {
log.debug("Current request is not an HttpServletRequest - cannot get session ID cookie. Returning null.");
returnnull;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
return getSessionIdCookie().readValue(httpRequest, WebUtils.toHttp(response));
}
private Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) {
String id = getSessionIdCookieValue(request, response);
if (id != null) {
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
} else {
// not in a cookie, or cookie is disabled - try the request URI as a
// fallback (i.e. due to URL rewriting):
// try the URI path segment parameters first:
id = getUriPathSegmentParamValue(request, ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
if (id == null) {
// not a URI path segment parameter, try the query parameters:
String name = getSessionIdName();
id = request.getParameter(name);
if (id == null) {
// try lowercase:
id = request.getParameter(name.toLowerCase());
}
}
if (id != null) {
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
ShiroHttpServletRequest.URL_SESSION_ID_SOURCE);
}
}
if (id != null) {
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
// automatically mark it valid here. If it is invalid, the
// onUnknownSession method below will be invoked and we'll remove
// the attribute at that time. request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
}
return id;
}
// SHIRO-351
// also see
//http://cdivilly.wordpress.com/2011/04/22/java-servlets-uri-parameters/// since 1.2.2private String getUriPathSegmentParamValue(ServletRequest servletRequest, String paramName) {
if (!(servletRequest instanceof HttpServletRequest)) {
returnnull;
}
HttpServletRequest request = (HttpServletRequest) servletRequest;
String uri = request.getRequestURI();
if (uri == null) {
returnnull;
}
int queryStartIndex = uri.indexOf('?');
if (queryStartIndex >= 0) { // get rid of the query string
uri = uri.substring(0, queryStartIndex);
}
int index = uri.indexOf(';'); // now check for path segment parameters:if (index < 0) {
// no path segment params - return:returnnull;
}
// there are path segment params, let's get the last one that may exist:final String TOKEN = paramName + "=";
uri = uri.substring(index + 1); // uri now contains only the path
// segment params
// we only care about the last JSESSIONID param:
index = uri.lastIndexOf(TOKEN);
if (index < 0) {
// no segment param:returnnull;
}
uri = uri.substring(index + TOKEN.length());
index = uri.indexOf(';'); // strip off any remaining segment params:if (index >= 0) {
uri = uri.substring(0, index);
}
return uri; // what remains is the value }
//------------------------------------------------------------------------------------------------------------------/**
* Modify By Goma
*/
@Override
protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
Serializable sessionId = getSessionId(sessionKey);
if (sessionId == null) {
log.debug("Unable to resolve session ID from SessionKey [{}]. Returning null to indicate a "
+ "session could not be found.", sessionKey);
returnnull;
}
// ***************Add By Goma****************
ServletRequest request = null;
if (sessionKey instanceof WebSessionKey) {
request = ((WebSessionKey) sessionKey).getServletRequest();
}
if (request != null) {
Object s = request.getAttribute(sessionId.toString());
if (s != null) {
return (Session) s;
}
}
// ***************Add By Goma****************
Session s = retrieveSessionFromDataSource(sessionId);
if (s == null) {
// session ID was provided, meaning one is expected to be found, but
// we couldn't find one:
String msg = "Could not find session with ID [" + sessionId + "]";
thrownew UnknownSessionException(msg);
}
// ***************Add By Goma****************if (request != null) {
request.setAttribute(sessionId.toString(),s);
}
// ***************Add By Goma****************return s;
}
//------------------------------------------------------------------------------------------------------------------
// since 1.2.1private String getSessionIdName() {
String name = this.sessionIdCookie != null ? this.sessionIdCookie.getName() : null;
if (name == null) {
name = ShiroHttpSession.DEFAULT_SESSION_ID_NAME;
}
return name;
}
protected Session createExposedSession(Session session, SessionContext context) {
if (!WebUtils.isWeb(context)) {
returnsuper.createExposedSession(session, context);
}
ServletRequest request = WebUtils.getRequest(context);
ServletResponse response = WebUtils.getResponse(context);
SessionKey key = new WebSessionKey(session.getId(), request, response);
returnnew DelegatingSession(this, key);
}
protected Session createExposedSession(Session session, SessionKey key) {
if (!WebUtils.isWeb(key)) {
returnsuper.createExposedSession(session, key);
}
ServletRequest request = WebUtils.getRequest(key);
ServletResponse response = WebUtils.getResponse(key);
SessionKey sessionKey = new WebSessionKey(session.getId(), request, response);
returnnew DelegatingSession(this, sessionKey);
}
/**
* Stores the Session's ID, usually as a Cookie, to associate with future
* requests.
*
* @param session
* the session that was just {@link #createSession created}.
*/
@Override
protectedvoid onStart(Session session, SessionContext context) {
super.onStart(session, context);
if (!WebUtils.isHttp(context)) {
log.debug("SessionContext argument is not HTTP compatible or does not have an HTTP request/response "
+ "pair. No session ID cookie will be set.");
return;
}
HttpServletRequest request = WebUtils.getHttpRequest(context);
HttpServletResponse response = WebUtils.getHttpResponse(context);
if (isSessionIdCookieEnabled()) {
Serializable sessionId = session.getId();
storeSessionId(sessionId, request, response);
} else {
log.debug("Session ID cookie is disabled. No cookie has been set for new session with id {}",
session.getId());
}
request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
}
@Override
public Serializable getSessionId(SessionKey key) {
Serializable id = super.getSessionId(key);
if (id == null && WebUtils.isWeb(key)) {
ServletRequest request = WebUtils.getRequest(key);
ServletResponse response = WebUtils.getResponse(key);
id = getSessionId(request, response);
}
return id;
}
/*protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
return getReferencedSessionId(request, response);
}*/
@Override
protectedvoid onExpiration(Session s, ExpiredSessionException ese, SessionKey key) {
super.onExpiration(s, ese, key);
onInvalidation(key);
}
@Override
protectedvoid onInvalidation(Session session, InvalidSessionException ise, SessionKey key) {
super.onInvalidation(session, ise, key);
onInvalidation(key);
}
privatevoid onInvalidation(SessionKey key) {
ServletRequest request = WebUtils.getRequest(key);
if (request != null) {
request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID);
}
if (WebUtils.isHttp(key)) {
log.debug("Referenced session was invalid. Removing session ID cookie.");
removeSessionIdCookie(WebUtils.getHttpRequest(key), WebUtils.getHttpResponse(key));
} else {
log.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response "
+ "pair. Session ID cookie will not be removed due to invalidated session.");
}
}
@Override
protectedvoid onStop(Session session, SessionKey key) {
super.onStop(session, key);
if (WebUtils.isHttp(key)) {
HttpServletRequest request = WebUtils.getHttpRequest(key);
HttpServletResponse response = WebUtils.getHttpResponse(key);
log.debug("Session has been stopped (subject logout or explicit stop). Removing session ID cookie.");
removeSessionIdCookie(request, response);
} else {
log.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response "
+ "pair. Session ID cookie will not be removed due to stopped session.");
}
}
/**
* This is a native session manager implementation, so this method returns
* {@code false} always.
*
* @return {@code false} always
* @since 1.2
*/publicboolean isServletContainerSessions() {
returnfalse;
}
}
DefaultWebSessionManager类 介绍 不是项目用到的
DefaultWebSessionManager类
1.数据属性
private Cookie sessionIdCookie;//sessionId cookieprivateboolean sessionIdCookieEnabled;//session是否可以被保存到cookie中
2.构造方法
public DefaultWebSessionManager() {
Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
cookie.setHttpOnly(true); //more secure, protects against XSS attacksthis.sessionIdCookie = cookie;
this.sessionIdCookieEnabled = true;
}
3.获取sessionIdCookie
public Cookie getSessionIdCookie() {
return sessionIdCookie;
}
4.设置sessionIdCookie
publicvoid setSessionIdCookie(Cookie sessionIdCookie) {
this.sessionIdCookie = sessionIdCookie;
}
5.是否将sessionId存储到cookie中
publicboolean isSessionIdCookieEnabled() {
return sessionIdCookieEnabled;
}
6.设置是否将sessionId存储到cookie中
publicvoid setSessionIdCookieEnabled(boolean sessionIdCookieEnabled) {
this.sessionIdCookieEnabled = sessionIdCookieEnabled;
}
7.存储sessionId到cookie中
privatevoid storeSessionId(Serializable currentId, HttpServletRequest request, HttpServletResponse response) {
if (currentId == null) {
String msg = "sessionId cannot be null when persisting for subsequent requests.";
thrownew IllegalArgumentException(msg);
}
Cookie template = getSessionIdCookie();
Cookie cookie = new SimpleCookie(template);
String idString = currentId.toString();
cookie.setValue(idString);
cookie.saveTo(request, response);
log.trace("Set session ID cookie for session with id {}", idString);
}
8.从cookie中移除session信息
privatevoid removeSessionIdCookie(HttpServletRequest request, HttpServletResponse response) {
getSessionIdCookie().removeFrom(request, response);
}
9.从cookie中读取sessionId信息
private String getSessionIdCookieValue(ServletRequest request, ServletResponse response) {
if (!isSessionIdCookieEnabled()) {
log.debug("Session ID cookie is disabled - session id will not be acquired from a request cookie.");
returnnull;
}
if (!(request instanceof HttpServletRequest)) {
log.debug("Current request is not an HttpServletRequest - cannot get session ID cookie. Returning null.");
returnnull;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
return getSessionIdCookie().readValue(httpRequest, WebUtils.toHttp(response));
}
10.检测sessionId关联源(如果可以从cookie中获取sessionId,则在request中设置sessionId的关联源为cookie;如果不可以读取,则从request访问路径中获取,如果不存在,则从request的parameter中获取,如果从request的访问路径中或者parameter中获取到的不为空,则设置关联源为url;并在将sessionId和合法信息存储到request中)
private Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) {
String id = getSessionIdCookieValue(request, response);
if (id != null) {
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
} else {
//not in a cookie, or cookie is disabled - try the request URI as a fallback (i.e. due to URL rewriting):
//try the URI path segment parameters first:
id = getUriPathSegmentParamValue(request, ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
if (id == null) {
//not a URI path segment parameter, try the query parameters:
String name = getSessionIdName();
id = request.getParameter(name);
if (id == null) {
//try lowercase:
id = request.getParameter(name.toLowerCase());
}
}
if (id != null) {
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
ShiroHttpServletRequest.URL_SESSION_ID_SOURCE);
}
}
if (id != null) {
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
//automatically mark it valid here. If it is invalid, the
//onUnknownSession method below will be invoked and we'll remove the attribute at that time. request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
}
return id;
}
11.从request路径中获取sessionId信息
private String getUriPathSegmentParamValue(ServletRequest servletRequest, String paramName) {
if (!(servletRequest instanceof HttpServletRequest)) {
returnnull;
}
HttpServletRequest request = (HttpServletRequest)servletRequest;
String uri = request.getRequestURI();
if (uri == null) {
returnnull;
}
int queryStartIndex = uri.indexOf('?');
if (queryStartIndex >= 0) { //get rid of the query string
uri = uri.substring(0, queryStartIndex);
}
int index = uri.indexOf(';'); //now check for path segment parameters:if (index < 0) {
//no path segment params - return:returnnull;
}
//there are path segment params, let's get the last one that may exist:final String TOKEN = paramName + "=";
uri = uri.substring(index+1); //uri now contains only the path segment params
//we only care about the last JSESSIONID param:
index = uri.lastIndexOf(TOKEN);
if (index < 0) {
//no segment param:returnnull;
}
uri = uri.substring(index + TOKEN.length());
index = uri.indexOf(';'); //strip off any remaining segment params:if(index >= 0) {
uri = uri.substring(0, index);
}
return uri; //what remains is the value }
12.获取sessionId名字
private String getSessionIdName() {
String name = this.sessionIdCookie != null ? this.sessionIdCookie.getName() : null;
if (name == null) {
name = ShiroHttpSession.DEFAULT_SESSION_ID_NAME;
}
return name;
}
13.创建session信息(它覆盖了AbstractNativeSessionManager接口的方法)
protected Session createExposedSession(Session session, SessionContext context) {
if (!WebUtils.isWeb(context)) {
returnsuper.createExposedSession(session, context);
}
ServletRequest request = WebUtils.getRequest(context);
ServletResponse response = WebUtils.getResponse(context);
SessionKey key = new WebSessionKey(session.getId(), request, response);
returnnew DelegatingSession(this, key);
}
14.创建session信息(它覆盖了AbstractNativeSessionManager抽象类的方法)
protected Session createExposedSession(Session session, SessionKey key) {
if (!WebUtils.isWeb(key)) {
returnsuper.createExposedSession(session, key);
}
ServletRequest request = WebUtils.getRequest(key);
ServletResponse response = WebUtils.getResponse(key);
SessionKey sessionKey = new WebSessionKey(session.getId(), request, response);
returnnew DelegatingSession(this, sessionKey);
}
15.启动session(将session存储到cookie中,并将cookie中移除session源,设置session是新的,它覆盖了AbstractNativeSessionManager抽象类的方法)
protectedvoid onStart(Session session, SessionContext context) {
super.onStart(session, context);
if (!WebUtils.isHttp(context)) {
log.debug("SessionContext argument is not HTTP compatible or does not have an HTTP request/response " +"pair. No session ID cookie will be set.");
return;
}
HttpServletRequest request = WebUtils.getHttpRequest(context);
HttpServletResponse response = WebUtils.getHttpResponse(context);
if (isSessionIdCookieEnabled()) {
Serializable sessionId = session.getId();
storeSessionId(sessionId, request, response);
} else {
log.debug("Session ID cookie is disabled. No cookie has been set for new session with id {}", session.getId());
}
request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
}
16.获取sessionId(先从sessionKey中获取,如果没有,则从cookie中获取,如果在没有,则从request请求路径或者parameter中获取,它覆盖了DefaultSessionManager类的方法)
public Serializable getSessionId(SessionKey key) {
Serializable id = super.getSessionId(key);
if (id == null && WebUtils.isWeb(key)) {
ServletRequest request = WebUtils.getRequest(key);
ServletResponse response = WebUtils.getResponse(key);
id = getSessionId(request, response);
}
return id;
}
17.从cookie或者request中获取sessionId信息
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
return getReferencedSessionId(request, response);
}
18.session过期(它覆盖了AbstractValidatingSessionManager抽象类的方法)
protectedvoid onExpiration(Session s, ExpiredSessionException ese, SessionKey key) {
super.onExpiration(s, ese, key);
onInvalidation(key);
}
19.session失效(它覆盖了AbstractValidatingSessionManager抽象类的方法)
protectedvoid onInvalidation(Session session, InvalidSessionException ise, SessionKey key) {
super.onInvalidation(session, ise, key);
onInvalidation(key);
}
20.移除request中属性(sessionId是合法的和从cookie中移除sessionId)
privatevoid onInvalidation(SessionKey key) {
ServletRequest request = WebUtils.getRequest(key);
if (request != null) {
request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID);
}
if (WebUtils.isHttp(key)) {
log.debug("Referenced session was invalid. Removing session ID cookie.");
removeSessionIdCookie(WebUtils.getHttpRequest(key), WebUtils.getHttpResponse(key));
} else {
log.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response " +"pair. Session ID cookie will not be removed due to invalidated session.");
}
}
21.暂停session(设置session的暂停时间,并从cookie中移除session,它实现了AbstractNativeSessionManager抽象类的方法)
protectedvoid onStop(Session session, SessionKey key) {
super.onStop(session, key);
if (WebUtils.isHttp(key)) {
HttpServletRequest request = WebUtils.getHttpRequest(key);
HttpServletResponse response = WebUtils.getHttpResponse(key);
log.debug("Session has been stopped (subject logout or explicit stop). Removing session ID cookie.");
removeSessionIdCookie(request, response);
} else {
log.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response " +"pair. Session ID cookie will not be removed due to stopped session.");
}
}
22.如果session被servlet container管理则返回true;如果被shiro管理,则返回false
publicboolean isServletContainerSessions() {
returnfalse;
}