我正在尝试使用SockJS连接到主题,但是得到的响应是401未经授权。该项目包含带有JWT身份验证的Spring安全性。通过互联网搜索,我发现我应该在拦截器中对用户进行身份验证。问题是没有到达我的拦截器。
没有Spring安全性,在POC(概念验证)应用程序中一切正常。
希望我能正确地描述问题,在此先感谢。
对用户进行身份验证的拦截器:
@Component
@RequiredArgsConstructor
public class SocketAuthenticationInterceptor implements ChannelInterceptor {
private final JwtTokenProvider tokenProvider;
private final UserDetailsServiceImpl userDetailsService;
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor =
MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
List<String> authorization = accessor.getNativeHeader("Authorization");
String jwt = authorization.get(0);
final Integer userId = tokenProvider.getUserIdFromJWT(jwt);
final UserDetails userDetails = userDetailsService.loadUserById(userId);
final UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
accessor.setUser(authentication);
}
return message;
}
}
注册拦截器:
@Configuration
@RequiredArgsConstructor
@EnableWebSocketMessageBroker
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class WebSocketAuthenticationConfig implements WebSocketMessageBrokerConfigurer {
private final SocketAuthenticationInterceptor socketAuthenticationInterceptor;
@Override
public void configureClientInboundChannel(final ChannelRegistration registration) {
registration.interceptors(socketAuthenticationInterceptor);
}
}
过滤器完成对Web请求的用户身份验证。默认情况下,有一堆筛选器尝试对任何请求进行身份验证。请注意,此身份验证是在握手过程中以及发送初始CONNECT
消息之前完成的。 CustomInterceptor
用于处理我们收到的消息not for AuthN,因为过滤器本身正在取消对请求的身份验证,因此甚至没有收到消息,因此执行未到达拦截器。因此,像这样编写您自己的自定义过滤器类]
class JwtRequestFilter extends OncePerRequestFilter {
...
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String requestTokenHeader = request.getHeader("Authorization");
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
}
final Integer userId = tokenProvider.getUserIdFromJWT(jwtToken);
final UserDetails userDetails = userDetailsService.loadUserById(userId);
final UsernamePasswordAuthenticationToken authentication =new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
//If you want to set source details
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
然后将此自定义过滤器添加到过滤器列表中,就像在WebSecurityConfig.java
中这样>>
@Override protected void configure(HttpSecurity httpSecurity) throws Exception { ... // Add a filter to validate the tokens with every request httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); // Or any other filter of your choice }
因此,您的身份验证上下文已设置。有用的链接: