Spring Security& Websockets - 未为帧处理程序设置身份验证

时间:2017-12-01 00:49:57

标签: java spring spring-security websocket spring-websocket

鉴于以下配置,与"/connect"的初始websocket握手成功进行基本身份验证。但是,当我通过活动websocket发送帧时,我得到以下异常:org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext

当我从@PreAuthorize "/sendMessage"中删除WebsocketController注释时,我没有收到异常。 Spring文档说明初始HTTP握手中的Authentication应该在SecurityContext中为未来的websocket框架设置,但这似乎不会自动发生。

我应该如何为websocket连接设置Authentication

@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);
    }
}

1 个答案:

答案 0 :(得分:0)

Spring WebSockets似乎不支持SpringSecurity注释,因此必须使用以下命令配置安全性:

@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

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