springsession源码分析四之CookieHttpSessionStrategy

CookieHttpSessionStrategy

  1. 源码分析

    public final class CookieHttpSessionStrategy
            implements MultiHttpSessionStrategy, HttpSessionManager {
        private static final String SESSION_IDS_WRITTEN_ATTR = CookieHttpSessionStrategy.class
                .getName().concat(".SESSIONS_WRITTEN_ATTR");
        //默认的别名是0
        static final String DEFAULT_ALIAS = "0";
        //默认的别名参数
        static final String DEFAULT_SESSION_ALIAS_PARAM_NAME = "_s";
    
        private static final Pattern ALIAS_PATTERN = Pattern.compile("^[\\w-]{1,50}$");
    
        private String sessionParam = DEFAULT_SESSION_ALIAS_PARAM_NAME;
    
        private CookieSerializer cookieSerializer = new DefaultCookieSerializer();
    
        public String getRequestedSessionId(HttpServletRequest request) {
            Map<String, String> sessionIds = getSessionIds(request);
            String sessionAlias = getCurrentSessionAlias(request);
            return sessionIds.get(sessionAlias);
        }
    
        public String getCurrentSessionAlias(HttpServletRequest request) {
            if (this.sessionParam == null) {
                return DEFAULT_ALIAS;
            }
            String u = request.getParameter(this.sessionParam);
            if (u == null) {
                return DEFAULT_ALIAS;
            }
            if (!ALIAS_PATTERN.matcher(u).matches()) {
                return DEFAULT_ALIAS;
            }
            return u;
        }
    
        public String getNewSessionAlias(HttpServletRequest request) {
            Set<String> sessionAliases = getSessionIds(request).keySet();
            if (sessionAliases.isEmpty()) {
                return DEFAULT_ALIAS;
            }
            long lastAlias = Long.decode(DEFAULT_ALIAS);
            for (String alias : sessionAliases) {
                long selectedAlias = safeParse(alias);
                if (selectedAlias > lastAlias) {
                    lastAlias = selectedAlias;
                }
            }
            return Long.toHexString(lastAlias + 1);
        }
    
        private long safeParse(String hex) {
            try {
                return Long.decode("0x" + hex);
            }
            catch (NumberFormatException notNumber) {
                return 0;
            }
        }
    
        public void onNewSession(Session session, HttpServletRequest request,
                HttpServletResponse response) {
            Set<String> sessionIdsWritten = getSessionIdsWritten(request);
            if (sessionIdsWritten.contains(session.getId())) {
                return;
            }
            sessionIdsWritten.add(session.getId());
    
            Map<String, String> sessionIds = getSessionIds(request);
            String sessionAlias = getCurrentSessionAlias(request);
            sessionIds.put(sessionAlias, session.getId());
    
            String cookieValue = createSessionCookieValue(sessionIds);
            this.cookieSerializer
                    .writeCookieValue(new CookieValue(request, response, cookieValue));
        }
    
        @SuppressWarnings("unchecked")
        private Set<String> getSessionIdsWritten(HttpServletRequest request) {
            Set<String> sessionsWritten = (Set<String>) request
                    .getAttribute(SESSION_IDS_WRITTEN_ATTR);
            if (sessionsWritten == null) {
                sessionsWritten = new HashSet<String>();
                request.setAttribute(SESSION_IDS_WRITTEN_ATTR, sessionsWritten);
            }
            return sessionsWritten;
        }
    //0 f81d4fae-7dec-11d0-a765-00a0c91e6bf6 1416195761178 8a929cde-2218-4557-8d4e-82a79a37876d
        private String createSessionCookieValue(Map<String, String> sessionIds) {
            if (sessionIds.isEmpty()) {
                return "";
            }
            if (sessionIds.size() == 1 && sessionIds.keySet().contains(DEFAULT_ALIAS)) {
                return sessionIds.values().iterator().next();
            }
    
            StringBuffer buffer = new StringBuffer();
            for (Map.Entry<String, String> entry : sessionIds.entrySet()) {
                String alias = entry.getKey();
                String id = entry.getValue();
    
                buffer.append(alias);
                buffer.append(" ");
                buffer.append(id);
                buffer.append(" ");
            }
            buffer.deleteCharAt(buffer.length() - 1);
            return buffer.toString();
        }
    
        public void onInvalidateSession(HttpServletRequest request,
                HttpServletResponse response) {
            Map<String, String> sessionIds = getSessionIds(request);
            String requestedAlias = getCurrentSessionAlias(request);
            sessionIds.remove(requestedAlias);
    
            String cookieValue = createSessionCookieValue(sessionIds);
            this.cookieSerializer
                    .writeCookieValue(new CookieValue(request, response, cookieValue));
        }
    
        /**
         * Sets the name of the HTTP parameter that is used to specify the session alias. If
         * the value is null, then only a single session is supported per browser.
         *
         * @param sessionAliasParamName the name of the HTTP parameter used to specify the
         * session alias. If null, then ony a single session is supported per browser.
         */
        public void setSessionAliasParamName(String sessionAliasParamName) {
            this.sessionParam = sessionAliasParamName;
        }
    
        /**
         * Sets the {@link CookieSerializer} to be used.
         *
         * @param cookieSerializer the cookieSerializer to set. Cannot be null.
         */
        public void setCookieSerializer(CookieSerializer cookieSerializer) {
            Assert.notNull(cookieSerializer, "cookieSerializer cannot be null");
            this.cookieSerializer = cookieSerializer;
        }
    
        /**
         * Sets the name of the cookie to be used.
         * @param cookieName the name of the cookie to be used
         * @deprecated use {@link #setCookieSerializer(CookieSerializer)}
         */
        @Deprecated
        public void setCookieName(String cookieName) {
            DefaultCookieSerializer serializer = new DefaultCookieSerializer();
            serializer.setCookieName(cookieName);
            this.cookieSerializer = serializer;
        }
    
        /**
        Map<String,String> 中的值是 别名=sessionId,比如0=1a830e1d-1099-47ca-9e3a-023890a6ff7e
        1=be29325d-d78f-4b6a-8fb9-a78fc68947ff
        **/
        public Map<String, String> getSessionIds(HttpServletRequest request) {
            /***
            多个别名
            ***/
            List<String> cookieValues = this.cookieSerializer.readCookieValues(request);
            String sessionCookieValue = cookieValues.isEmpty() ? ""
                    : cookieValues.iterator().next();
            Map<String, String> result = new LinkedHashMap<String, String>();
            StringTokenizer tokens = new StringTokenizer(sessionCookieValue, " ");
            if (tokens.countTokens() == 1) {
                result.put(DEFAULT_ALIAS, tokens.nextToken());
                return result;
            }
            while (tokens.hasMoreTokens()) {
                String alias = tokens.nextToken();
                if (!tokens.hasMoreTokens()) {
                    break;
                }
                String id = tokens.nextToken();
                result.put(alias, id);
            }
            return result;
        }
    
        public HttpServletRequest wrapRequest(HttpServletRequest request,
                HttpServletResponse response) {
            request.setAttribute(HttpSessionManager.class.getName(), this);
            return request;
        }
    
        public HttpServletResponse wrapResponse(HttpServletRequest request,
                HttpServletResponse response) {
            return new MultiSessionHttpServletResponse(response, request);
        }
    
        public String encodeURL(String url, String sessionAlias) {
            String encodedSessionAlias = urlEncode(sessionAlias);
            int queryStart = url.indexOf("?");
            boolean isDefaultAlias = DEFAULT_ALIAS.equals(encodedSessionAlias);
            if (queryStart < 0) {
                return isDefaultAlias ? url
                        : url + "?" + this.sessionParam + "=" + encodedSessionAlias;
            }
            String path = url.substring(0, queryStart);
            String query = url.substring(queryStart + 1, url.length());
            String replacement = isDefaultAlias ? "" : "$1" + encodedSessionAlias;
            query = query.replaceFirst("((^|&)" + this.sessionParam + "=)([^&]+)?",
                    replacement);
            if (!isDefaultAlias && url.endsWith(query)) {
                // no existing alias
                if (!(query.endsWith("&") || query.length() == 0)) {
                    query += "&";
                }
                query += this.sessionParam + "=" + encodedSessionAlias;
            }
    
            return path + "?" + query;
        }
    
        private String urlEncode(String value) {
            try {
                return URLEncoder.encode(value, "UTF-8");
            }
            catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * A {@link CookieHttpSessionStrategy} aware {@link HttpServletResponseWrapper}.
         */
        class MultiSessionHttpServletResponse extends HttpServletResponseWrapper {
            private final HttpServletRequest request;
    
            MultiSessionHttpServletResponse(HttpServletResponse response,
                    HttpServletRequest request) {
                super(response);
                this.request = request;
            }
    
            @Override
            public String encodeRedirectURL(String url) {
                url = super.encodeRedirectURL(url);
                return CookieHttpSessionStrategy.this.encodeURL(url,
                        getCurrentSessionAlias(this.request));
            }
    
            @Override
            public String encodeURL(String url) {
                url = super.encodeURL(url);
    
                String alias = getCurrentSessionAlias(this.request);
                return CookieHttpSessionStrategy.this.encodeURL(url, alias);
                }
            }
    
        }

猜你喜欢

转载自blog.csdn.net/usagoole/article/details/80639815