覆盖 CORS 配置

Posted

技术标签:

【中文标题】覆盖 CORS 配置【英文标题】:Overwriting CORS configuration 【发布时间】:2017-09-08 11:53:09 【问题描述】:

我基于Blade CLI blade.rest 示例部署了一个OSGi 模块,并对其进行了修改以返回响应而不是纯文本。这是课程:

package com.autentia.api.rest.users;

import org.osgi.service.component.annotations.Component;
import javax.servlet.http.HttpServletRequest;


import javax.ws.rs.ApplicationPath;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Collections;
import java.util.Set;

@ApplicationPath("/users")
@Component(
        immediate = true, property = "jaxrs.application=true",
        service = Application.class
)
public class UsersRestService extends Application 

    @Override
    public Set<Object> getSingletons() 
        return Collections.singleton(this);
    

    @GET
    @Path("/")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getUsers(@Context HttpServletRequest request) 
        System.out.println(request.getRemoteAddr());
        String json = "\n" + "  \"value\": \"ok\"\n" + "";
        return Response
                .status(200)
                .header("Access-Control-Allow-Origin", "*")
                .entity(json)
                .build();
    

(如果我删除 .header("Access-Control-Allow-Origin", "*"),这将在本地工作。)

当我向服务器提出请求时出现问题,响应具有两个 Access-Control-Access-Origin 属性,一个设置为“*”(这是我想要的),一个设置为它所在的 ip发送。响应如下:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://localhost:3000
Access-Control-Allow-Origin:*
Content-Length:19
Content-Type:application/json
Date:Wed, 12 Apr 2017 15:23:38 GMT
Server:Apache-Coyote/1.1
Set-Cookie:JSESSIONID=CF771CD0FAECDAF226D153FB05875CC3; Path=/; HttpOnly
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
X-Request-URL:http://localhost:8080/o/api/users
X-XSS-Protection:1

如您所见,有两个 Access-Control-Allow-Origin 不被接受。我应该从哪里开始寻找?我应该修改 Tomcat 的 web.xml 吗?我查看了portal.propertiessystem.properties,但没有看到启用该标头的属性。

谢谢。

【问题讨论】:

【参考方案1】:

正如@sideshowbarker 提到的,关键是编辑位于Liferay 嵌入式Tomcat 上的web.xml 文件。我应用的配置如下:

<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>http://localhost:49227</param-value>
    </init-param>
    <init-param>
        <param-name>cors.allowed.methods</param-name>
        <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
    </init-param>
    <init-param>
        <param-name>cors.allowed.headers</param-name>
        <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
    </init-param>
    <init-param>
        <param-name>cors.exposed.headers</param-name>
        <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
    </init-param>
    <init-param>
        <param-name>cors.support.credentials</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>cors.preflight.maxage</param-name>
        <param-value>10</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CorsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

之后,我从我正在使用的方法 getUsers 的响应中删除了标头并重新启动了 Tomcat,以便应用配置。

如果我想允许所有来源或将 IP 列入白名单,我必须更改以下 param

<init-param>
    <param-name>cors.allowed.origins</param-name>
    <param-value>http://<IP_TO_WHITELIST>:<PORT></param-value>
</init-param>

或允许所有来源:

<init-param>
    <param-name>cors.allowed.origins</param-name>
    <param-value>*</param-value>
</init-param>

【讨论】:

【参考方案2】:

在您的CATALINA_BASE/conf/web.xml 中查找CorsFilter 过滤器

http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#CORS_Filter 有文档。

要允许来自任何来源的请求,您可以将其添加到该文件中:

<init-param>
  <param-name>cors.allowed.origins</param-name>
  <param-value>*</param-value>
</init-param>

【讨论】:

我已经将该链接中提到的过滤器应用到 Liferay 的 web.xml 并且问题仍然存在。两个属性 Access-Control-Allow-Origin 被发送到客户端,这是不允许的。 我的意思是在那个文件中寻找它,如果你在那里找到它就删除它。但是现在你已经添加了它,你可以从你的应用程序代码中删除 headers 调用,对吧? 是的,这正是我尝试过的,但是发送的唯一标头是带有主机的标头,而不是 *。 那么,听起来你想设置&lt;init-param&gt;&lt;param-name&gt;cors.allowed.origins&lt;/param-name&gt;&lt;param-value&gt;*&lt;/param-value&lt;/init-param&gt; 我会试试的,谢谢!我想要完成的是设置一个公共 API Rest 并使用来自远程客户端的 fetch 连接到它。有没有更好的方法来做到这一点,还是我错过了什么?

以上是关于覆盖 CORS 配置的主要内容,如果未能解决你的问题,请参考以下文章

在 java spring boot 中覆盖 CORS 策略

Chrome 地理定位传感器破坏 CORS

如何覆盖子类中的macwire注入

如何配置 SonarQube 让我们增加覆盖范围?

你如何覆盖 OpenFeign 的 Hystrix 配置?

什么可以防止在服务器中覆盖 Access-Control-Allow-Origin?