Springboot - websocket 未经授权的 401 与 JWT 身份验证
Springboot - websocket unauthorized 401 with JWT authentication
在我的项目中,我通过 JWT 令牌对登录用户进行身份验证。我也在为聊天模块创建网络套接字,但我无法与后端建立连接(我的前端很好,我可以连接到我发现的示例 here。在作者代码中,聊天和身份验证是单独的 springboot 项目,而我想将它放在一个地方。
我已经配置了 WebSecurityConfig
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private UserDetailsService jwtUserDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable()
.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll()
.and()
.authorizeRequests().antMatchers("/authenticate").permitAll().
and().
authorizeRequests().antMatchers("/ws").permitAll().
// ...
anyRequest().authenticated().
and().
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
我的 websocket 配置文件:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/user");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/ws")
.setAllowedOrigins("*")
.withSockJS();
}
@Override
public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
DefaultContentTypeResolver resolver = new DefaultContentTypeResolver();
resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON);
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setObjectMapper(new ObjectMapper());
converter.setContentTypeResolver(resolver);
messageConverters.add(converter);
return false;
}
}
我这里也配置了 CORS:
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true) //edited, added this.
.allowedHeaders("*")
.allowedOrigins("*");
}
};
}
}
如您所见,我想我已经处理了 cors 工作所需的东西,headers 和来源是允许的,添加了 authorizeRequests().antMatchers("/ws").permitAll().
以确保这个端点没有被验证,并且但是有些东西坏了。我是 websockets 的新手,如果我搞砸了一些基本的东西,我很抱歉,我只是无法在网上找到合适的解决方案。
编辑: 我在 corsConfigurer 中添加了缺失的 .allowCredentials(true)
,现在控制台将请求标记为非失败请求,而是未授权请求(我想步骤更好。 ..)
实际上,由于我错误地使用了 httpSecurity configure(),因此授权无法正常工作。
我变了
and().
authorizeRequests().antMatchers("/ws").permitAll().
至:
and().
authorizeRequests().antMatchers("/ws/**").permitAll().
因此不会检查此端点的所有子项,从而消除 401 响应。
在我的项目中,我通过 JWT 令牌对登录用户进行身份验证。我也在为聊天模块创建网络套接字,但我无法与后端建立连接(我的前端很好,我可以连接到我发现的示例 here。在作者代码中,聊天和身份验证是单独的 springboot 项目,而我想将它放在一个地方。 我已经配置了 WebSecurityConfig
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private UserDetailsService jwtUserDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable()
.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll()
.and()
.authorizeRequests().antMatchers("/authenticate").permitAll().
and().
authorizeRequests().antMatchers("/ws").permitAll().
// ...
anyRequest().authenticated().
and().
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
我的 websocket 配置文件:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/user");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/ws")
.setAllowedOrigins("*")
.withSockJS();
}
@Override
public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
DefaultContentTypeResolver resolver = new DefaultContentTypeResolver();
resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON);
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setObjectMapper(new ObjectMapper());
converter.setContentTypeResolver(resolver);
messageConverters.add(converter);
return false;
}
}
我这里也配置了 CORS:
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true) //edited, added this.
.allowedHeaders("*")
.allowedOrigins("*");
}
};
}
}
如您所见,我想我已经处理了 cors 工作所需的东西,headers 和来源是允许的,添加了 authorizeRequests().antMatchers("/ws").permitAll().
以确保这个端点没有被验证,并且但是有些东西坏了。我是 websockets 的新手,如果我搞砸了一些基本的东西,我很抱歉,我只是无法在网上找到合适的解决方案。
编辑: 我在 corsConfigurer 中添加了缺失的 .allowCredentials(true)
,现在控制台将请求标记为非失败请求,而是未授权请求(我想步骤更好。 ..)
实际上,由于我错误地使用了 httpSecurity configure(),因此授权无法正常工作。 我变了
and().
authorizeRequests().antMatchers("/ws").permitAll().
至:
and().
authorizeRequests().antMatchers("/ws/**").permitAll().
因此不会检查此端点的所有子项,从而消除 401 响应。