java - Spring Security 和 Websockets - 未为框架处理程序设置身份验证

标签 java spring spring-security websocket spring-websocket

根据以下配置,与 "/connect" 的初始 Websocket 握手通过基本身份验证成功。但是,当我通过 Activity 的 websocket 发送帧时,出现以下异常:org.springframework.security.authentication.AuthenticationCredentialsNotFoundException:在 SecurityContext 中找不到身份验证对象

当我从 WebsocketController 中的 "/sendMessage" 中删除 @PreAuthorize 注释时,我没有收到异常。 Spring 文档表示,应在 SecurityContext 中为 future 的 Websocket 框架设置初始 HTTP 握手中的身份验证,但这似乎不会自动发生。

我应该如何为 websocket 连接设置身份验证

@Configuration
@EnableWebSocket
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config){
        config.enableStompBrokerRelay("/outbound");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/connect").withSockJS();
    }
}

//...............

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthenticationProvider authProvider;

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .anyRequest().authenticated()
            .and().httpBasic()
        ;
    }

    @Autowired
    public void configureAuthentication(final AuthenticationManagerBuilder authBuilder) throws Exception {
        authBuilder.authenticationProvider(authProvider);
    }
}

//.............

@Controller
public class WebSocketController {

    // This fails despite successful websocket handshake
    @MessageMapping("/sendMessage")
    @SendTo("/outbound/message")
    @PreAuthorize("hasRole('USER')")
    public Message message(@Payload Message message) {
        return "web socket message";
    }

    // This HTTP call succeeds
    @RequestMapping("/httpEndpoint")
    @PreAuthorize("hasRole('USER')")
    public @ResponseBody String doSomething(){
        return "some response";
    }

}

// ..................

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
        // all are valid
        return new UsernamePasswordAuthenticationToken(username, password, Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
    }

    @Override
    public boolean supports(final Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

最佳答案

Spring WebSockets 似乎不支持 SpringSecurity 注释,因此必须配置安全性:

@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    @Override
    protected void configureInbound(final MessageSecurityMetadataSourceRegistry messages) {
        messages.anyMessage().authenticated()
                .simpDestMatchers("/**").hasRole("USER")
        ;
    }
}

关于java - Spring Security 和 Websockets - 未为框架处理程序设置身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47585025/

相关文章:

java - SimpleMessageListenerContainer 批量消息处理

java - gerResources().getStringArray(R.array.string_name); <-- 不工作

java - 无法从客户端 x509 证书中检索主体

spring-boot - 认证2 : Spring Boot 2: Auth Server/oauth/check_token returns user_name as null

java - 如何保护 JpaRepository

java - 带有表单登录的 Spring Security OAuth 2

java - 在 Eclipse 插件中使用 Sqlite 数据库

java - 在 Java 中使用流对 2 个列表的项进行乘法和求和

java - 将文件重命名为当前日期和时间 Spring Batch

java - Spring MVC - 检查用户是否已经通过 Spring Security 登录?