Я создаю приложение, в котором аутентификация выполняется с помощью Spring Security для обработчиков HTTP, для HTTP я отключил защиту csrf, и теперь я хочу отключить csrf для весеннего веб-сокета, но я не могу понять, как это сделать, я уже пробовал много разных подходов, но, похоже, никто не работает. Если невозможно отключить csrf для WebSocket, как получить токен csrf? (Я попытался настроить конечную точку csrf для получения токена, но это не работает, и все руководства, которые я нашел, устарели) Заранее спасибо!
Конфигурация безопасности веб-сокета:
@Configuration
@EnableWebSocketSecurity
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Bean
AuthorizationManager<Message<?>> messageAuthorizationManager(
MessageMatcherDelegatingAuthorizationManager.Builder messages) {
messages.anyMessage().permitAll();
return messages.build();
}
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
Конфигурация безопасности:
@Configuration
@EnableWebSecurity(debug = true)
public class SecurityConfig {
@Autowired
private JwtFilter jwtFilter;
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity HTTP) throws Exception {
return http.addFilterBefore(jwtFilter, BasicAuthenticationFilter.class)
.cors(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/authenticate").permitAll()
.requestMatchers("/createchatroom").authenticated()
.requestMatchers("/public/*").permitAll()
.requestMatchers("/private/*").permitAll()
.requestMatchers("/ws/**").authenticated()
.requestMatchers("/register").permitAll()
.requestMatchers("/csrf").authenticated()
.requestMatchers("/addEmployeeToFavorites").hasAnyAuthority(EMPLOYEE.name(),
ADMIN.name())
.requestMatchers("/addChatRoomToFavorites")
.hasAnyAuthority(EMPLOYEE.name(), ADMIN.name())
.requestMatchers("/home").hasAnyAuthority(EMPLOYEE.name(), ADMIN.name()))
.build();
}
}
Да конечно есть версии пакетов: spring-boot-starter-security: 3.0.1 spring-boot-starter-websocket:3.0.1
Это не 2.7, .. вы уже где-то использовали " http.cors().and().csrf().disable() "? иначе я могу сформулировать ответ
Да, я использую его в конфигурации безопасности
По умолчанию Spring Security требует маркер CSRF в любом типе сообщения CONNECT. Это гарантирует, что только сайт, имеющий доступ к токену CSRF, сможет подключиться. Поскольку только один и тот же источник может получить доступ к токену CSRF, внешним доменам не разрешено устанавливать соединение.
Spring Security 4.0 представила поддержку авторизации для WebSockets через абстракцию Spring Messaging.
В Spring Security 5.8 эта поддержка была обновлена для использования API AuthorizationManager.
Чтобы настроить авторизацию с помощью конфигурации Java, просто включите аннотацию @EnableWebSocketSecurity и опубликуйте AuthorizationManager<Message<?>> bean-компонент или в XML используйте атрибут use-authorization-manager. Один из способов сделать это — использовать AuthorizationManagerMessageMatcherRegistry для указания шаблонов конечных точек следующим образом:
@Configuration
@EnableWebSocketSecurity
public class WebSocketSecurityConfig {
@Bean
AuthorizationManager<Message<?>> messageAuthorizationManager(MessageMatcherDelegatingAuthorizationManager.Builder messages) {
messages
.simpDestMatchers("/user/**").authenticated()
return messages.build();
}
}
На данный момент CSRF нельзя настроить при использовании @EnableWebSocketSecurity, хотя это, вероятно, будет добавлено в будущем выпуске.
Чтобы отключить CSRF, вместо использования @EnableWebSocketSecurity вы можете использовать поддержку XML или самостоятельно добавить компоненты Spring Security, например:
Джава
@Configuration
public class WebSocketSecurityConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new AuthenticationPrincipalArgumentResolver());
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
AuthorizationManager<Message<?>> myAuthorizationRules = AuthenticatedAuthorizationManager.authenticated();
AuthorizationChannelInterceptor authz = new AuthorizationChannelInterceptor(myAuthorizationRules);
AuthorizationEventPublisher publisher = new SpringAuthorizationEventPublisher(this.context);
authz.setAuthorizationEventPublisher(publisher);
registration.interceptors(new SecurityContextChannelInterceptor(), authz);
}
}
Веб.xml
<websocket-message-broker use-authorization-manager = "true" same-origin-disabled = "true">
<intercept-message pattern = "/**" access = "authenticated"/>
</websocket-message-broker>
С другой стороны, если вы используете legacy-websocket-configuration и хотите разрешить другим доменам доступ к вашему сайту, вы можете отключить защиту Spring Security. Например, в конфигурации Java вы можете использовать следующее:
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
...
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
Рекомендации
Спасибо за ваш ответ! Могу я спросить вас, как я могу сгенерировать токен csrf?
Привет! Не беспокойся. Попробуйте поискать реализацию csrf в этом: youtube.com/watch?v=roVG7Qgm4hU С уважением
Бро, если мой первоначальный ответ поможет, пожалуйста, поставь галочку, чтобы показать свою поддержку. Это важно как часть моей работы. Я буду признателен за вашу проверку.
Может быть, вы можете показать текущую конфигурацию безопасности? Используете ли вы новейшую загрузочную систему Spring Boot 2.7 или что вы используете?