博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
shiro+redis多次调用doReadSession方法的解决方案
阅读量:6441 次
发布时间:2019-06-23

本文共 13939 字,大约阅读时间需要 46 分钟。

Web 项目使用shiro,针对这个问题可以重写DefaultWebSessionManager,将缓存数据存放到request中,这样可以保证每次请求(可能会多次调用doReadSession方法)只请求一次redis。

具体扩展如下:

添加MyWebSessionManager.java

package com.xiyinli.web.shiro;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.DefaultSessionManager;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.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;/** * * 自定义WebSessionManager,用于替代DefaultWebSessionManager; * 解决: *      在shiro的一次认证过程中会调用10次左右的 doReadSession,如果使用内存缓存这个问题不大。 *      但是如果使用redis,而且子网络情况不是特别好的情况下这就成为问题了。我简单在我的环境下测试了一下。 *      一次redis请求需要80 ~ 100 ms, 一下来10次,我们一次认证就需要10 * 100 = 1000 ms, 这个就是我们无法接受的了。 * * 大部分代码都是从DefaultWebSessionManager中复制过来的,扩展点在 line:200~212、225~229 * * @author Goma oma1989@yeah.net  2016.03.31 * */public class MyWebSessionManager extends DefaultSessionManager implements WebSessionManager {    private static final Logger log = LoggerFactory.getLogger(DefaultWebSessionManager.class);    private Cookie sessionIdCookie;    private boolean sessionIdCookieEnabled;    public MyWebSessionManager() {        Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);        cookie.setHttpOnly(true); // more secure, protects against XSS attacks        this.sessionIdCookie = cookie;        this.sessionIdCookieEnabled = true;    }    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;    }    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);        log.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()) {            log.debug("Session ID cookie is disabled - session id will not be acquired from a request cookie.");            return null;        }        if (!(request instanceof HttpServletRequest)) {            log.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);        }        return id;    }    // SHIRO-351    // also see    // http://cdivilly.wordpress.com/2011/04/22/java-servlets-uri-parameters/    // since 1.2.2    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);        }        int index = uri.indexOf(';'); // now check for path segment parameters:        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 = 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:            return null;        }        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     */    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);            return null;        }        // ***************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 + "]";            throw new UnknownSessionException(msg);        }        // ***************Add By Goma****************        if (request != null) {            request.setAttribute(sessionId.toString(),s);        }        // ***************Add By Goma****************        return s;    }    //------------------------------------------------------------------------------------------------------------------    // since 1.2.1    private 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)) {            return super.createExposedSession(session, context);        }        ServletRequest request = WebUtils.getRequest(context);        ServletResponse response = WebUtils.getResponse(context);        SessionKey key = new WebSessionKey(session.getId(), request, response);        return new DelegatingSession(this, key);    }    protected Session createExposedSession(Session session, SessionKey key) {        if (!WebUtils.isWeb(key)) {            return super.createExposedSession(session, key);        }        ServletRequest request = WebUtils.getRequest(key);        ServletResponse response = WebUtils.getResponse(key);        SessionKey sessionKey = new WebSessionKey(session.getId(), request, response);        return new 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 protected void 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 protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) { super.onExpiration(s, ese, key); onInvalidation(key); } @Override protected void onInvalidation(Session session, InvalidSessionException ise, SessionKey key) { super.onInvalidation(session, ise, key); onInvalidation(key); } private void 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 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); 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 */ public boolean isServletContainerSessions() { return false; }}

 

spring shiro xml 配置调整:

变更为:

 

转载于:https://www.cnblogs.com/007sx/p/7511310.html

你可能感兴趣的文章
如何用phpmyadmin导入大容量.sql文件,直接使用cmd命令进行导入
查看>>
BZOJ4133 : Answer的排队
查看>>
基于Centos搭建 Mono 开发环境
查看>>
算法题:福尔摩斯的约会
查看>>
Oralce sql (+) 补充
查看>>
hdu 2665 划分树
查看>>
laravel中的plicy授权方法:
查看>>
基于R进行相关性分析--转载
查看>>
常用 cdn
查看>>
tomcat8 管理页面403 Access Denied的解决方法
查看>>
怎样避免应用冷启动
查看>>
把vux中的@font-face为base64格式的字体信息解码成可用的字体文件
查看>>
vue sync
查看>>
CentOS6下OpenLDAP+PhpLdapAdmin基本安装及主从/主主高可用模式部署记录
查看>>
Wix 安装部署教程(十一) ---QuickWix
查看>>
Spring @Value注解问题
查看>>
P1886 滑动窗口
查看>>
实施vertex compression所遇到的各种问题和解决办法
查看>>
ubuntu 12.04 rails server 时候报错 execjs
查看>>
linux下文件压缩与解压操作
查看>>