使用 WebSockets 的 Spring Security - 禁止 403
Posted
技术标签:
【中文标题】使用 WebSockets 的 Spring Security - 禁止 403【英文标题】:Spring Security with WebSockets - Forbidden 403 【发布时间】:2015-08-16 05:15:26 【问题描述】:我已经在 Spring 中实现了 WebSocket。一切正常,但最近我决定实施 Spring Security。
我的 MessageBroker 看起来像:
@Configuration
@EnableWebSocketMessageBroker
@Component("messageBroker")
public class MessageBroker implements WebSocketMessageBrokerConfigurer
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry)
stompEndpointRegistry.addEndpoint("/graphs").withSockJS();
@Override
public void configureMessageBroker(MessageBrokerRegistry messageBrokerRegistry)
@Override
public void configureClientInboundChannel(ChannelRegistration channelRegistration)
@Override
public void configureClientOutboundChannel(ChannelRegistration channelRegistration)
@Override
public boolean configureMessageConverters(List<MessageConverter> messageConverters)
messageConverters.add(new MappingJackson2MessageConverter());
return false;
我的 JS 客户端看起来像这样:
var socket = new SockJS('/server/graphs');
var client = Stomp.over(socket);
client.connect(, function (frame)
client.subscribe("/data", function (message)
console.log('GET MESSAGE :' + message.body);
var test = JSON.parse(message.body);
var point = [ (new Date()).getTime(), parseInt(25) ];
var shift = randomData.data.length > 60;
randomData.addPoint(point, true, shift);
);
);
Spring 安全配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:http auto-config='true' use-expressions="true" disable-url-rewriting="true">
<security:intercept-url pattern="/login/**" access="isAnonymous()"/>
<security:intercept-url pattern="/index/**" access="isAuthenticated()" />
<security:intercept-url pattern="/volumegraph/**" access="isAuthenticated()" />
<security:intercept-url pattern="/graphs/**" access="permitAll()" />
<security:intercept-url pattern="/graphs/**/**" access="permitAll()" />
<security:form-login login-page="/" login-processing-url="/" authentication-failure-url="/" always-use-default-target="true"/>
<security:csrf/>
<security:logout logout-success-url="/login"/>
<security:headers>
<security:frame-options></security:frame-options>
</security:headers>
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="user" password="password" authorities="ROLE_USER"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
通过我的 JS 客户端订阅后,我收到:
Opening Web Socket...
sockjs.js:1213 WebSocket connection to 'ws://localhost:8080/server/graphs/651/kyzdihld/websocket' failed: Error during WebSocket handshake: Unexpected response code: 404
sockjs.js:807 POST http://localhost:8080/server/graphs/651/zx7zdre7/xhr_streaming 403 (Forbidden)AbstractXHRObject._start @ sockjs.js:807(anonymous function) @ sockjs.js:834
sockjs.js:807 POST http://localhost:8080/server/graphs/651/o6eg5ikc/xhr 403 (Forbidden)AbstractXHRObject._start @ sockjs.js:807(anonymous function) @ sockjs.js:834
stomp.js:122 Whoops! Lost connection to undefined
所以我决定在安全配置中添加这段代码:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:websocket-message-broker>
<!--<security:intercept-message pattern="/graphs/**" access="permitAll()"/>-->
<security:intercept-message pattern="/**" access="permitAll()"/>
<security:intercept-message type="SUBSCRIBE" access="permitAll()"/>
<security:intercept-message type="CONNECT" access="permitAll()"/>
</security:websocket-message-broker>
</beans>
但之后我收到这种错误:
NoSuchBeanDefinitionException: No bean named 'springSecurityMessagePathMatcher' is defined
我不知道如何定义这样的 bean,所以我在下面的类中创建了这个:
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages)
messages.simpDestMatchers("/graphs/*").permitAll();
messages.simpDestMatchers("/**").permitAll();
但是在编译过程中我收到了这种错误:
java: cannot access org.springframework.beans.factory.SmartInitializingSingleton
class file for org.springframework.beans.factory.SmartInitializingSingleton not found
我真的不知道如何解决这个问题:(我必须补充一点,我正在使用 Spring Core 4.0.1.RELEASE 和 Spring Messaging 4.0.1.RELEASE。所有与 Spring Security 相关的库都在 4.0 版中。 1.释放。
【问题讨论】:
您的 MessageBroker 类的包是否用于组件扫描? 如果您使用@EnableCaching 是一个错误jira.spring.io/browse/SPR-12336,这会导致找不到SmartInitializingSingleton。你能上传完整的错误吗 我没有使用@EnableCaching @Jebil 是的,我认为是的。你可以在那里看到github.com/GarciaPL/CurrencyFair/blob/master/currencyfair/…,但事实并非如此。此应用程序已修改为不使用 MessageBroker 的安全性 您似乎没有将currencyfair-consumer-ctx.xml
添加到您的“web.xml”中,它也在资源文件夹中,而不是在WEB-INF
中。检查一下,我认为问题存在。
【参考方案1】:
为了让它工作,你必须修改你的<security:websocket-message-broker >
通过添加一些 id,<security:websocket-message-broker id="interceptor">
并将它链接到你的 websocket 入站通道的定义。
<websocket:message-broker application-destination-prefix="/app" user-destination-prefix="/user" >
<websocket:stomp-endpoint path="/websocketEndPoint" >
<websocket:handshake-handler ref="astalavista" />
<websocket:simple-broker prefix="/topic , /queue" />
<websocket:client-inbound-channel >
<websocket:interceptors>
<!--This will reference your interceptor that you have defined in you security XML-->
<ref bean="interceptor"/>
</websocket:interceptors>
</websocket:client-inbound-channel>
</websocket:message-broker>
【讨论】:
以上是关于使用 WebSockets 的 Spring Security - 禁止 403的主要内容,如果未能解决你的问题,请参考以下文章
对如何使用 Spring-websockets 进行 stomp 调用感到困惑
Spring-Websockets 4.2 中使用 SockJS 的部分消息
Spring 4 中 Websockets 的自定义对象映射器
使用 STOMP/WebSockets/Spring 从 @SubscribeMapping 返回原始字符串