Я следую весеннему учебнику WebSocket https://spring.io/guides/gs/messaging-stomp-websocket/ и успешно заставил его работать над новым проектом. Затем я попытался добавить WebSocket в свой существующий проект, пока у него уже есть класс конфигурации SpringSecurity. Клиенты могут подключаться и подписываться на Websocket, и клиентские сообщения успешно принимаются на сервере Spring, но когда сервер Spring возвращает сообщение или отправляет сообщение клиентам, клиент не получает его. Я сомневаюсь, что существующая конфигурация безопасности блокирует исходящие сообщения. Если кто-то может указать, что не так, это будет очень полезно.
Моя конфигурация Websocket,
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
}
Контроллер похож на это,
@MessageMapping("/hello")
@SendTo("/topic/greetings")
public String greeting(String message) throws Exception {
this.template.convertAndSend("/topic/greetings", new Greeting("Hey !"));
return "Hello, " + HtmlUtils.htmlEscape(message) + "!";
}
Конфигурация безопасностикласс такой,
@SuppressWarnings("SpringJavaAutowiringInspection")
@Configuration
@EnableWebSecurity
@EnableScheduling
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(this.userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
return new JwtAuthenticationTokenFilter();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/ws/**");
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// we don't need CSRF because our token is invulnerable
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// don't create session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
//.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// allow anonymous resource requests
.antMatchers(
HttpMethod.GET,
"/",
"/v2/api-docs", // swagger
"/webjars/**", // swagger-ui webjars
"/swagger-resources/**", // swagger-ui resources
"/configuration/**", // swagger configuration
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/graphical/getFlowCount",
"/getAppVersion"
).permitAll()
.antMatchers("/socket/**").permitAll() // for testing purpose
.antMatchers("/auth/**").permitAll()
.antMatchers("/resetPassword").permitAll()
.antMatchers("/order/create_external").permitAll()
.antMatchers("/order/get_finished_workOrders_external").permitAll()
.anyRequest().authenticated();
// Custom JWT based security filter
httpSecurity
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
// disable page caching
httpSecurity.headers().cacheControl();
}
}