如何使用SpringWebSocket拒绝基于用户权限的主题订阅
我正在实现一个stock应用程序的版本,其中服务器能够根据用户权限拒绝特定主题的主题订阅。 在SpringWebSocket中有什么方法可以做到这一点吗 例如: 在股票示例项目中,我们有3种工具的价格主题:苹果、微软、谷歌 并且有两个用户:User1,User2 User1应该可以访问苹果和微软 User2应该只能访问Google如何使用SpringWebSocket拒绝基于用户权限的主题订阅,spring,spring-security,websocket,publish-subscribe,spring-websocket,Spring,Spring Security,Websocket,Publish Subscribe,Spring Websocket,我正在实现一个stock应用程序的版本,其中服务器能够根据用户权限拒绝特定主题的主题订阅。 在SpringWebSocket中有什么方法可以做到这一点吗 例如: 在股票示例项目中,我们有3种工具的价格主题:苹果、微软、谷歌 并且有两个用户:User1,User2 User1应该可以访问苹果和微软 User2应该只能访问Google 如果用户1订阅了谷歌,他应该会收到拒绝的回复,之后消息不应该向他广播。多亏了Rossen Stoyanchev,我通过向入站频道添加拦截器成功地解决了这个问题。演示应
如果用户1订阅了谷歌,他应该会收到拒绝的回复,之后消息不应该向他广播。多亏了Rossen Stoyanchev,我通过向入站频道添加拦截器成功地解决了这个问题。演示应用程序中需要的更改如下: 更改websocket配置:
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(new TopicSubscriptionInterceptor());
}
拦截器是这样的:
public class TopicSubscriptionInterceptor extends ChannelInterceptorAdapter {
private static Logger logger = org.slf4j.LoggerFactory.getLogger(TopicSubscriptionInterceptor.class);
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor headerAccessor= StompHeaderAccessor.wrap(message);
if (StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())) {
Principal userPrincipal = headerAccessor.getUser();
if(!validateSubscription(userPrincipal, headerAccessor.getDestination()))
{
throw new IllegalArgumentException("No permission for this topic");
}
}
return message;
}
private boolean validateSubscription(Principal principal, String topicDestination)
{
if (principal == null) {
// unauthenticated user
return false;
}
logger.debug("Validate subscription for {} to topic {}",principal.getName(),topicDestination);
//Additional validation logic coming here
return true;
}
公共类TopicSubscriptionInterceptor扩展了ChannelInterceptor适配器{
私有静态记录器Logger=org.slf4j.LoggerFactory.getLogger(TopicSubscriptionInterceptor.class);
@凌驾
公共消息呈现(消息消息、消息通道){
StompHeaderAccessor headerAccessor=StompHeaderAccessor.wrap(消息);
if(StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())){
Principal userPrincipal=headerAccessor.getUser();
如果(!validateSubscription(userPrincipal,headerAccessor.getDestination()))
{
抛出新的IllegalArgumentException(“不允许此主题”);
}
}
返回消息;
}
私有布尔验证订阅(主体,字符串主题目标)
{
if(principal==null){
//未经验证的用户
返回false;
}
debug(“验证{}对主题{},principal.getName(),topicDestination的订阅”);
//这里有额外的验证逻辑
返回true;
}
}从Spring 5.x开始,如果您正在扩展
AbstractSecurityWebSocketMessageBrokerConfigure
,则覆盖以附加拦截器的正确方法是customizeClientInboundChannel
:
@Override
public void customizeClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new TopicSubscriptionInterceptor());
}
您好,我正在使用SpringWebSocket,与您面临类似的情况。你能告诉我调用headerAccessor.getHeader(“simpUser”)时的值在哪里吗。WebSockeThttpHeader只能在client-side.org.springframework.messaging.MessagingException中为头添加字符串值