在我的春季启动项目中,我在客户端和服务器之间建立了websocket连接。在服务器站点中使用自定义 ChannelInterceptor 的情况下,当stomp命令等于 CONNECT 时,我重写了 preSend 方法进行身份验证。
用户未通过身份验证时,我无法将带有异常类的消息或消息发送到客户端应用程序。
当我不对用户进行身份验证时,我在StompSession Frame标头中的消息下方的客户端应用程序中收到:
无法向ExecutorSubscribableChannel [clientInboundChannel]发送消息;嵌套的异常是org.springframework.security.access.AccessDeniedException:访问被拒绝
但是我希望那里有信息,为什么会因此拒绝访问。 AuthenticationCredentialsNotFoundException 或 BadCredentialsException 。
频道拦截器:
public class CustomChannelInterceptorAdapter implements ChannelInterceptor {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor =
MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (accessor.getCommand().equals(StompCommand.CONNECT)) {
WebSocketAuthenticatorService.getAuthenticatedOrFail(accessor.getLogin(), accessor.getPasscode());
/*above and below line is just mind shortcut. getAuthenticatedOrFail will
return UsernamePasswordAuthenticationToken or throw specific exception
for ex. AuthenticationCredentialsNotFoundException or BadCredentialsException */
if (userOK) {
accessor.setUser(user);
} else {
// send response to client with exception thrown above
}
}
return message;
}
}
安全配置:
AbstractSecurityWebSocketMessageBrokerConfigurer
@Configuration
public class WebSocketAuthorizationSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(final MessageSecurityMetadataSourceRegistry messages) {
messages.anyMessage().authenticated();
}
}
WebSecurityConfigurerAdapter
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("/register").permitAll()
.and()
.authorizeRequests().antMatchers("/gs-guide-websocket").permitAll()
.and()
.authorizeRequests().antMatchers("/actuator/info").permitAll()
.anyRequest().denyAll();
}
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder(10);
}
}
WebSocketMessageBrokerConfigurer
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class WebSocketAuthenticationSecurityConfig implements WebSocketMessageBrokerConfigurer {
@Autowired
CustomChannelInterceptorAdapter customChannelInterceptorAdapter;
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(customChannelInterceptorAdapter);
}
}
是否可以发送带有异常信息的消息?
或者也许我应该使用 hasRole 代替 AbstractSecurityWebSocketMessageBrokerConfigurer 中的经过身份验证,并为错误创建一个单独的主题并允许每个用户在那里连接?