Author: markt Date: Mon Feb 27 14:04:09 2017 New Revision: 1784565 URL: http://svn.apache.org/viewvc?rev=1784565&view=rev Log: Modify the cookie header generated by the Rfc6265CookieProcessor so it always sends an Expires attribute as well as a Max-Age attribute to avoid problems with Microsoft browsers that do not support the Max-Age attribute. Note the code that sets the Expires attribute was refactored from the LegacyCookieProcessor into a new, common base class.
Added: tomcat/trunk/java/org/apache/tomcat/util/http/CookieProcessorBase.java Modified: tomcat/trunk/java/org/apache/tomcat/util/http/LegacyCookieProcessor.java tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java tomcat/trunk/webapps/docs/changelog.xml Added: tomcat/trunk/java/org/apache/tomcat/util/http/CookieProcessorBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/CookieProcessorBase.java?rev=1784565&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/http/CookieProcessorBase.java (added) +++ tomcat/trunk/java/org/apache/tomcat/util/http/CookieProcessorBase.java Mon Feb 27 14:04:09 2017 @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.http; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +public abstract class CookieProcessorBase implements CookieProcessor { + + private static final String COOKIE_DATE_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z"; + + protected static final ThreadLocal<DateFormat> COOKIE_DATE_FORMAT = + new ThreadLocal<DateFormat>() { + @Override + protected DateFormat initialValue() { + DateFormat df = + new SimpleDateFormat(COOKIE_DATE_PATTERN, Locale.US); + df.setTimeZone(TimeZone.getTimeZone("GMT")); + return df; + } + }; + + protected static final String ANCIENT_DATE; + + static { + ANCIENT_DATE = COOKIE_DATE_FORMAT.get().format(new Date(10000)); + } +} Modified: tomcat/trunk/java/org/apache/tomcat/util/http/LegacyCookieProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/LegacyCookieProcessor.java?rev=1784565&r1=1784564&r2=1784565&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/http/LegacyCookieProcessor.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/http/LegacyCookieProcessor.java Mon Feb 27 14:04:09 2017 @@ -18,13 +18,9 @@ package org.apache.tomcat.util.http; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.text.DateFormat; import java.text.FieldPosition; -import java.text.SimpleDateFormat; import java.util.BitSet; import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; import javax.servlet.http.Cookie; @@ -44,7 +40,7 @@ import org.apache.tomcat.util.res.String * @author Costin Manolache * @author kevin seguin */ -public final class LegacyCookieProcessor implements CookieProcessor { +public final class LegacyCookieProcessor extends CookieProcessorBase { private static final Log log = LogFactory.getLog(LegacyCookieProcessor.class); @@ -62,26 +58,10 @@ public final class LegacyCookieProcessor '\t', ' ', '\"', '(', ')', ',', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' }; - private static final String COOKIE_DATE_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z"; - private static final ThreadLocal<DateFormat> COOKIE_DATE_FORMAT = - new ThreadLocal<DateFormat>() { - @Override - protected DateFormat initialValue() { - DateFormat df = - new SimpleDateFormat(COOKIE_DATE_PATTERN, Locale.US); - df.setTimeZone(TimeZone.getTimeZone("GMT")); - return df; - } - }; - - private static final String ANCIENT_DATE; - static { for (char c : V0_SEPARATORS) { V0_SEPARATOR_FLAGS.set(c); } - - ANCIENT_DATE = COOKIE_DATE_FORMAT.get().format(new Date(10000)); } private final boolean STRICT_SERVLET_COMPLIANCE = Modified: tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java?rev=1784565&r1=1784564&r2=1784565&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java Mon Feb 27 14:04:09 2017 @@ -18,7 +18,9 @@ package org.apache.tomcat.util.http; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.text.FieldPosition; import java.util.BitSet; +import java.util.Date; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; @@ -27,7 +29,7 @@ import org.apache.tomcat.util.buf.Messag import org.apache.tomcat.util.http.parser.Cookie; import org.apache.tomcat.util.res.StringManager; -public class Rfc6265CookieProcessor implements CookieProcessor { +public class Rfc6265CookieProcessor extends CookieProcessorBase { private static final Log log = LogFactory.getLog(Rfc6265CookieProcessor.class); @@ -98,7 +100,9 @@ public class Rfc6265CookieProcessor impl @Override public String generateHeader(javax.servlet.http.Cookie cookie) { - StringBuilder header = new StringBuilder(); + // Can't use StringBuilder due to DateFormat + StringBuffer header = new StringBuffer(); + // TODO: Name validation takes place in Cookie and cannot be configured // per Context. Moving it to here would allow per Context config // but delay validation until the header is generated. However, @@ -112,12 +116,28 @@ public class Rfc6265CookieProcessor impl header.append(value); } - // RFC 6265 prefers Max-Age to Expires so use Max-Age + // RFC 6265 prefers Max-Age to Expires but... (see below) int maxAge = cookie.getMaxAge(); if (maxAge > -1) { // Negative Max-Age is equivalent to no Max-Age header.append(";Max-Age="); header.append(maxAge); + + // Microsoft IE and Microsoft Edge don't understand Max-Age so send + // expires as well. Without this, persistent cookies fail with those + // browsers. See http://tomcat.markmail.org/thread/g6sipbofsjossacn + + // Wdy, DD-Mon-YY HH:MM:SS GMT ( Expires Netscape format ) + header.append ("; Expires="); + // To expire immediately we need to set the time in past + if (maxAge == 0) { + header.append(ANCIENT_DATE); + } else { + COOKIE_DATE_FORMAT.get().format( + new Date(System.currentTimeMillis() + maxAge * 1000L), + header, + new FieldPosition(0)); + } } String domain = cookie.getDomain(); Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1784565&r1=1784564&r2=1784565&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Mon Feb 27 14:04:09 2017 @@ -175,6 +175,13 @@ expectation is that configuration will be performed via a JSSE provider specific mechanisms. (markt) </fix> + <fix> + Modify the cookie header generated by the + <code>Rfc6265CookieProcessor</code> so it always sends an + <code>Expires</code> attribute as well as a <code>Max-Age</code> + attribute to avoid problems with Microsoft browsers that do not support + the <code>Max-Age</code> attribute. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org