当请求的凭据模式为“include”时,响应中的标头不能是通配符“\*”

新手上路,请多包涵

我正在使用 Auth0 进行用户身份验证,只允许登录用户访问 Spring (Boot) RestController 。此时,我正在创建一个实时消息功能,用户可以在其中使用 Angular 2 客户端 ( localhost:4200 ) 向 Spring 服务器 (localhost:8081) 发送消息 stompjssockjs

尝试创建 Stomp 客户端并启动连接时,我收到以下控制台错误:

  The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:4200' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

在研究了这个问题之后,看起来不可能同时设置选项 origins = * 和 credentials = true。当我已经在 WebSocketConfig 中将允许的来源设置为客户端域时,我该如何解决这个问题?

角度 2 组件

connect() {
    var socket = new SockJS('http://localhost:8081/chat');
    this.stompClient = Stomp.over(socket);
    this.stompClient.connect({}, function(result) {
        console.log('Connected: ' + result);
        this.stompClient.subscribe('/topic/messages', function(message) {
            console.log(message);
        });
    });
}

WebSocket配置

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/chat").setAllowedOrigins("http://localhost:4200").withSockJS();
    }
}

本地主机:8081/聊天/信息?t=1490866768565

 {"entropy":-1720701276,"origins":["*:*"],"cookie_needed":true,"websocket":true}

消息控制器

public class MessageController {
    @MessageMapping("/chat")
    @SendTo("/topic/messages")
    public Message send(Message message) throws Exception {
        return new Message(message.getFrom(), message.getText());
    }
}

SecurityConfig(暂时全部允许)

 public class SecurityConfig extends Auth0SecurityConfig {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().permitAll();
    }
}

更新

经过更多测试和研究后,问题似乎只发生在使用 Chrome 时。问题可能与: https ://github.com/sockjs/sockjs-node/issues/177 有关

更新

我像提到的 chsdk 创建了 CORSFilter,并使用了 addFilterBefore() 方法: https ://stackoverflow.com/a/40300363/4836952。

 @Bean
CORSFilter corsFilter() {
    CORSFilter filter = new CORSFilter();
    return filter;
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.addFilterBefore(corsFilter(), SessionManagementFilter.class).authorizeRequests().anyRequest().permitAll();
    http.csrf().disable();
}

我可以看到过滤器是通过调试调用的,但是即使设置了正确的 Access-Control-Allow-Origin,错误消息也会一直出现在客户端:

在此处输入图像描述

原文由 Sam 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

问题:

您没有正确配置 'Access-Control-Allow-Origin' 并且您当前的配置只是被服务器忽略。

情况:

错误堆栈跟踪说:

响应中的 'Access-Control-Allow-Origin' 标头的值不能是通配符 '*' 当请求的凭证模式为“include”时。因此不允许访问源“ http://localhost:4200 ”。

这意味着除了您无法将 'Access-Control-Allow-Origin' 设置为通配符 "*" ,您的域 'http://localhost:4200' 也不允许访问-

回答你的问题:

当我已经在 WebSocketConfig 中将允许的来源设置为客户端域时,我该如何解决这个问题?

解决方案:

我想你不需要在 WebSocketConfig 中设置允许的来源,因为它意味着 在 web 应用程序中配置 WebSocket 样式的消息传递,Spring 文档中的 WebSocket 支持 所述,你需要在 CORSFilter 配置类,因为它旨在为 Web 应用程序访问配置 Spring 过滤器。

这是您在 CORSFilter.java 配置类中需要的:

 public class CORSFilter implements Filter {

    // This is to be replaced with a list of domains allowed to access the server
  //You can include more than one origin here
    private final List<String> allowedOrigins = Arrays.asList("http://localhost:4200");

    public void destroy() {

    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        // Lets make sure that we are working with HTTP (that is, against HttpServletRequest and HttpServletResponse objects)
        if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;

            // Access-Control-Allow-Origin
            String origin = request.getHeader("Origin");
            response.setHeader("Access-Control-Allow-Origin", allowedOrigins.contains(origin) ? origin : "");
            response.setHeader("Vary", "Origin");

            // Access-Control-Max-Age
            response.setHeader("Access-Control-Max-Age", "3600");

            // Access-Control-Allow-Credentials
            response.setHeader("Access-Control-Allow-Credentials", "true");

            // Access-Control-Allow-Methods
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");

            // Access-Control-Allow-Headers
            response.setHeader("Access-Control-Allow-Headers",
                "Origin, X-Requested-With, Content-Type, Accept, " + "X-CSRF-TOKEN");
        }

        chain.doFilter(req, res);
    }

    public void init(FilterConfig filterConfig) {
    }
}

你可以看到使用:

 private final List<String> allowedOrigins = Arrays.asList("http://localhost:4200");

设置允许访问服务器的域列表。

参考:

您可能需要查看 Spring Framework 中的 CORS 支持Enabling Cross Origin Requests for a RESTful Web Service 以进一步阅读相关内容。

原文由 cнŝdk 发布,翻译遵循 CC BY-SA 3.0 许可协议

这与您的弹簧或角度应用程序代码无关。

介绍你的问题

Access-Control-Allow-Origin 是 CORS (跨源资源共享) 机制的一部分,它为 Web 服务器提供跨域访问控制。它可以保护您的应用程序/站点免受 CSRF (跨站点请求伪造) 的侵害。

CORS / CSRF

问题

现在,如果我们仔细阅读您的错误

The value of the 'Access-Control-Allow-Origin' header in the response must
not be the wildcard '*' when the request's credentials mode is 'include'.
Origin 'http://localhost:4200' is therefore not allowed access.

它说 Access-Control-Allow-Origin 标头不能是通配符。

换句话说,现在您的后端表示来自整个网络的每个人都可以在我的站点上运行代码。

我们想要实现 的目标:将来源限制为仅您的前端应用程序 (ng2)。

解决方案 现在,因为您正在使用 Spring,所以我假设您将它与 Apache Tomcat 一起用作后端 Web 服务器。

CORS 在您的 web.conf(tomcat 文件夹)中定义为过滤器

找到这条线

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

并将 \* 更改为 http://localhost:4200

有关 Tomcat 中 CORS 配置的更多信息, 请阅读此

编辑(春季启动)

因为你用的是spring boot,你可以把cors的配置委托给框架。

请遵循 spring.io 上的本教程(如建议的 chsdk),以更好地掌握 spring boot 的 CORS 配置。

原文由 VikingCode 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏