在 Tomcat 中设置 CORS 标头

Posted

技术标签:

【中文标题】在 Tomcat 中设置 CORS 标头【英文标题】:Set CORS header in Tomcat 【发布时间】:2013-04-24 03:39:07 【问题描述】:

我有一个由 Tomcat 托管的静态网站。

如何为我的网站设置标题,例如:Access-Control-Allow-Origin: *

它们都是静态文件,不是任何 servlet 应用程序。

【问题讨论】:

这能回答你的问题吗? Access-Control-Allow-Origin: * in tomcat 【参考方案1】:

您需要添加一个Filter 来添加额外的标头并将其配置到所有路径

<filter>
  <filter-name>header</filter-name>
  <filter-class>...</filter-class>
</filter>
<filter-mapping>
  <filter-name>header</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

【讨论】:

它只是一个静态网站,我必须使用servlet吗? 是的,如果没有 ServletFilter 在 Tomcat 中,您将无法添加标头 @Dozer:考虑在最常见的用例中使用container provided filters。 @SzymonBiliński 我不认为 tomcat 提供任何过滤器来添加自定义标题【参考方案2】:

这是一个非常基本的过滤器,它将添加 CORS 标头。请注意,默认情况下,这将启用所有域和方法,因此您应该对其进行自定义以满足您的需求。

它还需要是 web.xml 中的第一个过滤器。

package com.conductiv.api.listener;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CORSFilter implements Filter 
    public void destroy() 
    
    public static String VALID_METHODS = "DELETE, HEAD, GET, OPTIONS, POST, PUT";

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException 
        HttpServletRequest httpReq = (HttpServletRequest) req;
        HttpServletResponse httpResp = (HttpServletResponse) resp;

        // No Origin header present means this is not a cross-domain request
        String origin = httpReq.getHeader("Origin");
         if (origin == null) 
            // Return standard response if OPTIONS request w/o Origin header
           if ("OPTIONS".equalsIgnoreCase(httpReq.getMethod())) 
                httpResp.setHeader("Allow", VALID_METHODS);
                httpResp.setStatus(200);
                return;
            
         else 
            // This is a cross-domain request, add headers allowing access
            httpResp.setHeader("Access-Control-Allow-Origin", origin);
            httpResp.setHeader("Access-Control-Allow-Methods", VALID_METHODS);

            String headers = httpReq.getHeader("Access-Control-Request-Headers");
            if (headers != null)
                httpResp.setHeader("Access-Control-Allow-Headers", headers);

            // Allow caching cross-domain permission
            httpResp.setHeader("Access-Control-Max-Age", "3600");
        
        // Pass request down the chain, except for OPTIONS
        if (!"OPTIONS".equalsIgnoreCase(httpReq.getMethod())) 
            chain.doFilter(req, resp);
        
 

    public void init(FilterConfig config) throws ServletException 

    


【讨论】:

如何使用这个类?。我是否需要在此类“CORSFilter”中添加我的@Post 方法 在您的应用中创建此类。然后在您的应用程序的 web.xml 中添加此类路径,其中 class header.......header/* 添加标头是否足以处理 CORS 请求?不需要实际的逻辑吗?【参考方案3】:

如果是静态站点,那么从 Tomcat 7.0.41 开始,您可以通过内置过滤器轻松控制 CORS 行为。

参考资料:

Tomcat 7 Tomcat 9

您几乎唯一需要做的就是在CATALINA_HOME/conf 中编辑全局web.xml 并添加过滤器定义:

... CorsFilterorg.apache.catalina.filters.CorsFilter过滤器> CorsFilter/*

但请注意,Firefox 不喜欢 Access-Control-Allow-Origin: * 和带有凭据 (cookie) 的请求:when responding to a credentialed request, server must specify a domain, and cannot use wild carding.

如果您想在这种情况下调试请求,请注意,根据此流程图,只有在存在跨域请求时才会发送 CORS 标头。

(tomcat.apache.org/tomcat-8.0-doc/images/cors-flowchart.png)

【讨论】:

调试时,请注意只有在有跨域请求时才会发送 CORS 标头。见tomcat.apache.org/tomcat-8.0-doc/images/cors-flowchart.png。因此,请不要只检查随机调用(使用 Fiddler、网络选项卡等),而是检查 CORS 本身的请求。 添加该过滤器后,我仍然收到 对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'localhost:8080' 不允许访问。响应具有 HTTP 状态代码 403。另外我的方法实际上是一个 GET 已被转换为 OPTION 并返回 403 有这个nice site 可以让你发送 CORS 请求,如果你想测试一些东西。 请注意,这实际上不会添加标题,除非您还设置了 cors.allowed.origins。其他参数有可用的默认值,但你肯定也需要设置这个。 (它实际上并不适合我,但文档对此非常清楚,所以也许这可能对某人有所帮助......) 您可以像这样设置允许的来源:&lt;filter&gt; &lt;filter-name&gt;CorsFilter&lt;/filter-name&gt; &lt;filter-class&gt;org.apache.catalina.filters.CorsFilter&lt;/filter-class&gt; &lt;init-param&gt; &lt;param-name&gt;cors.allowed.origins&lt;/param-name&gt; &lt;param-value&gt;*&lt;/param-value&gt; &lt;/init-param&gt; &lt;/filter&gt;【参考方案4】:

请注意,要使用值 * 配置 CORS 过滤器,除了启用文件管理器之外,您还需要为参数 &lt;param-name&gt;cors.allowed.origins&lt;/param-name&gt; 添加配置,如下所示(基于 Johannes Jander @987654321 @):

 <!-- ================== Built In Filter Definitions ===================== -->

  ...

 <filter>
   <filter-name>CorsFilter</filter-name>
   <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
   <init-param>
     <param-name>cors.allowed.origins</param-name>
     <param-value>*</param-value>
   </init-param>
 </filter>
 <filter-mapping>
   <filter-name>CorsFilter</filter-name>
   <url-pattern>/*</url-pattern>
 </filter-mapping>

<!-- ==================== Built In Filter Mappings ====================== -->

【讨论】:

以上是关于在 Tomcat 中设置 CORS 标头的主要内容,如果未能解决你的问题,请参考以下文章

当使用 mode: no-cors 请求时,浏览器没有添加我在前端代码中设置的请求标头

连接到 slack api 中的 chat.postMessage 的 CORS 策略错误,标头已设置但未在 React 和 Redux 中设置 [重复]

带有域字段的 CORS cookie 仅在使用 jQuery AJAX 的 Firefox 中设置

即使存在标头,CORS 也会失败

即使存在标头,CORS 也会失败

CORS过滤在“授权”标头中不起作用[重复]