You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2019/12/02 18:03:54 UTC
[tomcat] branch 7.0.x updated:
https://bz.apache.org/bugzilla/show_bug.cgi?id=63937 allowCorsPreflight
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/7.0.x by this push:
new 0592e5e https://bz.apache.org/bugzilla/show_bug.cgi?id=63937 allowCorsPreflight
0592e5e is described below
commit 0592e5e2955c790d5072d2ba040d76e217f9f283
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Dec 2 14:01:13 2019 +0000
https://bz.apache.org/bugzilla/show_bug.cgi?id=63937 allowCorsPreflight
Add a new attribute to the standard Authenticator implementations,
allowCorsPreflight, that allows the Authenticators to be configured to
allow CORS preflight requests to bypass authentication as required by
the CORS specification.
---
.../catalina/authenticator/AuthenticatorBase.java | 88 +++++++++-
java/org/apache/catalina/filters/CorsFilter.java | 34 +---
java/org/apache/tomcat/util/http/RequestUtil.java | 43 +++++
.../TestAuthenticatorBaseCorsPreflight.java | 177 +++++++++++++++++++++
.../apache/catalina/filters/TestCorsFilter.java | 12 +-
webapps/docs/changelog.xml | 18 ++-
webapps/docs/config/valve.xml | 93 +++++++++--
7 files changed, 417 insertions(+), 48 deletions(-)
diff --git a/java/org/apache/catalina/authenticator/AuthenticatorBase.java b/java/org/apache/catalina/authenticator/AuthenticatorBase.java
index 5399716..7bd9a89 100644
--- a/java/org/apache/catalina/authenticator/AuthenticatorBase.java
+++ b/java/org/apache/catalina/authenticator/AuthenticatorBase.java
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.security.Principal;
import java.security.cert.X509Certificate;
+import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
@@ -36,8 +37,11 @@ import org.apache.catalina.Session;
import org.apache.catalina.Valve;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
+import org.apache.catalina.deploy.FilterDef;
+import org.apache.catalina.deploy.FilterMap;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.deploy.SecurityConstraint;
+import org.apache.catalina.filters.CorsFilter;
import org.apache.catalina.filters.RemoteIpFilter;
import org.apache.catalina.realm.GenericPrincipal;
import org.apache.catalina.util.SessionIdGeneratorBase;
@@ -49,6 +53,7 @@ import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.http.FastHttpDateFormat;
+import org.apache.tomcat.util.http.RequestUtil;
import org.apache.tomcat.util.res.StringManager;
/**
@@ -200,11 +205,19 @@ public abstract class AuthenticatorBase extends ValveBase
*/
protected SingleSignOn sso = null;
-
+ private AllowCorsPreflight allowCorsPreflight = AllowCorsPreflight.NEVER;
// ------------------------------------------------------------- Properties
+ public String getAllowCorsPreflight() {
+ return allowCorsPreflight.name().toLowerCase();
+ }
+
+ public void setAllowCorsPreflight(String allowCorsPreflight) {
+ this.allowCorsPreflight = AllowCorsPreflight.valueOf(allowCorsPreflight.trim().toUpperCase());
+ }
+
public boolean getAlwaysUseSession() {
return alwaysUseSession;
}
@@ -543,6 +556,14 @@ public abstract class AuthenticatorBase extends ValveBase
authRequired = certs != null && certs.length > 0;
}
+ if ((authRequired || constraints != null) && allowCorsPreflightBypass(request)) {
+ if (log.isDebugEnabled()) {
+ log.debug(" CORS Preflight request bypassing authentication");
+ }
+ getNext().invoke(request, response);
+ return;
+ }
+
if (authRequired) {
if (log.isDebugEnabled()) {
log.debug(" Calling authenticate()");
@@ -585,6 +606,64 @@ public abstract class AuthenticatorBase extends ValveBase
}
+ protected boolean allowCorsPreflightBypass(Request request) {
+ boolean allowBypass = false;
+
+ if (allowCorsPreflight != AllowCorsPreflight.NEVER) {
+ // First check to see if this is a CORS Preflight request
+ // This is a subset of the tests in CorsFilter.checkRequestType
+ if ("OPTIONS".equals(request.getMethod())) {
+ String originHeader = request.getHeader(CorsFilter.REQUEST_HEADER_ORIGIN);
+ if (originHeader != null &&
+ !originHeader.isEmpty() &&
+ RequestUtil.isValidOrigin(originHeader) &&
+ !RequestUtil.isSameOrigin(request, originHeader)) {
+ String accessControlRequestMethodHeader =
+ request.getHeader(CorsFilter.REQUEST_HEADER_ACCESS_CONTROL_REQUEST_METHOD);
+ if (accessControlRequestMethodHeader != null &&
+ !accessControlRequestMethodHeader.isEmpty()) {
+ // This appears to be a CORS Preflight request
+ if (allowCorsPreflight == AllowCorsPreflight.ALWAYS) {
+ allowBypass = true;
+ } else if (allowCorsPreflight == AllowCorsPreflight.FILTER) {
+ if (DispatcherType.REQUEST == request.getDispatcherType()) {
+ // Look at Filter configuration for the Context
+ // Can't cache this unless we add a listener to
+ // the Context to clear the cache on reload
+ for (FilterDef filterDef : request.getContext().findFilterDefs()) {
+ if (CorsFilter.class.getName().equals(filterDef.getFilterClass())) {
+ for (FilterMap filterMap : context.findFilterMaps()) {
+ if (filterMap.getFilterName().equals(filterDef.getFilterName())) {
+ if ((filterMap.getDispatcherMapping() & FilterMap.REQUEST) > 0) {
+ for (String urlPattern : filterMap.getURLPatterns()) {
+ if ("/*".equals(urlPattern)) {
+ allowBypass = true;
+ // No need to check other patterns
+ break;
+ }
+ }
+ }
+ // Found mappings for CORS filter.
+ // No need to look further
+ break;
+ }
+ }
+ // Found the CORS filter. No need to look further.
+ break;
+ }
+ }
+ }
+ } else {
+ // Unexpected enum type
+ }
+ }
+ }
+ }
+ }
+ return allowBypass;
+ }
+
+
@Override
public boolean authenticate(Request request, HttpServletResponse httpResponse)
throws IOException {
@@ -1028,4 +1107,11 @@ public abstract class AuthenticatorBase extends ValveBase
sso = null;
}
+
+
+ protected enum AllowCorsPreflight {
+ NEVER,
+ FILTER,
+ ALWAYS
+ }
}
diff --git a/java/org/apache/catalina/filters/CorsFilter.java b/java/org/apache/catalina/filters/CorsFilter.java
index 4f107ce..a4fe022 100644
--- a/java/org/apache/catalina/filters/CorsFilter.java
+++ b/java/org/apache/catalina/filters/CorsFilter.java
@@ -18,7 +18,6 @@ package org.apache.catalina.filters;
import java.io.IOException;
import java.net.URI;
-import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
@@ -640,7 +639,7 @@ public class CorsFilter implements Filter {
if (originHeader != null) {
if (originHeader.isEmpty()) {
requestType = CORSRequestType.INVALID_CORS;
- } else if (!isValidOrigin(originHeader)) {
+ } else if (!RequestUtil.isValidOrigin(originHeader)) {
requestType = CORSRequestType.INVALID_CORS;
} else if (RequestUtil.isSameOrigin(request, originHeader)) {
return CORSRequestType.NOT_CORS;
@@ -832,34 +831,13 @@ public class CorsFilter implements Filter {
*
* @param origin
* @see <a href="http://tools.ietf.org/html/rfc952">RFC952</a>
+ *
+ * @deprecated This will be removed in Tomcat 10
+ * Use {@link RequestUtil#isValidOrigin(String)}
*/
+ @Deprecated
protected static boolean isValidOrigin(String origin) {
- // Checks for encoded characters. Helps prevent CRLF injection.
- if (origin.contains("%")) {
- return false;
- }
-
- // "null" is a valid origin
- if ("null".equals(origin)) {
- return true;
- }
-
- // RFC6454, section 4. "If uri-scheme is file, the implementation MAY
- // return an implementation-defined value.". No limits are placed on
- // that value so treat all file URIs as valid origins.
- if (origin.startsWith("file://")) {
- return true;
- }
-
- URI originURI;
- try {
- originURI = new URI(origin);
- } catch (URISyntaxException e) {
- return false;
- }
- // If scheme for URI is null, return false. Return true otherwise.
- return originURI.getScheme() != null;
-
+ return RequestUtil.isValidOrigin(origin);
}
diff --git a/java/org/apache/tomcat/util/http/RequestUtil.java b/java/org/apache/tomcat/util/http/RequestUtil.java
index cfa9c57..2edd695 100644
--- a/java/org/apache/tomcat/util/http/RequestUtil.java
+++ b/java/org/apache/tomcat/util/http/RequestUtil.java
@@ -16,6 +16,8 @@
*/
package org.apache.tomcat.util.http;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
@@ -164,4 +166,45 @@ public class RequestUtil {
return origin.equals(target.toString());
}
+
+ /**
+ * Checks if a given origin is valid or not. Criteria:
+ * <ul>
+ * <li>If an encoded character is present in origin, it's not valid.</li>
+ * <li>If origin is "null", it's valid.</li>
+ * <li>Origin should be a valid {@link URI}</li>
+ * </ul>
+ *
+ * @param origin The origin URI
+ * @return <code>true</code> if the origin was valid
+ * @see <a href="http://tools.ietf.org/html/rfc952">RFC952</a>
+ */
+ public static boolean isValidOrigin(String origin) {
+ // Checks for encoded characters. Helps prevent CRLF injection.
+ if (origin.contains("%")) {
+ return false;
+ }
+
+ // "null" is a valid origin
+ if ("null".equals(origin)) {
+ return true;
+ }
+
+ // RFC6454, section 4. "If uri-scheme is file, the implementation MAY
+ // return an implementation-defined value.". No limits are placed on
+ // that value so treat all file URIs as valid origins.
+ if (origin.startsWith("file://")) {
+ return true;
+ }
+
+ URI originURI;
+ try {
+ originURI = new URI(origin);
+ } catch (URISyntaxException e) {
+ return false;
+ }
+ // If scheme for URI is null, return false. Return true otherwise.
+ return originURI.getScheme() != null;
+
+ }
}
diff --git a/test/org/apache/catalina/authenticator/TestAuthenticatorBaseCorsPreflight.java b/test/org/apache/catalina/authenticator/TestAuthenticatorBaseCorsPreflight.java
new file mode 100644
index 0000000..e463882
--- /dev/null
+++ b/test/org/apache/catalina/authenticator/TestAuthenticatorBaseCorsPreflight.java
@@ -0,0 +1,177 @@
+/*
+ * 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.catalina.authenticator;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Realm;
+import org.apache.catalina.authenticator.AuthenticatorBase.AllowCorsPreflight;
+import org.apache.catalina.deploy.FilterDef;
+import org.apache.catalina.deploy.FilterMap;
+import org.apache.catalina.deploy.LoginConfig;
+import org.apache.catalina.deploy.SecurityCollection;
+import org.apache.catalina.deploy.SecurityConstraint;
+import org.apache.catalina.filters.AddDefaultCharsetFilter;
+import org.apache.catalina.filters.CorsFilter;
+import org.apache.catalina.realm.NullRealm;
+import org.apache.catalina.servlets.DefaultServlet;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+@RunWith(Parameterized.class)
+public class TestAuthenticatorBaseCorsPreflight extends TomcatBaseTest {
+
+ private static final String ALLOWED_ORIGIN = "http://example.com";
+ private static final String EMPTY_ORIGIN = "";
+ private static final String INVALID_ORIGIN = "http://%20";
+ private static final String SAME_ORIGIN = "http://localhost";
+ private static final String ALLOWED_METHOD = "GET";
+ private static final String BLOCKED_METHOD = "POST";
+ private static final String EMPTY_METHOD = "";
+
+ @Parameterized.Parameters(name = "{index}: input[{0}]")
+ public static Collection<Object[]> parameters() {
+ List<Object[]> parameterSets = new ArrayList<Object[]>();
+
+ parameterSets.add(new Object[] { AllowCorsPreflight.NEVER, "/*", "OPTIONS", null, null, Boolean.FALSE });
+ parameterSets.add(new Object[] { AllowCorsPreflight.ALWAYS, "/*", "OPTIONS", null, null, Boolean.FALSE });
+ parameterSets.add(new Object[] { AllowCorsPreflight.ALWAYS, "/*", "OPTIONS", ALLOWED_ORIGIN, ALLOWED_METHOD, Boolean.TRUE });
+ parameterSets.add(new Object[] { AllowCorsPreflight.ALWAYS, "/*", "OPTIONS", EMPTY_ORIGIN, ALLOWED_METHOD, Boolean.FALSE});
+ parameterSets.add(new Object[] { AllowCorsPreflight.ALWAYS, "/*", "OPTIONS", INVALID_ORIGIN, ALLOWED_METHOD, Boolean.FALSE });
+ parameterSets.add(new Object[] { AllowCorsPreflight.ALWAYS, "/*", "OPTIONS", SAME_ORIGIN, ALLOWED_METHOD, Boolean.FALSE });
+ parameterSets.add(new Object[] { AllowCorsPreflight.ALWAYS, "/*", "GET", ALLOWED_ORIGIN, ALLOWED_METHOD, Boolean.FALSE });
+ parameterSets.add(new Object[] { AllowCorsPreflight.ALWAYS, "/*", "OPTIONS", ALLOWED_ORIGIN, BLOCKED_METHOD, Boolean.FALSE });
+ parameterSets.add(new Object[] { AllowCorsPreflight.ALWAYS, "/*", "OPTIONS", ALLOWED_ORIGIN, EMPTY_METHOD, Boolean.FALSE});
+ parameterSets.add(new Object[] { AllowCorsPreflight.ALWAYS, "/*", "OPTIONS", ALLOWED_ORIGIN, null, Boolean.FALSE});
+ parameterSets.add(new Object[] { AllowCorsPreflight.FILTER, "/*", "OPTIONS", ALLOWED_ORIGIN, ALLOWED_METHOD, Boolean.TRUE });
+ parameterSets.add(new Object[] { AllowCorsPreflight.FILTER, "/x", "OPTIONS", ALLOWED_ORIGIN, ALLOWED_METHOD, Boolean.FALSE });
+
+ return parameterSets;
+ }
+
+ @Parameter(0)
+ public AllowCorsPreflight allowCorsPreflight;
+ @Parameter(1)
+ public String filterMapping;
+ @Parameter(2)
+ public String method;
+ @Parameter(3)
+ public String origin;
+ @Parameter(4)
+ public String accessControl;
+ @Parameter(5)
+ public boolean allow;
+
+
+ @BeforeClass
+ public static void init() {
+ // So the test can set the origin header
+ System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
+ }
+
+
+ @Test
+ public void test() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ File appDir = new File("test/webapp");
+ Context ctx = tomcat.addContext("", appDir.getAbsolutePath());
+
+ Tomcat.addServlet(ctx, "default", new DefaultServlet());
+ ctx.addServletMapping("/", "default");
+
+ LoginConfig loginConfig = new LoginConfig();
+ loginConfig.setAuthMethod("BASIC");
+ ctx.setLoginConfig(loginConfig);
+
+ BasicAuthenticator basicAuth = new BasicAuthenticator();
+ basicAuth.setAllowCorsPreflight(allowCorsPreflight.toString());
+ ctx.getPipeline().addValve(basicAuth);
+
+ Realm realm = new NullRealm();
+ ctx.setRealm(realm);
+
+ SecurityCollection securityCollection = new SecurityCollection();
+ securityCollection.addPattern("/*");
+ SecurityConstraint constraint = new SecurityConstraint();
+ constraint.setAuthConstraint(true);
+ constraint.addCollection(securityCollection);
+ ctx.addConstraint(constraint);
+
+ // For code coverage
+ FilterDef otherFilter = new FilterDef();
+ otherFilter.setFilterName("other");
+ otherFilter.setFilterClass(AddDefaultCharsetFilter.class.getName());
+ FilterMap otherMap = new FilterMap();
+ otherMap.setFilterName("other");
+ otherMap.addURLPattern("/other");
+ ctx.addFilterDef(otherFilter);
+ ctx.addFilterMap(otherMap);
+
+ FilterDef corsFilter = new FilterDef();
+ corsFilter.setFilterName("cors");
+ corsFilter.setFilterClass(CorsFilter.class.getName());
+ corsFilter.addInitParameter(CorsFilter.PARAM_CORS_ALLOWED_ORIGINS, ALLOWED_ORIGIN);
+ corsFilter.addInitParameter(CorsFilter.PARAM_CORS_ALLOWED_METHODS, ALLOWED_METHOD);
+ FilterMap corsFilterMap = new FilterMap();
+ corsFilterMap.setFilterName("cors");
+ corsFilterMap.addURLPattern(filterMapping);
+ ctx.addFilterDef(corsFilter);
+ ctx.addFilterMap(corsFilterMap);
+
+ tomcat.start();
+
+ Map<String,List<String>> reqHead = new HashMap<String,List<String>>();
+ if (origin != null) {
+ List<String> values = new ArrayList<String>();
+ if (SAME_ORIGIN.equals(origin)) {
+ values.add(origin + ":" + getPort());
+ } else {
+ values.add(origin);
+ }
+ reqHead.put(CorsFilter.REQUEST_HEADER_ORIGIN, values);
+ }
+ if (accessControl != null) {
+ List<String> values = new ArrayList<String>();
+ values.add(accessControl);
+ reqHead.put(CorsFilter.REQUEST_HEADER_ACCESS_CONTROL_REQUEST_METHOD, values);
+ }
+
+ ByteChunk out = new ByteChunk();
+ int rc = methodUrl("http://localhost:" + getPort() + "/target", out, 300000, reqHead, null, method, false);
+
+ if (allow) {
+ Assert.assertEquals(200, rc);
+ } else {
+ Assert.assertEquals(403, rc);
+ }
+ }
+}
diff --git a/test/org/apache/catalina/filters/TestCorsFilter.java b/test/org/apache/catalina/filters/TestCorsFilter.java
index 47d520a..6c7b8a1 100644
--- a/test/org/apache/catalina/filters/TestCorsFilter.java
+++ b/test/org/apache/catalina/filters/TestCorsFilter.java
@@ -29,6 +29,8 @@ import javax.servlet.http.HttpServletResponse;
import org.junit.Assert;
import org.junit.Test;
+import org.apache.tomcat.util.http.RequestUtil;
+
public class TestCorsFilter {
private FilterChain filterChain = new TesterFilterChain();
@@ -1414,27 +1416,27 @@ public class TestCorsFilter {
@Test
public void testValidOrigin() {
- Assert.assertTrue(CorsFilter.isValidOrigin("http://www.w3.org"));
+ Assert.assertTrue(RequestUtil.isValidOrigin("http://www.w3.org"));
}
@Test
public void testInValidOriginCRLF() {
- Assert.assertFalse(CorsFilter.isValidOrigin("http://www.w3.org\r\n"));
+ Assert.assertFalse(RequestUtil.isValidOrigin("http://www.w3.org\r\n"));
}
@Test
public void testInValidOriginEncodedCRLF1() {
- Assert.assertFalse(CorsFilter.isValidOrigin("http://www.w3.org%0d%0a"));
+ Assert.assertFalse(RequestUtil.isValidOrigin("http://www.w3.org%0d%0a"));
}
@Test
public void testInValidOriginEncodedCRLF2() {
- Assert.assertFalse(CorsFilter.isValidOrigin("http://www.w3.org%0D%0A"));
+ Assert.assertFalse(RequestUtil.isValidOrigin("http://www.w3.org%0D%0A"));
}
@Test
public void testInValidOriginEncodedCRLF3() {
- Assert.assertFalse(CorsFilter
+ Assert.assertFalse(RequestUtil
.isValidOrigin("http://www.w3.org%0%0d%0ad%0%0d%0aa"));
}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index b3201a7..3ee3850 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -66,17 +66,25 @@
<bug>63681</bug>: Introduce RealmBase#authenticate(GSSName, GSSCredential)
and friends. (michaelo)
</add>
- <fix>
- <bug>63950</bug>: Fix timing issue in
- <code>TestAsyncContextStateChanges</code> test that caused it
- to hang indefinitely. (markt)
- </fix>
+ <add>
+ <bug>63937</bug>: Add a new attribute to the standard
+ <code>Authenticator</code> implementations,
+ <code>allowCorsPreflight</code>, that allows the
+ <code>Authenticator</code>s to be configured to allow CORS preflight
+ requests to bypass authentication as required by the CORS specification.
+ (markt)
+ </add>
<fix>
<bug>63939</bug>: Correct the same origin check in the CORS filter. An
origin with an explicit default port is now considered to be the same as
an origin without a deafult port and origins are now compared in a
case-sensitive manner as required by the CORS specification. (markt)
</fix>
+ <fix>
+ <bug>63950</bug>: Fix timing issue in
+ <code>TestAsyncContextStateChanges</code> test that caused it
+ to hang indefinitely. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
diff --git a/webapps/docs/config/valve.xml b/webapps/docs/config/valve.xml
index 5a9f671..05d1b6b 100644
--- a/webapps/docs/config/valve.xml
+++ b/webapps/docs/config/valve.xml
@@ -1102,6 +1102,21 @@
<attributes>
+ <attribute name="allowCorsPreflight" required="false">
+ <p>Are requests that appear to be CORS preflight requests allowed to
+ bypass the authenticator as required by the CORS specification. The
+ allowed values are <code>never</code>, <code>filter</code> and
+ <code>always</code>. <code>never</code> means that a request will never
+ bypass authentication even if it appears to be a CORS preflight request.
+ <code>filter</code> means that a request will bypass authentication if
+ it appears to be a CORS preflight request and the web application the
+ request maps to has the <a href="filter.html#CORS_Filter">CORS
+ Filter</a> enabled and mapped to <code>/*</code>. <code>always</code>
+ means that all requests that appear to be CORS preflight requests will
+ bypass authentication. If not set, the default value is
+ <code>never</code>.</p>
+ </attribute>
+
<attribute name="alwaysUseSession" required="false">
<p>Should a session always be used once a user is authenticated? This
may offer some performance benefits since the session can then be used
@@ -1230,6 +1245,21 @@
<attributes>
+ <attribute name="allowCorsPreflight" required="false">
+ <p>Are requests that appear to be CORS preflight requests allowed to
+ bypass the authenticator as required by the CORS specification. The
+ allowed values are <code>never</code>, <code>filter</code> and
+ <code>always</code>. <code>never</code> means that a request will never
+ bypass authentication even if it appears to be a CORS preflight request.
+ <code>filter</code> means that a request will bypass authentication if
+ it appears to be a CORS preflight request and the web application the
+ request maps to has the <a href="filter.html#CORS_Filter">CORS
+ Filter</a> enabled and mapped to <code>/*</code>. <code>always</code>
+ means that all requests that appear to be CORS preflight requests will
+ bypass authentication. If not set, the default value is
+ <code>never</code>.</p>
+ </attribute>
+
<attribute name="alwaysUseSession" required="false">
<p>Should a session always be used once a user is authenticated? This
may offer some performance benefits since the session can then be used
@@ -1388,6 +1418,21 @@
<attributes>
+ <attribute name="allowCorsPreflight" required="false">
+ <p>Are requests that appear to be CORS preflight requests allowed to
+ bypass the authenticator as required by the CORS specification. The
+ allowed values are <code>never</code>, <code>filter</code> and
+ <code>always</code>. <code>never</code> means that a request will never
+ bypass authentication even if it appears to be a CORS preflight request.
+ <code>filter</code> means that a request will bypass authentication if
+ it appears to be a CORS preflight request and the web application the
+ request maps to has the <a href="filter.html#CORS_Filter">CORS
+ Filter</a> enabled and mapped to <code>/*</code>. <code>always</code>
+ means that all requests that appear to be CORS preflight requests will
+ bypass authentication. If not set, the default value is
+ <code>never</code>.</p>
+ </attribute>
+
<attribute name="changeSessionIdOnAuthentication" required="false">
<p>Controls if the session ID is changed if a session exists at the
point where users are authenticated. This is to prevent session fixation
@@ -1505,6 +1550,21 @@
<attributes>
+ <attribute name="allowCorsPreflight" required="false">
+ <p>Are requests that appear to be CORS preflight requests allowed to
+ bypass the authenticator as required by the CORS specification. The
+ allowed values are <code>never</code>, <code>filter</code> and
+ <code>always</code>. <code>never</code> means that a request will never
+ bypass authentication even if it appears to be a CORS preflight request.
+ <code>filter</code> means that a request will bypass authentication if
+ it appears to be a CORS preflight request and the web application the
+ request maps to has the <a href="filter.html#CORS_Filter">CORS
+ Filter</a> enabled and mapped to <code>/*</code>. <code>always</code>
+ means that all requests that appear to be CORS preflight requests will
+ bypass authentication. If not set, the default value is
+ <code>never</code>.</p>
+ </attribute>
+
<attribute name="cache" required="false">
<p>Should we cache authenticated Principals if the request is part of an
HTTP session? If not specified, the default value of <code>true</code>
@@ -1597,15 +1657,19 @@
<attributes>
- <attribute name="applyJava8u40Fix" required="false">
- <p>A fix introduced in Java 8 update 40 (
- <a href="https://bugs.openjdk.java.net/browse/JDK-8048194">JDK-8048194</a>)
- onwards broke SPNEGO authentication for IE with Tomcat running on
- Windows 2008 R2 servers. This option enables a work-around that allows
- SPNEGO authentication to continue working. The work-around should not
- impact other configurations so it is enabled by default. If necessary,
- the workaround can be disabled by setting this attribute to
- <code>false</code>.</p>
+ <attribute name="allowCorsPreflight" required="false">
+ <p>Are requests that appear to be CORS preflight requests allowed to
+ bypass the authenticator as required by the CORS specification. The
+ allowed values are <code>never</code>, <code>filter</code> and
+ <code>always</code>. <code>never</code> means that a request will never
+ bypass authentication even if it appears to be a CORS preflight request.
+ <code>filter</code> means that a request will bypass authentication if
+ it appears to be a CORS preflight request and the web application the
+ request maps to has the <a href="filter.html#CORS_Filter">CORS
+ Filter</a> enabled and mapped to <code>/*</code>. <code>always</code>
+ means that all requests that appear to be CORS preflight requests will
+ bypass authentication. If not set, the default value is
+ <code>never</code>.</p>
</attribute>
<attribute name="alwaysUseSession" required="false">
@@ -1620,6 +1684,17 @@
<code>false</code> will be used.</p>
</attribute>
+ <attribute name="applyJava8u40Fix" required="false">
+ <p>A fix introduced in Java 8 update 40 (
+ <a href="https://bugs.openjdk.java.net/browse/JDK-8048194">JDK-8048194</a>)
+ onwards broke SPNEGO authentication for IE with Tomcat running on
+ Windows 2008 R2 servers. This option enables a work-around that allows
+ SPNEGO authentication to continue working. The work-around should not
+ impact other configurations so it is enabled by default. If necessary,
+ the workaround can be disabled by setting this attribute to
+ <code>false</code>.</p>
+ </attribute>
+
<attribute name="cache" required="false">
<p>Should we cache authenticated Principals if the request is part of an
HTTP session? If not specified, the default value of <code>true</code>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org