Заголовок в ответе не должен быть подстановочным знаком "*", когда режим учетных данных запроса "включает",

Я использую Auth0 для моей аутентификации пользователей, чтобы разрешить вход в систему только пользователям с доступом к Spring (Boot) RestController. На данный момент я создаю функциональность сообщений в режиме реального времени, когда пользователи могут отправлять сообщения от клиента Angular 2 (localhost:4200) на сервер Spring (localhost: 8081) с помощью stompjs и sockjs.

При попытке создать Stomp-клиент и запуск соединения я получаю следующую консольную ошибку:

 The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request 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 для домена клиента?

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
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/чат/информация т = 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();
    }
}

UPDATE

После нескольких тестов и исследований кажется, что проблема возникает только с помощью Chrome. Проблема может быть связана с: https://github.com/sockjs/sockjs-node/issues/177

UPDATE

Я создал CORSFilter, например chsdk, и использовал метод addFilterBefore(): qaru.site/info/33420/....

@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

Проблема:

Вы не настраиваете 'Access-Control-Allow-Origin' правильно, и ваша текущая конфигурация просто игнорируется сервером.

Ситуация:

Трассировка стека ошибок говорит:

Значение заголовка 'Access-Control-Allow-Origin' в ответе не должно быть подстановочным символом '*', когда режим учетных данных запроса "include". Происхождение http://localhost:4200 ', следовательно, не допускается.

Это означает, что помимо того, что вы не можете установить 'Access-Control-Allow-Origin' подстановочный знак "*", ваш домен 'http://localhost:4200' также не имеет доступа.

Чтобы ответить на ваш вопрос:

Как я могу это решить, когда я уже установил разрешенное происхождение в WebSocketConfig в домен клиента?

Решение:

Я думаю, вам не нужно устанавливать разрешенное происхождение в WebSocketConfig, поскольку оно предназначено для настройки обмена сообщениями в стиле WebSocket в веб-приложениях, как указано в Поддержка WebSocket в Spring документации, вам необходимо настроить его в классе конфигурации CORSFilter, поскольку это означает настроить фильтры 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");

Чтобы установить список доменов, которым разрешен доступ к серверу.

Литература:

Возможно, вам нужно взглянуть на Поддержка CORS в Spring Framework и Включение запросов перекрестного происхождения для веб-службы RESTful для дальнейшего ознакомления с ней.

Ответ 2

Это не имеет никакого отношения к вашему приложению spring или angular.

Вступление к вашей проблеме
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 credentials mode is 'include'. 
Origin 'http://localhost:4200' is therefore not allowed access.

В нем говорится, что заголовок Access-Control-Allow-Origin не может быть подстановочным знаком.

Другими словами, теперь ваш back-end говорит, что все из всех веб-сайтов могут запускать код на моем сайте.

Что мы хотим достичь. Ограничьте исходное положение только вашим интерфейсом (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

для получения дополнительной информации о конфиге CORS в Tomcat прочитайте это

EDIT (spring загрузка)
Поскольку вы используете загрузку spring, вы можете делегировать конфигурацию корса в фреймворк.

Пожалуйста, следуйте этому руководству по spring.io (например, chsdk), чтобы лучше понять конфигурацию CORS с помощью spring ботинок.

Ответ 3

Просто добавьте .setAllowedOrigins("*") в конфигурацию webSocket.

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

Версия webSocket - 1.4.1.RELEASE, вы должны обновить свою версию, если метод не был показан.