com.github.streamone.shiro.session.RedissonWebSessionManager Maven / Gradle / Ivy
package com.github.streamone.shiro.session;
import org.apache.shiro.session.Session;
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.WebSessionKey;
import org.apache.shiro.web.session.mgt.WebSessionManager;
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 javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
/**
* Web-application capable {@link RedissonSessionManager RedissonSessionManager}.
*
* @author streamone
*/
public class RedissonWebSessionManager extends RedissonSessionManager implements WebSessionManager {
public static final Logger logger = LoggerFactory.getLogger(RedissonWebSessionManager.class);
private Cookie sessionIdCookie;
private boolean sessionIdCookieEnabled;
private boolean sessionIdUrlRewritingEnabled;
public RedissonWebSessionManager() {
Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
cookie.setHttpOnly(true);
this.sessionIdCookie = cookie;
this.sessionIdCookieEnabled = true;
this.sessionIdUrlRewritingEnabled = true;
}
private void storeSessionId(Serializable currentId, HttpServletRequest request, HttpServletResponse response) {
if (currentId == null) {
String msg = "sessionId cannot be null when persisting for subsequent requests.";
throw new IllegalArgumentException(msg);
}
Cookie template = getSessionIdCookie();
Cookie cookie = new SimpleCookie(template);
String idString = currentId.toString();
cookie.setValue(idString);
cookie.saveTo(request, response);
if (logger.isTraceEnabled()) {
logger.trace("Set session ID cookie for session with id {}", idString);
}
}
private void removeSessionIdCookie(HttpServletRequest request, HttpServletResponse response) {
getSessionIdCookie().removeFrom(request, response);
}
private String getSessionIdCookieValue(ServletRequest request, ServletResponse response) {
if (!isSessionIdCookieEnabled()) {
if (logger.isDebugEnabled()) {
logger.debug("Session ID cookie is disabled - session id will not be acquired from a request cookie.");
}
return null;
}
if (!(request instanceof HttpServletRequest)) {
if (logger.isDebugEnabled()) {
logger.debug("Current request is not an HttpServletRequest - cannot get session ID cookie. Returning null.");
}
return null;
}
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);
}
// always set rewrite flag - SHIRO-361
request.setAttribute(ShiroHttpServletRequest.SESSION_ID_URL_REWRITING_ENABLED, isSessionIdUrlRewritingEnabled());
return id;
}
/**
* SHIRO-351
* also see http://cdivilly.wordpress.com/2011/04/22/java-servlets-uri-parameters/
*/
private String getUriPathSegmentParamValue(ServletRequest servletRequest, String paramName) {
if (!(servletRequest instanceof HttpServletRequest)) {
return null;
}
HttpServletRequest request = (HttpServletRequest)servletRequest;
String uri = request.getRequestURI();
if (uri == null) {
return null;
}
int queryStartIndex = uri.indexOf('?');
if (queryStartIndex >= 0) {
//get rid of the query string
uri = uri.substring(0, queryStartIndex);
}
//now check for path segment parameters:
int index = uri.indexOf(';');
if (index < 0) {
//no path segment params - return:
return null;
}
//there are path segment params, let's get the last one that may exist:
final String token = paramName + "=";
//uri now contains only the path segment params
uri = uri.substring(index+1);
//we only care about the last JSESSIONID param:
index = uri.lastIndexOf(token);
if (index < 0) {
//no segment param:
return null;
}
uri = uri.substring(index + token.length());
//strip off any remaining segment params:
index = uri.indexOf(';');
if(index >= 0) {
uri = uri.substring(0, index);
}
//what remains is the value
return uri;
}
private String getSessionIdName() {
String name = this.sessionIdCookie != null ? this.sessionIdCookie.getName() : null;
if (name == null) {
name = ShiroHttpSession.DEFAULT_SESSION_ID_NAME;
}
return name;
}
@Override
protected Session createExposedSession(Session session, SessionContext context) {
if (!WebUtils.isWeb(context)) {
return super.createExposedSession(session, context);
}
return doCreateExposedSession(session, context);
}
@Override
protected Session createExposedSession(Session session, SessionKey key) {
if (!WebUtils.isWeb(key)) {
return super.createExposedSession(session, key);
}
return doCreateExposedSession(session, key);
}
private Session doCreateExposedSession(Session session, Object source) {
ServletRequest request = WebUtils.getRequest(source);
ServletResponse response = WebUtils.getResponse(source);
SessionKey key = new WebSessionKey(session.getId(), request, response);
return new DelegatingSession(this, key);
}
/**
* 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
protected void onStart(Session session, SessionContext context) {
super.onStart(session, context);
if (!WebUtils.isHttp(context)) {
if (logger.isDebugEnabled()) {
logger.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 {
if (logger.isDebugEnabled()) {
logger.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
protected void onStop(Session session, SessionKey key) {
super.onStop(session, key);
if (WebUtils.isHttp(key)) {
HttpServletRequest request = WebUtils.getHttpRequest(key);
HttpServletResponse response = WebUtils.getHttpResponse(key);
if (logger.isDebugEnabled()) {
logger.debug("Session has been stopped (subject logout or explicit stop). Removing session ID cookie.");
}
removeSessionIdCookie(request, response);
} else {
if (logger.isDebugEnabled()) {
logger.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
*/
@Override
public boolean isServletContainerSessions() {
return false;
}
public Cookie getSessionIdCookie() {
return sessionIdCookie;
}
public void setSessionIdCookie(Cookie sessionIdCookie) {
this.sessionIdCookie = sessionIdCookie;
}
public boolean isSessionIdCookieEnabled() {
return sessionIdCookieEnabled;
}
public void setSessionIdCookieEnabled(boolean sessionIdCookieEnabled) {
this.sessionIdCookieEnabled = sessionIdCookieEnabled;
}
public boolean isSessionIdUrlRewritingEnabled() {
return sessionIdUrlRewritingEnabled;
}
public void setSessionIdUrlRewritingEnabled(boolean sessionIdUrlRewritingEnabled) {
this.sessionIdUrlRewritingEnabled = sessionIdUrlRewritingEnabled;
}
}