У меня есть приложение SpringBoot, работающее на Java 17 с Maven, использующее SpringBoot 3.2.4 и Spring Security 6. Я развернул его на железной дороге вместе с базой данных MySQL. Развертывание прошло успешно, но я столкнулся с проблемой, из-за которой запросы POST не работают, а запросы GET работают правильно. В моем локальном режиме все работает отлично, но запросы POST на железной дороге не работают. Ниже приведен мой код SecurityConfig с SecurityFilterChain:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
private final JwtUtils jwtUtils;
public SecurityConfig(final JwtUtils jwtUtils) {
this.jwtUtils = jwtUtils;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.csrf(AbstractHttpConfigurer::disable)
.cors(AbstractHttpConfigurer::disable)
.httpBasic(Customizer.withDefaults())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(http -> {
// public endpoints
http.requestMatchers(HttpMethod.POST, "/api/v1/auth/sign-up").permitAll();
http.requestMatchers(HttpMethod.POST, "/api/v1/auth/log-in").permitAll();
http.requestMatchers(HttpMethod.POST, "/api/v1/auth/new-password").permitAll();
http.requestMatchers(HttpMethod.POST, "/api/v1/auth/test").permitAll();
http.requestMatchers(HttpMethod.POST, "/api/v1/auth/test-body").permitAll();
http.requestMatchers(HttpMethod.GET, "/api/v1/auth/test").permitAll();
// private endpoints
http.requestMatchers(HttpMethod.POST, "/api/v1/auth/unlock").hasRole("GERENTE");
})
.addFilterBefore(new JwtTokenValidator(jwtUtils), BasicAuthenticationFilter.class)
.build();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public AuthenticationProvider authenticationProvider(UserDetailsServiceImpl userDetailsService) {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder(passwordEncoder());
provider.setUserDetailsService(userDetailsService);
return provider;
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
Это моя производственная среда на железной дороге: Архитектура
Журналы, когда я пытаюсь выполнить запрос POST и от Postman получаю код 401: Наблюдательность
Я пробовал включать и отключать CORS и CSRF, но у меня это не работает. Я хочу понять, почему я сталкиваюсь с этой ошибкой и что мне нужно добавить, включить или отключить, чтобы мои POST-запросы работали.
ОБНОВЛЯТЬ
Добавление сопоставителя запросов: http.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll(); И использование https:// вместо http:// решит проблему.
Чтобы решить проблему с неработающими POST-запросами в вашем развертывании Railway, вы можете попробовать следующие решения в своем коде:
Явно разрешить запросы OPTIONS. Иногда проблемы с CORS (совместное использование ресурсов между источниками) могут вызывать проблемы с запросами POST. Убедитесь, что ваше приложение разрешает запросы OPTIONS, которые часто представляют собой предварительные запросы, отправляемые браузерами для проверки, разрешает ли сервер фактический запрос. Добавьте .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() в свой метод авторизацииHttpRequests.
Обновите конфигурацию CSRF. Хотя вы уже отключили защиту CSRF в SecurityConfig, стоит еще раз проверить, отключена ли она во всех частях вашего приложения. Убедитесь, что защита CSRF отключена глобально, добавив .csrf().disable() в вашу конфигурацию httpSecurity.
Проверьте наличие перенаправлений. Иногда перенаправления могут вызывать проблемы с запросами POST, особенно когда они меняют метод запроса. Убедитесь, что ваше приложение не перенаправляет запросы POST на другую конечную точку, требующую аутентификации. Вы можете настроить Spring Security так, чтобы он игнорировал определенные URL-адреса для перенаправления, используя .permitAll() для этих URL-адресов.
Проверьте аутентификацию и авторизацию: дважды проверьте логику аутентификации и авторизации, чтобы убедиться, что пользователи правильно аутентифицированы и авторизованы для доступа к конечным точкам POST. Убедитесь, что токены JWT генерируются и анализируются правильно, а также что роли и разрешения правильно назначены пользователям.
Ведение журнала и отладка. Добавьте в свое приложение дополнительные операторы журналирования, чтобы отслеживать поток запросов и выявлять любые ошибки или непредвиденное поведение. Используйте режим отладки в своей IDE или платформы ведения журналов, такие как Logback или Log4j, чтобы получить подробную информацию о том, что происходит внутри вашего приложения.
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final JwtUtils jwtUtils;
public SecurityConfig(final JwtUtils jwtUtils) {
this.jwtUtils = jwtUtils;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.cors().disable()
.httpBasic(Customizer.withDefaults())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeRequests(authorize -> authorize
.antMatchers(HttpMethod.POST, "/api/v1/auth/sign-up").permitAll()
.antMatchers(HttpMethod.POST, "/api/v1/auth/log-in").permitAll()
.antMatchers(HttpMethod.POST, "/api/v1/auth/new-password").permitAll()
.antMatchers(HttpMethod.POST, "/api/v1/auth/test").permitAll()
.antMatchers(HttpMethod.POST, "/api/v1/auth/test-body").permitAll()
.antMatchers(HttpMethod.GET, "/api/v1/auth/test").permitAll()
.antMatchers(HttpMethod.POST, "/api/v1/auth/unlock").hasRole("GERENTE")
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // Allow OPTIONS requests
.anyRequest().authenticated()
)
.addFilterBefore(new JwtTokenValidator(jwtUtils), BasicAuthenticationFilter.class);
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public AuthenticationProvider authenticationProvider(UserDetailsServiceImpl userDetailsService) {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder(passwordEncoder());
provider.setUserDetailsService(userDetailsService);
return provider;
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
Эти изменения должны помочь обеспечить правильную работу ваших POST-запросов в вашем развертывании Railway. Обязательно тщательно протестируйте после внесения этих изменений. Если проблема не устранена, продолжайте отладку и исследование других потенциальных причин.
Я использую Spring Security 6, а WebSecurityConfigurerAdapter уже устарел. Я добавил разрешение запросов OPTIONS, но на железной дороге это все равно не работает. Локально все работает нормально, включая JWT.