Spring WebSockets с функцией Spring Security ChannelInterceptor.presend, не вызываемой в WebStomp.connect - PullRequest
0 голосов
/ 04 марта 2020

Я использую Spring Boot 2.1.8 и пытаюсь реализовать микросервис websocket с безопасностью OAuth2. Я пытался посмотреть на другие подобные вопросы на Stackoverflow. У меня проблема с моим ChannelInterceptor.presend, который не запускается на ws Connect. Я хотел бы иметь возможность авторизовать пользователя из JWT OAuth2 в параметре запроса.

Я использую wscat для тестирования моего сервиса с помощью команды

$ wscat -c ws://177.15.32.34:8080/collaboration?access_token=xxx.yyy.zzz

Он подключится fine и ChannelInterceptor.presend никогда не будет вызываться до тех пор, пока websocket не закроется, а затем не будет захвачен обмен сообщениями WebStomp.DISCONNECT.

Код ниже. Я ценю любые идеи и указания.

@SpringBootApplication
public class MyApplication {

  public static void main(String[] args) {
    SpringApplication.run(MyApplication.class, args);
  }
}
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
@Component
public class AuthChannelInterceptor implements ChannelInterceptor {

  @Override
  public Message<?> preSend(Message<?> message, MessageChannel channel) {

    final StompHeaderAccessor accessor =
        MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

    if (StompCommand.CONNECT.equals(accessor.getCommand())) {
      System.out.println("preSend called");
    }
    return message;
  }
}
@Configuration
@EnableWebSocketMessageBroker
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

  @Value("${stomp.endPoint}")
  private String stompEndpoint;

  @Override
  public void configureClientInboundChannel(ChannelRegistration registration) {
    registration.interceptors(new AuthChannelInterceptor());
  }

  @Override
  public void configureMessageBroker(MessageBrokerRegistry registry) {
    registry
    .enableSimpleBroker("/queue", "/topic");
  }

  @Override
  public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
    stompEndpointRegistry
        .addEndpoint("collaboration")
        .setAllowedOrigins("*");
  }

  @Bean
  public CorsFilter corsFilter() {

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true); // you USUALLY want this
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("OPTIONS");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
  }
}
@Configuration
@EnableWebSecurity(debug = true)
@Order(PriorityOrdered.HIGHEST_PRECEDENCE + 500)
public class ResourceServerWebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    DefaultBearerTokenResolver resolver = new DefaultBearerTokenResolver();
    resolver.setAllowUriQueryParameter(true);

    http.sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authorizeRequests()
        .antMatchers(HttpMethod.GET, "/collaboration")
        .permitAll();
  }
}
@Configuration
public class WebSocketSecurityConfigurer extends AbstractSecurityWebSocketMessageBrokerConfigurer {

  @Override
  protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {

    messages.simpTypeMatchers(CONNECT, UNSUBSCRIBE, DISCONNECT, HEARTBEAT).permitAll()
                .simpDestMatchers("/**")
                .authenticated();


  }

  @Override
  protected boolean sameOriginDisabled() {
    return true;
  }
}

1 Ответ

0 голосов
/ 09 марта 2020

Мне все еще не удается заставить ChannelInterceptor правильно работать для аутентификации веб-сокетов. В итоге я снова использовал BearerTokenAuthenticationFilter, но сконфигурировал его для обработки токенов в качестве параметра запроса. В моем WebsecurityConfigurerAdapter я создал следующие bean-компоненты и затем вставил их в цепочку фильтров безопасности, как показано ниже.

@EnableWebSecurity
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

  @Bean
  public JwtDecoder jwtDecoder() {
    NimbusJwtDecoderJwkSupport jwtDecoder =
        (NimbusJwtDecoderJwkSupport) JwtDecoders.fromOidcIssuerLocation(issuerUri);

    return jwtDecoder;
  }

  @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
  public AuthenticationManager myAuthenticationManager() {
    //copied from OAuth2ResourceServerSecurityConfiguration
    JwtAuthenticationProvider authenticationProvider = new JwtAuthenticationProvider(jwtDecoder());
    authenticationProvider.setJwtAuthenticationConverter(new JwtAuthenticationConverter());
    return authenticationProvider::authenticate;
  }

  @Bean("DefaultBearerTokenResolver")
  public DefaultBearerTokenResolver getDefaultBearerTokenResolver() {
    DefaultBearerTokenResolver defaultBearerTokenResolver = new DefaultBearerTokenResolver();
    defaultBearerTokenResolver.setAllowUriQueryParameter(true);
    return defaultBearerTokenResolver;
  }

  @Bean("BearerTokenAuthenticationFilter")
  public BearerTokenAuthenticationFilter getBearerTokenAuthFilter() {
    AuthenticationManager authenticationManager = myAuthenticationManager();
    BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(authenticationManager);
    filter.setBearerTokenResolver(getDefaultBearerTokenResolver());

    AuthenticationEntryPoint authenticationEntryPoint = new BearerTokenAuthenticationEntryPoint();
    filter.setAuthenticationEntryPoint(authenticationEntryPoint);

    return filter;
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {

    http
            .anonymous().disable()
            .logout().disable()
            .csrf().disable()
            .formLogin().disable()
            .addFilterAfter(getBearerTokenAuthFilter()
                    , SecurityContextHolderAwareRequestFilter.class )
            .authorizeRequests()
        .anyRequest()
        .authenticated();
  }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...