Header in the response must not be the wildcard '*' when the request's credentials mode is 'include'

前端 未结 4 2153
一生所求
一生所求 2020-12-09 15:12

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 r

相关标签:
4条回答
  • 2020-12-09 15:18

    my answer is too late but i'm posting this if anyone could face the same problem, i've been facing the same cross-origin issue.

    Basically if you are using Spring Security implemented on your server side application, Probably it is he who blocks websocket handshaker

    You have to tell Spring security to allow your websocket endpoints in order to allow socket handshake... using

    .antMatchers("/socket/**").permitAll()
    

    So sockjs will be able now to send a GET (Http) request for handshaking before switching to Websocket protocol

    This is Spring security Configuration

    package org.souhaib.caremy.security.module.config;
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint).and()
                .authorizeRequests()
                .antMatchers(SecurityParams.PUBLIC_ROUTES).permitAll()
                .antMatchers("/socket/**").permitAll();
    
        http.csrf().disable();
    }}
    

    This is WebSocket Broker configuration

    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
    
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            registry.addEndpoint("/socket")
                    .setAllowedOrigins("http://localhost:4200")
                    .withSockJS();
        }
    
        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry) {
            registry.setApplicationDestinationPrefixes("/app")
                    .enableSimpleBroker("/chat");
        }
    }
    
    0 讨论(0)
  • 2020-12-09 15:24

    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.

    0 讨论(0)
  • 2020-12-09 15:24

    Just add .setAllowedOrigins("*") at webSocket config.

    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        stompEndpointRegistry.addEndpoint("/yourEndpoint");
        stompEndpointRegistry.addEndpoint("/yourEndpoint").setAllowedOrigins("*").withSockJS();
    }
    

    The version of webSocket is 1.4.1.RELEASE,you should update your version if the method wasn't shown.

    0 讨论(0)
  • 2020-12-09 15:33

    This has nothing to do with your spring or angular app code.

    Intro to your problem
    The Access-Control-Allow-Origin is a part of CORS (Cross-Origin Resource Sharing) mechanism that gives web servers cross-domain access controls. It is in place to protect your app/site from CSRF (Cross-Site Request Forgery).

    CORS / CSRF

    The problem
    Now if we read your error carefully

    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 says that Access-Control-Allow-Origin header cannot be a wildcard.

    With other words, now your back-end is saying everybody from allover the web can run code on my site.

    What we want to achieve: Limit the origin to only your front-end app (ng2).

    Solution Now because you are using Spring I will assume that you are using it with Apache Tomcat as your back-end webserver.

    CORS are difined as filter in your web.conf (tomcat folder)

    find this line

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

    and change the * to http://localhost:4200

    for more information about config of CORS in Tomcat please read this

    EDIT ( Spring boot )
    Because you are using spring boot, you can delegate configuration of cors to the framework.

    Please follow this tutorial on spring.io ( like chsdk proposed )to get a better grasp of CORS configuration with spring boot .

    0 讨论(0)
提交回复
热议问题