我正在使用 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'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.
在研究了这个问题之后,看起来不可能同时设置选项 origins = * 和 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);
});
});
}
WebSocket配置
@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/聊天/信息?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();
}
}
更新
经过更多测试和研究后,问题似乎只发生在使用 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,错误消息也会一直出现在客户端:
原文由 Sam 发布,翻译遵循 CC BY-SA 4.0 许可协议
问题:
您没有正确配置
'Access-Control-Allow-Origin'
并且您当前的配置只是被服务器忽略。情况:
错误堆栈跟踪说:
这意味着除了您无法将
'Access-Control-Allow-Origin'
设置为通配符"*"
,您的域'http://localhost:4200'
也不允许访问-回答你的问题:
解决方案:
我想你不需要在
WebSocketConfig
中设置允许的来源,因为它意味着 在 web 应用程序中配置 WebSocket 样式的消息传递, 如 Spring 文档中的 WebSocket 支持 所述,你需要在CORSFilter
配置类,因为它旨在为 Web 应用程序访问配置 Spring 过滤器。这是您在
CORSFilter.java
配置类中需要的:你可以看到使用:
设置允许访问服务器的域列表。
参考:
您可能需要查看 Spring Framework 中的 CORS 支持 和 Enabling Cross Origin Requests for a RESTful Web Service 以进一步阅读相关内容。