programing

요청의 자격 증명 모드가 '포함'인 경우 응답의 헤더는 와일드카드 '*'이 되어서는 안 됩니다.

bestprogram 2023. 10. 14. 10:23

요청의 자격 증명 모드가 '포함'인 경우 응답의 헤더는 와일드카드 '*'이 되어서는 안 됩니다.

사용하고 있습니다.Auth0합니다 Spring팅) 수 하는 내 인증에 됩니다.RestController가 . 에서 수 Angular 2localhost:4200하여 Spring 서버(localhost:8081) 합니다를 :8081)에합니다.stompjs그리고.sockjs.

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.

이 문제를 조사한 결과 옵션 오리진 = * 및 자격 증명 = 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);
        });
    });
}    

웹소켓구성

@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}

메시지컨트롤러

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

갱신하다

몇 가지 테스트와 연구를 더 해본 결과 크롬에서만 문제가 발생하는 것 같습니다.문제는 다음과 관련이 있을 수 있습니다. 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이 설정되더라도 클라이언트 측에 오류 메시지가 계속 나타납니다.

enter image description here

문제:

를(를) 구성하고 있지 .'Access-Control-Allow-Origin'정확하게 그리고 현재 구성은 단순히 서버에 의해 무시됩니다.

상황:

Error stack trace는 다음과 같이 말합니다.

의 입니다.'Access-Control-Allow-Origin'다가 .'*'요청의 자격 증명 모드가 'include'인 경우.따라서 오리진 'http://localhost:4200'은(는) 접근이 허용되지 않습니다.

수 는 말입니다.'Access-Control-Allow-Origin'"*", 'http://localhost:4200'접근도 허용되지 않습니다.

질문에 대답하기

WebSocketConfig에서 허용된 오리진을 클라이언트 도메인으로 이미 설정했는데 어떻게 해결할 수 있습니까?

해결책:

에 될 것 .WebSocketConfig애플리케이션에서 WebSocket Support in Spring 문서에 명시된 대로 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");

서버에 액세스할 수 있는 도메인 목록을 설정합니다.

참조:

자세한 내용을 보려면 Spring Framework의 CORS 지원과 RESTful 서비스대한 교차 오리진 요청 활성화를 확인해야 할 수도 있습니다.

이것은 당신의 스프링이나 각진 앱 코드와는 아무런 관련이 없습니다.

합니다.
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가 제안한 것과 같이) 이 자습서를 따르십시오.

제 대답은 너무 늦었지만 누군가가 같은 문제에 직면할 수 있다면 이 글을 올립니다. 저는 같은 origin 간 문제에 직면해 있었습니다.

기본적으로 서버측 애플리케이션에 구현된 Spring Security를 사용하는 경우 웹소켓 핸드셰이커를 차단하는 것은 아마도 그일 것입니다.

소켓 핸드셰이크를 허용하려면 웹소켓 엔드포인트를 허용하라고 Spring 보안부에 말해야 합니다.사용.

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

따라서 sockjs는 이제 웹소켓 프로토콜로 전환하기 전에 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");
    }
}

당신은 아래와 같이 당신의 코르를 구성하기만 하면 됩니다.

Othorize OPTION 방법을 수업시간에 제시하였습니다.

    @Component
public class CORSFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String origin = request.getHeader("Origin");
        response.setHeader("Access-Control-Allow-Origin", origin );

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

        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "authorization, content-type, xsrf-token, Sec-Fetch-Mode, Sec-Fetch-Site, Sec-Fetch-Dest");
        response.addHeader("Access-Control-Expose-Headers", "xsrf-token");
        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            filterChain.doFilter(request, response);
        }
    }

이 코드에 주의하세요.브라우저에서 첫 번째 OPTION 요청을 리디렉션하기 때문입니다.

if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            filterChain.doFilter(request, response);
        }

이 구성 라인에서 자격 증명을 허용합니다.

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

그리고 이 라인에서 모든 오리진을 수락하면 브라우저 오리진을 해제하는 것이 권장되지는 않습니다.

String origin = request.getHeader("Origin");
        response.setHeader("Access-Control-Allow-Origin", origin );

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

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

웹소켓의 버전은 1.4.1입니다.릴리스, 메서드가 표시되지 않았다면 버전을 업데이트해야 합니다.

언급URL : https://stackoverflow.com/questions/43114750/header-in-the-response-must-not-be-the-wildcard-when-the-requests-credentia