Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带STOMP的Spring MVC WebSocket-针对特定通道进行身份验证_Spring_Spring Mvc_Websocket_Stomp_Spring Websocket - Fatal编程技术网

带STOMP的Spring MVC WebSocket-针对特定通道进行身份验证

带STOMP的Spring MVC WebSocket-针对特定通道进行身份验证,spring,spring-mvc,websocket,stomp,spring-websocket,Spring,Spring Mvc,Websocket,Stomp,Spring Websocket,在AbstractWebSocketMessageBrokerConfigure(Spring Boot)中是否有方法拦截特定频道的用户注册 我在注册表中使用握手手柄进行了基本身份验证: @Override public void registerStompEndpoints(StompEndpointRegistry registry) { HandshakeHandler handler = new DefaultHandshakeHandler() { @Override

AbstractWebSocketMessageBrokerConfigure
(Spring Boot)中是否有方法拦截特定频道的用户注册

我在
注册表中使用握手手柄进行了基本身份验证:

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
   HandshakeHandler handler = new DefaultHandshakeHandler() {
      @Override
      protected Principal determineUser(ServerHttpRequest request, 
            WebSocketHandler wsHandler, Map<String, Object> attributes) {
       Principal principal = request.getPrincipal();
       if (principal == null) {
         return () -> getPrincipal();
       }
       return principal;
     }
   };
   registry.addEndpoint("/websocket")
    .setHandshakeHandler(handler)
    .setAllowedOrigins("*").withSockJS();
}
@覆盖
公共无效注册表TompendPoints(StompEndpointRegistry注册表){
HandshakeHandler handler=新的DefaultHandshakeHandler(){
@凌驾
受保护的主体确定器(ServerHttpRequest请求,
WebSocketHandler(wsHandler,映射属性){
Principal=request.getPrincipal();
if(principal==null){
return()->getPrincipal();
}
返还本金;
}
};
registry.addEndpoint(“/websocket”)
.SetHandsheHandler(处理程序)
.setAllowedOrigins(“*”).withSockJS();
}
现在,如果该用户没有“admin”权限,我想阻止该用户注册到“/topic/admin/news”。我没有使用Spring Security。我想在注册频道之前安装一个拦截器

作为替代方案,我希望使用
SimpMessagingTemplate
仅从具有权限的频道向用户发送消息。有没有办法查看哪些用户当前连接到我的stomp连接

public void configureClientInboundChannel(ChannelRegistration registration) {
    registration.setInterceptors(new TopicSubscriptionInterceptor());
}
拦截机:

public class TopicSubscriptionInterceptor implements ChannelInterceptor {

private static Logger logger = org.slf4j.LoggerFactory.getLogger(TopicSubscriptionInterceptor.class);

@Override
public Message<?> postReceive(Message<?> message, MessageChannel chanenel) {
    return message;
}

@Override
public void postSend(Message<?> message, MessageChannel chanel, boolean sent) {
}

@Override
public boolean preReceive(MessageChannel channel) {
    return true;
}

@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
    StompHeaderAccessor headerAccessor= StompHeaderAccessor.wrap(message);
    if (StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand()) && headerAccessor.getHeader("simpUser") !=null &&  headerAccessor.getHeader("simpUser") instanceof UsernamePasswordAuthenticationToken) {
        UsernamePasswordAuthenticationToken userToken = (UsernamePasswordAuthenticationToken) headerAccessor.getHeader("simpUser");
        if(!validateSubscription((User)userToken.getPrincipal(), headerAccessor.getDestination()))
        {
            throw new IllegalArgumentException("No permission for this topic");
        }
    }
    return message;
}

private boolean validateSubscription(User principal, String topicDestination)
{
    logger.debug("Validate subscription for {} to topic {}",principal.getUsername(),topicDestination);
    //Validation logic coming here
    return true;
}
}
公共类TopicSubscriptionInterceptor实现ChannelInterceptor{
私有静态记录器Logger=org.slf4j.LoggerFactory.getLogger(TopicSubscriptionInterceptor.class);
@凌驾
公共消息postReceive(消息消息、消息通道通道通道){
返回消息;
}
@凌驾
public void postSend(消息消息、消息通道通道通道、布尔发送){
}
@凌驾
公共布尔预接收(MessageChannel){
返回true;
}
@凌驾
公共消息呈现(消息消息、消息通道){
StompHeaderAccessor headerAccessor=StompHeaderAccessor.wrap(消息);
if(StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())和&headerAccessor.getHeader(“simpUser”)!=null和&headerAccessor.getHeader(“simpUser”)实例的用户名密码身份验证令牌){
UsernamePasswordAuthenticationToken userToken=(UsernamePasswordAuthenticationToken)headerAccessor.getHeader(“simpUser”);
如果(!validateSubscription((用户)userToken.getPrincipal(),headerAccessor.getDestination())
{
抛出新的IllegalArgumentException(“不允许此主题”);
}
}
返回消息;
}
私有布尔验证订阅(用户主体,字符串主题目标)
{
debug(“验证{}对主题{}的订阅”,principal.getUsername(),topicDestination);
//验证逻辑来了
返回true;
}
}
拦截机:

public class TopicSubscriptionInterceptor implements ChannelInterceptor {

private static Logger logger = org.slf4j.LoggerFactory.getLogger(TopicSubscriptionInterceptor.class);

@Override
public Message<?> postReceive(Message<?> message, MessageChannel chanenel) {
    return message;
}

@Override
public void postSend(Message<?> message, MessageChannel chanel, boolean sent) {
}

@Override
public boolean preReceive(MessageChannel channel) {
    return true;
}

@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
    StompHeaderAccessor headerAccessor= StompHeaderAccessor.wrap(message);
    if (StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand()) && headerAccessor.getHeader("simpUser") !=null &&  headerAccessor.getHeader("simpUser") instanceof UsernamePasswordAuthenticationToken) {
        UsernamePasswordAuthenticationToken userToken = (UsernamePasswordAuthenticationToken) headerAccessor.getHeader("simpUser");
        if(!validateSubscription((User)userToken.getPrincipal(), headerAccessor.getDestination()))
        {
            throw new IllegalArgumentException("No permission for this topic");
        }
    }
    return message;
}

private boolean validateSubscription(User principal, String topicDestination)
{
    logger.debug("Validate subscription for {} to topic {}",principal.getUsername(),topicDestination);
    //Validation logic coming here
    return true;
}
}
公共类TopicSubscriptionInterceptor实现ChannelInterceptor{
私有静态记录器Logger=org.slf4j.LoggerFactory.getLogger(TopicSubscriptionInterceptor.class);
@凌驾
公共消息postReceive(消息消息、消息通道通道通道){
返回消息;
}
@凌驾
public void postSend(消息消息、消息通道通道通道、布尔发送){
}
@凌驾
公共布尔预接收(MessageChannel){
返回true;
}
@凌驾
公共消息呈现(消息消息、消息通道){
StompHeaderAccessor headerAccessor=StompHeaderAccessor.wrap(消息);
if(StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())和&headerAccessor.getHeader(“simpUser”)!=null和&headerAccessor.getHeader(“simpUser”)实例的用户名密码身份验证令牌){
UsernamePasswordAuthenticationToken userToken=(UsernamePasswordAuthenticationToken)headerAccessor.getHeader(“simpUser”);
如果(!validateSubscription((用户)userToken.getPrincipal(),headerAccessor.getDestination())
{
抛出新的IllegalArgumentException(“不允许此主题”);
}
}
返回消息;
}
私有布尔验证订阅(用户主体,字符串主题目标)
{
debug(“验证{}对主题{}的订阅”,principal.getUsername(),topicDestination);
//验证逻辑来了
返回true;
}
}

正是我想要的。干杯,这正是我想要的。干杯