Springboot-具有JWT身份验证的Websocket未经授权的401

时间:2020-11-03 15:31:37

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

在我的项目中,我通过JWT令牌对登录的用户进行身份验证。我还在为聊天模块创建Web套接字,但是我无法与后端建立连接(我的前端很好,我可以连接到我发现的一个示例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正常工作,允许标头和原点,并添加了authorizeRequests().antMatchers("/ws").permitAll().以确保此端点未得到验证,但是还是有问题。我是websocket的新手,所以很抱歉,如果我弄乱了一些基本知识,我只是无法在网上找到合适的解决方案。

编辑:我在corsConfigurer中缺少了.allowCredentials(true),现在控制台将请求标记为不是失败的请求,而是未授权的(我想是更好的选择...)

updated

1 个答案:

答案 0 :(得分:0)

实际上,由于我使用了不正确的httpSecurity configure(),因此授权不起作用。 我变了

 and().
 authorizeRequests().antMatchers("/ws").permitAll().

收件人:

 and().
 authorizeRequests().antMatchers("/ws/**").permitAll().

因此将不检查此端点的所有子级,从而消除401响应。