`
halloffame
  • 浏览: 54750 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

从tomcat 8源码看session cookie maxage的配置

阅读更多

最近有兴趣看了tomcat 8源码对session cookie的处理,才发现web.xml支持对session cookie配置maxage,如果不配置默认就是-1,-1表示这个cookie在当前浏览器窗口有效,存放在内存中而不是硬盘,关掉当前浏览器窗口的话,这个cookie失效,会话结束;如果设置了maxage(不等于-1),则存放到硬盘。

 

部分源码:

org/apache/catalina/connector/Request.java

createSessionCookie:创建一个sessionCookie,并添加到response 

protected Session doGetSession(boolean create) {
	.................
	.................
	.................
	// Creating a new session cookie based on that session
	if (session != null
			&& context.getServletContext()
					.getEffectiveSessionTrackingModes()
					.contains(SessionTrackingMode.COOKIE)) {
		Cookie cookie =
			ApplicationSessionCookieConfig.createSessionCookie(
					context, session.getIdInternal(), isSecure());

		response.addSessionCookieInternal(cookie);
	}
	.................
	.................
	.................
}

 

 

org/apache/catalina/core/ApplicationSessionCookieConfig.java

private int maxAge = -1; //默认等于-1

scc.getMaxAge():从scc里取得maxAge 

package org.apache.catalina.core;

import javax.servlet.SessionCookieConfig;
import javax.servlet.http.Cookie;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.util.SessionConfig;
import org.apache.tomcat.util.res.StringManager;

public class ApplicationSessionCookieConfig implements SessionCookieConfig {

    /**
     * The string manager for this package.
     */
    private static final StringManager sm = StringManager
            .getManager(Constants.Package);

    private boolean httpOnly;
    private boolean secure;
    private int maxAge = -1;
    private String comment;
    private String domain;
    private String name;
    private String path;
    private StandardContext context;
	.................
	.................
	.................
	@Override
	public int getMaxAge() {
		return maxAge;
	}
	.................
	.................
	.................
	/**
	 * Creates a new session cookie for the given session ID
	 *
	 * @param context     The Context for the web application
	 * @param sessionId   The ID of the session for which the cookie will be
	 *                    created
	 * @param secure      Should session cookie be configured as secure
	 * @return the cookie for the session
	 */
	public static Cookie createSessionCookie(Context context,
			String sessionId, boolean secure) {

		SessionCookieConfig scc =
			context.getServletContext().getSessionCookieConfig();

		// NOTE: The priority order for session cookie configuration is:
		//       1. Context level configuration
		//       2. Values from SessionCookieConfig
		//       3. Defaults

		Cookie cookie = new Cookie(
				SessionConfig.getSessionCookieName(context), sessionId);

		// Just apply the defaults.
		cookie.setMaxAge(scc.getMaxAge());
		cookie.setComment(scc.getComment());
		.................
		.................
		.................
	}
}

 

 

 org/apache/catalina/startup/ContextConfig.java

 scc.setMaxAge:读取web.xml里面session-config的max-age并set到scc

package org.apache.catalina.startup;  
.................  
.................  
.................  
/** 
 * Startup event listener for a <b>Context</b> that configures the properties 
 * of that Context, and the associated defined servlets. 
 * 
 * @author Craig R. McClanahan 
 */  
public class ContextConfig implements LifecycleListener {  
    .................  
    .................  
    .................  
    /**
     * Process a "contextConfig" event for this Context.
     */
    protected synchronized void configureStart() {
        // Called from StandardContext.start()

        if (log.isDebugEnabled()) {
            log.debug(sm.getString("contextConfig.start"));
        }

        if (log.isDebugEnabled()) {
            log.debug(sm.getString("contextConfig.xmlSettings",
                    context.getName(),
                    Boolean.valueOf(context.getXmlValidation()),
                    Boolean.valueOf(context.getXmlNamespaceAware())));
        }

        webConfig(); 
        .................  
        .................  
        .................  
    }  
    .................  
    .................  
    .................  
    /** 
     * Scan the web.xml files that apply to the web application and merge them 
     * using the rules defined in the spec. For the global web.xml files, 
     * where there is duplicate configuration, the most specific level wins. ie 
     * an application's web.xml takes precedence over the host level or global 
     * web.xml file. 
     */  
    protected void webConfig() {  
        /* 
         * Anything and everything can override the global and host defaults. 
         * This is implemented in two parts 
         * - Handle as a web fragment that gets added after everything else so 
         *   everything else takes priority 
         * - Mark Servlets as overridable so SCI configuration can replace 
         *   configuration from the defaults 
         */  
  
        /* 
         * The rules for annotation scanning are not as clear-cut as one might 
         * think. Tomcat implements the following process: 
         * - As per SRV.1.6.2, Tomcat will scan for annotations regardless of 
         *   which Servlet spec version is declared in web.xml. The EG has 
         *   confirmed this is the expected behaviour. 
         * - As per http://java.net/jira/browse/SERVLET_SPEC-36, if the main 
         *   web.xml is marked as metadata-complete, JARs are still processed 
         *   for SCIs. 
         * - If metadata-complete=true and an absolute ordering is specified, 
         *   JARs excluded from the ordering are also excluded from the SCI 
         *   processing. 
         * - If an SCI has a @HandlesType annotation then all classes (except 
         *   those in JARs excluded from an absolute ordering) need to be 
         *   scanned to check if they match. 
         */  
        WebXmlParser webXmlParser = new WebXmlParser(context.getXmlNamespaceAware(),  
                context.getXmlValidation(), context.getXmlBlockExternal());  
  
        Set<WebXml> defaults = new HashSet<>();  
        defaults.add(getDefaultWebXmlFragment(webXmlParser));  
  
        WebXml webXml = createWebXml();  
  
        // Parse context level web.xml  
        InputSource contextWebXml = getContextWebXmlSource();  
        if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) {  
            ok = false;  
        }  
        .................  
        .................  
        .................  
        configureContext(webXml);  
        .................  
        .................  
        .................  
    }  
  
    private void configureContext(WebXml webxml) {  
        .................  
        .................  
        .................  
        SessionConfig sessionConfig = webxml.getSessionConfig();  
        if (sessionConfig != null) {  
            if (sessionConfig.getSessionTimeout() != null) {  
                context.setSessionTimeout(  
                        sessionConfig.getSessionTimeout().intValue());  
            }  
            SessionCookieConfig scc =  
                context.getServletContext().getSessionCookieConfig();  
            scc.setName(sessionConfig.getCookieName());  
            scc.setDomain(sessionConfig.getCookieDomain());  
            scc.setPath(sessionConfig.getCookiePath());  
            scc.setComment(sessionConfig.getCookieComment());  
            if (sessionConfig.getCookieHttpOnly() != null) {  
                scc.setHttpOnly(sessionConfig.getCookieHttpOnly().booleanValue());  
            }  
            if (sessionConfig.getCookieSecure() != null) {  
                scc.setSecure(sessionConfig.getCookieSecure().booleanValue());  
            }  
            if (sessionConfig.getCookieMaxAge() != null) {  
                scc.setMaxAge(sessionConfig.getCookieMaxAge().intValue());  
            }  
            if (sessionConfig.getSessionTrackingModes().size() > 0) {  
                context.getServletContext().setSessionTrackingModes(  
                        sessionConfig.getSessionTrackingModes());  
            }  
        }  
        .................  
        .................  
        .................  
    }  
    .................  
    .................  
    .................  
} 

 

 

org/apache/tomcat/util/descriptor/web/WebRuleSet.java

/session-config/cookie-config/max-age为web.xml的配置项

/**
 * <p>Add the set of Rule instances defined in this RuleSet to the
 * specified <code>Digester</code> instance, associating them with
 * our namespace URI (if any).  This method should only be called
 * by a Digester instance.</p>
 *
 * @param digester Digester instance to which the new Rule instances
 *  should be added.
 */
@Override
public void addRuleInstances(Digester digester) {
	.................
	.................
	.................
	digester.addRule(fullPrefix + "/session-config", sessionConfig);
	digester.addObjectCreate(fullPrefix + "/session-config",
							 "org.apache.tomcat.util.descriptor.web.SessionConfig");
	digester.addSetNext(fullPrefix + "/session-config", "setSessionConfig",
						"org.apache.tomcat.util.descriptor.web.SessionConfig");
	digester.addCallMethod(fullPrefix + "/session-config/session-timeout",
						   "setSessionTimeout", 0);
	digester.addCallMethod(fullPrefix + "/session-config/cookie-config/name",
						   "setCookieName", 0);
	digester.addCallMethod(fullPrefix + "/session-config/cookie-config/domain",
						   "setCookieDomain", 0);
	digester.addCallMethod(fullPrefix + "/session-config/cookie-config/path",
						   "setCookiePath", 0);
	digester.addCallMethod(fullPrefix + "/session-config/cookie-config/comment",
						   "setCookieComment", 0);
	digester.addCallMethod(fullPrefix + "/session-config/cookie-config/http-only",
						   "setCookieHttpOnly", 0);
	digester.addCallMethod(fullPrefix + "/session-config/cookie-config/secure",
						   "setCookieSecure", 0);
	digester.addCallMethod(fullPrefix + "/session-config/cookie-config/max-age",
						   "setCookieMaxAge", 0);
	digester.addCallMethod(fullPrefix + "/session-config/tracking-mode",
						   "addSessionTrackingMode", 0);
	.................
	.................
	.................
}

 从上面的addRuleInstances里看出session cookie maxage的配置在工程里的web.xml的session-config里,比如:

<session-config>
    # 设置Session数据30分钟后过期-服务端
    <session-timeout>30</session-timeout>
    <cookie-config>
        # 设置SessionId在Cookie中的名称
        <name>sop_session_id</name>
        # 设置SessionId存在哪个路径下,跟路径则可全站使用
        <path>/</path>
        # 设置是否只读
        <http-only>true</http-only>
        # 设置SessionId30分钟后过期
        <max-age>1800</max-age>
        # 设置安全机制,只有https才能获取
        <secure>true</secure>
     </cookie-config>
</session-config>

 

疑问:如果session-timeout和max-age我都设置1年,那不是一年都不用登录了?

 

2
2
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics