我使用Auth0
进行用户身份验证,只允许登录的用户访问Spring (Boot) RestController
。此时,我正在创建一个实时消息功能,用户可以在其中使用stompjs
和sockjs
将消息从Angular 2
客户机(localhost:4200
)发送到Spring服务器(本地主机: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.
研究此问题后,似乎不可能同时设置选项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);
});
});
}
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/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,错误消息也一直出现在客户端:
发布于 2017-04-14 16:32:27
这与您的spring或angular应用程序代码无关。
问题的简介
Access-Control-Allow-Origin是CORS (跨域资源共享)机制的一部分,该机制为web服务器提供跨域访问控制。它可以保护您的应用程序/站点免受CSRF (跨站点请求伪造)的攻击。
The problem
现在如果我们仔细阅读你的错误
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)。
Solution现在,因为您使用的是Spring,所以我将假定您将它与Apache Tomcat一起使用作为后端with服务器。
CORS被定义为web.conf (tomcat文件夹)中的过滤器
找到这一行
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
并将*更改为http://localhost:4200
有关Tomcat please read this中CORS配置的详细信息,请参阅
编辑( Spring boot )
因为您使用的是spring boot,所以可以将cors的配置委托给框架。
请关注this tutorial on spring.io (就像chsdk建议的那样),以更好地掌握使用spring boot的CORS配置。
发布于 2018-02-19 03:07:05
我的回答太晚了,但我发布了这篇文章,如果有人能面临同样的问题,我也一直面临着同样的跨来源问题。
基本上,如果您使用在服务器端应用程序上实现的Spring Security,那么很可能是他阻止了websocket握手程序
为了允许套接字握手,您必须告诉Spring security允许您的websocket端点...使用
.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
@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");
}
}
发布于 2017-07-03 19:11:35
只需在webSocket配置中添加.setAllowedOrigins("*")
即可。
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/yourEndpoint");
stompEndpointRegistry.addEndpoint("/yourEndpoint").setAllowedOrigins("*").withSockJS();
}
webSocket的版本是1.4.1.RELEASE,如果没有显示该方法,您应该更新版本。
https://stackoverflow.com/questions/43114750
复制相似问题