当请求的凭据模式为“include”时,响应中的标头不能是通配符“*” [英] Header in the response must not be the wildcard '*' when the request's credentials mode is 'include'

查看:316
本文介绍了当请求的凭据模式为“include”时,响应中的标头不能是通配符“*”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

 当请求的凭据模式为include时,响应中的Access-Control-Allow-Origin标头的值不能是通配符*。因此不允许来源'http:// localhost:4200'访问。 XMLHttpRequest发起的请求的凭据模式由withCredentials属性控制。 

在研究了这个问题之后,看起来无法设置选项origins = *和credentials =同时是真的。当我已经将WebSocketConfig中允许的原点设置为客户端域时,如何解决这个问题?



Angular 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);
});
});
}

WebSocketConfig

  @Configuration 
@EnableWebSocketMessageBroker
公共类WebSocketConfig扩展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();
}
}

localhost:8081 / chat / info?t = 1490866768565

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

MessageController

 公共类MessageController {
@MessageMapping(/ chat)
@SendTo(/ topic / messages)
公共消息发送(消息消息)抛出异常{
返回新消息(message.getFrom(),message.getText());
}
}

SecurityConfig(暂时允许所有)

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

更新



经过一些更多的测试和研究后,问题似乎只发生在Chrome上。问题可能与以下内容有关:

解决方案

问题:



您没有配置'Access-Control-Allow-Origin'正确,服务器会忽略您当前的配置。



情况:



错误堆栈跟踪说:


值响应中的'Access-Control-Allow-Origin'标题不能是通配符'*'时请求的凭据模式是包含。因此,不允许访问 http:// localhost:4200




这意味着除了你不能将'Access-Control-Allow-Origin'设置为通配符这一事实*,您的域'http:// localhost:4200'也不允许访问。



回答你的问题:


如果我已经设置了,我该如何解决这个问题允许来自WebSocketConfig到客户端域的来源?


解决方案:



我想您不需要在 WebSocketConfig 中设置允许的来源,因为它意味着在Web中配置 WebSocket样式的消息传递应用程序,如 中所述Spring中的WebSocket支持 ocumentation ,你需要在 CORSFilter 配置类中配置它,因为它意味着配置Spring Filters for Web应用程序访问。



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

 公共类CORSFilter实现Filter {

//这将替换为允许访问服务器的域列表
//您可以包含多个一个来源这里
私人最终名单< String> allowedOrigins = Arrays.asList(http:// localhost:4200);

public void destroy(){

}

public void doFilter(ServletRequest req,ServletResponse res,FilterChain chain)抛出IOException,ServletException {
//让我们确保我们正在使用HTTP(即,针对HttpServletRequest和HttpServletResponse对象)
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-输入,接受,+X-CSRF-TOKEN);
}

chain.doFilter(req,res);
}

public void init(FilterConfig filterConfig){
}
}

您可以看到使用:

 私人最终名单< String> allowedOrigins = Arrays.asList(http:// localhost:4200); 

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



参考文献:



您可能需要查看 Spring Framework中的CORS支持 启用RESTful Web服务的跨域请求 ,以便进一步阅读。


I'm using Auth0 for my user authentication to only allow logged in users to access a Spring (Boot) RestController. At this point I'm creating a real-time message functionality where users can send messages from the Angular 2 client (localhost:4200) to the Spring server (localhost:8081) using stompjs and sockjs.

When trying to create a Stomp-client and starting a connection I receive the following console-error:

 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.

After researching this problem it looks like it is not possible to set the option origins = * and credentials = true at the same time. How can I resolve this when I've already set the allowed origin in the WebSocketConfig to the client domain?

Angular 2 component

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);
        });
    });
}    

WebSocketConfig

@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();
    }
}

localhost:8081/chat/info?t=1490866768565

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

MessageController

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

SecurityConfig (temporarily permits all)

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

UPDATE

After some more testing and researching it seems that the problem only happens using Chrome. Problem maybe related to: https://github.com/sockjs/sockjs-node/issues/177

UPDATE

I created the CORSFilter like chsdk mentioned and used the addFilterBefore() method: 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();
}

I can see that the Filter is called by debugging it but the error message keeps appearing on the clientside even if the correct Access-Control-Allow-Origin gets set:

解决方案

Problem:

You are not configuring 'Access-Control-Allow-Origin' correctly and your current configuration is simply ignored by the server.

Situation:

The Error stack trace says:

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.

It means that apart from the fact that you can't set 'Access-Control-Allow-Origin' to the wildcard "*", your domain 'http://localhost:4200' is not allowed access too.

To answer your question:

How can I resolve this when I've already set the allowed origin in the WebSocketConfig to the client domain?

Solution:

I guess you don't need to set the allowed origin in the WebSocketConfig because it's meant to configure WebSocket-style messaging in web applications as stated in WebSocket Support in Spring documentation, you will need to configure it in a CORSFilter configuration class as it's meant to configure Spring Filters for Web application access.

This is what you will need in your CORSFilter.java configuration class:

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) {
    }
}

You can see the use of :

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

To set the list of domains allowed to access the server.

References:

You may need to take a look at CORS support in Spring Framework and Enabling Cross Origin Requests for a RESTful Web Service for further reading about it.

这篇关于当请求的凭据模式为“include”时,响应中的标头不能是通配符“*”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆