根据以下配置,与 "/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/