복붙노트

[SPRING] 요청의 자격 증명 모드가 '포함'인 경우 응답의 헤더는 와일드 카드 '*'가 아니어야합니다.

SPRING

요청의 자격 증명 모드가 '포함'인 경우 응답의 헤더는 와일드 카드 '*'가 아니어야합니다.

내 사용자 인증을 위해 Auth0을 사용하여 로그인 한 사용자 만 Spring (Boot) RestController에 액세스하도록 허용합니다. 이 시점에서 저는 사용자가 stompjs와 sockjs를 사용하여 Angular 2 클라이언트 (localhost : 4200)에서 Spring 서버 (localhost : 8081)로 메시지를 보낼 수있는 실시간 메시지 기능을 만들고 있습니다.

Stomp-client를 만들고 연결을 시작할 때 다음과 같은 콘솔 오류가 발생합니다 :

 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.

이 문제를 연구 한 후에 동시에 originins = * 및 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);
        });
    });
}    

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 (일시적으로 모두 허용)

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이 설정된 경우에도 오류 메시지가 클라이언트 측에 계속 표시됩니다.

해결법

  1. ==============================

    1.문제:

    문제:

    'Access-Control-Allow-Origin'을 올바르게 구성하지 않아 현재 구성이 서버에서 무시됩니다.

    상태:

    오류 스택 추적 :

    와일드 카드 "*"에 'Access-Control-Allow-Origin'을 설정할 수 없다는 점 외에도 도메인 'http : // localhost : 4200'에도 액세스가 허용되지 않습니다.

    귀하의 질문에 대답하려면 :

    해결책:

    아마 WebSocketConfig에 허용 된 출처를 설정할 필요는 없다고 생각합니다. WebSocketConfig는 Spring 설명서의 WebSocket Support에 명시된대로 웹 응용 프로그램에서 WebSocket 스타일의 메시징을 구성하기위한 것이기 때문에 CORSFilter 구성 클래스에서 구성해야합니다. 웹 응용 프로그램 액세스를위한 스프링 필터를 구성합니다.

    이것은 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");
    

    서버에 액세스하도록 허용 된 도메인 목록을 설정합니다.

    참고 문헌 :

    스프링 프레임 워크의 CORS 지원과 RESTful 웹 서비스에 대한 교차 원점 요청 활성화에 대한 추가 정보가 필요합니다.

  2. ==============================

    2.이것은 스프링 또는 각도 앱 코드와 아무 관련이 없습니다.

    이것은 스프링 또는 각도 앱 코드와 아무 관련이 없습니다.

    문제 소개 Access-Control-Allow-Origin은 웹 서버에 도메인 간 액세스 제어를 제공하는 CORS (Cross-Origin Resource Sharing) 메커니즘의 일부입니다. 앱 / 사이트를 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에서 백엔드 웹 서버로 사용한다고 가정합니다.

    CORS는 web.conf (tomcat 폴더)에서 필터로 정의됩니다.

    이 줄을 찾아라.

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

    *를 http : // localhost : 4200으로 변경하십시오.

    Tomcat의 CORS 구성에 대한 자세한 내용은 다음을 참조하십시오.

    EDIT (스프링 부트) 스프링 부트를 사용하기 때문에 프레임 구성에 cors 구성을 위임 할 수 있습니다.

    스프링 부트로 CORS 설정을 더 잘 이해하려면 spring.io (chsdk 제안) 튜토리얼을 따르십시오.

  3. ==============================

    3.내 대답은 너무 늦었지만, 누군가가 똑같은 문제에 직면 할 수 있다면 나는 이것을 게시 할 것이다. 나는 같은 공통 기원 문제에 직면 해왔다.

    내 대답은 너무 늦었지만, 누군가가 똑같은 문제에 직면 할 수 있다면 나는 이것을 게시 할 것이다. 나는 같은 공통 기원 문제에 직면 해왔다.

    기본적으로 서버 측 애플리케이션에 구현 된 스프링 보안을 사용하는 경우, 아마도 웹 소켓 핸드 셰이커를 차단하는 사람 일 것입니다

    당신은 소켓 핸드 쉐이크를 허용하기 위해 웹 보안 엔드 포인트가 허용하도록 Spring 보안에 지시해야합니다 ... ~을 사용하여

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

    따라서 sockjs는 이제 Websocket 프로토콜로 전환하기 전에 핸드 셰이크에 대한 GET (HTTP) 요청을 보낼 수 있습니다.

    이것은 스프링 보안 구성입니다.

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

    이것은 WebSocket Broker 구성입니다.

    @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");
        }
    }
    
  4. ==============================

    4..setAllowedOrigins ( "*")를 webSocket config에 추가하기 만하면됩니다.

    .setAllowedOrigins ( "*")를 webSocket config에 추가하기 만하면됩니다.

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

    webSocket의 버전은 1.4.1입니다. 릴리스가 표시되지 않으면 버전을 업데이트해야합니다.

  5. from https://stackoverflow.com/questions/43114750/header-in-the-response-must-not-be-the-wildcard-when-the-requests-credentia by cc-by-sa and MIT license