Конечная точка Spring Boot @PostMapping не поражена, пока @GetMapping работает после добавления securityFilterChain

Я изучаю Spring Boot с помощью Spring Security, и у меня возникли проблемы с конечной точкой @PostMapping в моем AuthController. Конечная точка @GetMapping работает нормально, но конечная точка @PostMapping никогда не затрагивается. Я проверил запрос с помощью Postman, и все кажется правильным. Вот подробности:

Конфигурация безопасности (SecurityConfig):

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
    @Bean
    public UserDetailsService userDetailsService() {
        // Define your custom UserDetailsService implementation
        return new CustomUserDetailsService();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(req ->
                        req.requestMatchers(
                                        "/auth/**",
                                        "/css/**.css",
                                        "/js/**"
                                ).permitAll()
                                .anyRequest().authenticated()
                )
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
}

AuthController:

@RestController
@RequestMapping("/auth")
public class AuthController {
    @GetMapping("/test")
    public String test() {
        return "Testing GET in Auth Ctrl.";
    }

    @PostMapping("/login")
    public String login(@RequestBody AuthRequest authRequest) {
        try {
            if (authRequest.getUsername() == null || authRequest.getPassword() == null)
                throw new AuthenticationException("AuthRequest is empty");

            // Assuming successful authentication, you would normally return a JWT token here
            return "Login successful!";
        } catch (AuthenticationException e) {
            return "Login failed!";
        }
    }
}

@Data
@NoArgsConstructor
class AuthRequest {
    private String username;
    private String password;
}

CustomUserDetailsService:

@Service
public class CustomUserDetailsService implements UserDetailsService {
    private final Map<String, String> usersMap = new HashMap<>();

    @Autowired
    public CustomUserDetailsService() {
        // Initialize the usersMap with encoded passwords
        usersMap.put("ricky", "$2a$10$Dow1SE9N1XzFxXh3YDJIoO/b0Zi4DlCg8Up7X5DpIS9b/T/xkaHOO"); // password: 123
        usersMap.put("martin", "$2a$10$Dow1SE9N1XzFxXh3YDJIoO/b0Zi4DlCg8Up7X5DpIS9b/T/xkaHOO"); // password: 456
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (usersMap.containsKey(username)) {
            return new User(username, usersMap.get(username), new ArrayList<>()); // Empty authorities list
        }

        // If this is thrown, then we won't generate a JWT token.
        throw new UsernameNotFoundException(username + " not found.");
    }
}

Тестирование с помощью Postman:

URL: http://localhost:8080/auth/login Метод: ПОСТ Заголовки: Тип контента: application/json Тело: необработанный JSON. Пример тела:

{
    "username": "ricky",
    "password": "123"
}

Что я пробовал:

  1. Проверено, что конечная точка @GetMapping работает.
  2. Убедитесь, что запрос POST правильно отформатирован и отправлен с соответствующими заголовками.
  3. Проверено, разрешена ли конечная точка /auth/login в конфигурации безопасности.
  4. Добавлено ведение журнала запросов, чтобы узнать, получен ли запрос Spring.
  5. Упрощен контроллер, чтобы исключить другие потенциальные проблемы.

Проблема: Несмотря на описанные выше шаги, конечная точка @PostMapping никогда не попадает в систему, и сообщения об ошибках не регистрируются. Конечная точка @GetMapping работает нормально.

Дополнительная информация: pom.xml

Мы будем очень признательны за любые идеи или предложения о том, почему конечная точка @PostMapping не затрагивается!

Что значит «никогда не бить»? Какой код ответа HTTP вы получаете?

J Asgarov 08.07.2024 08:25

403 Запрещено, контроль отладки никогда не достигает конечной точки входа в контроллер аутентификации.

BeingSuman 08.07.2024 09:38
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
89
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

ну, конечно, он не дойдет до вашего метода, если фильтр безопасности Spring возвращает запрещенный :)

вам также следует проверить, ПОЧЕМУ вы получаете 403, установить уровень ведения журнала для отладки с помощью logging.level.org.springframework.security=DEBUG, чтобы вы увидели ошибку.

Я готов поспорить, что именно CSRF правильно не позволяет вам отправлять «опасные» запросы (фактически любой другой запрос, кроме GET) без токена CSRF.

CSRF Вариант 1 для приложений без сохранения состояния:

Настройте серверную часть для хранения токенов CSRF в файлах cookie.

   http.csrf(csrf -> csrf.csrfTokenRepository
            (CookieCsrfTokenRepository.withHttpOnlyFalse()));

Сначала вам следует отправить какой-то запрос (любой запрос), чтобы получить файл cookie CSRF (автоматически добавляется в ответ на вызов, у которого его еще нет) с именем (XSRF-TOKEN), а затем добавить значение этого файла. cookie в качестве заголовка X-XSRF-TOKEN вашего POST-вызова. Смотрите здесь


CSRF Вариант 2 отключает CSRF, если у вашего приложения нет сеанса:

Если вы не используете файлы cookie для аутентификации и не используете сеанс, вы также можете рассмотреть возможность отключения CSRF, поскольку вам не нужна защита CSRF без сеанса / файлов cookie

   http
       .csrf(AbstractHttpConfigurer::disable)
       // ...

Действительно спасибо за помощь. Но я сталкиваюсь со странной ошибкой, когда в AuthController происходит вызов authenticationManager.authenticate. Вот репозиторий [ссылка] (github.com/codesuman/spring-auth/blob/basic-security/src/ma‌​in/… ). Подробности об ошибке: AuthenticationManager выдает StackOverflowError?

BeingSuman 08.07.2024 18:21

Пожалуйста, создайте новый вопрос, а затем пришлите мне ссылку, чтобы я мог посмотреть — я не могу давать ответы в комментариях (недостаточно места). Я отвечал на аналогичный вопрос неделю назад - посмотрите

J Asgarov 08.07.2024 20:15

Спасибо за помощь, проблема решена. AuthenticationProvider не был настроен и возвращал ноль — отсюда и исключение.

BeingSuman 12.07.2024 05:03

Возможно, потому, что ваш «/login» не разрешен в RequestMatchers. Вы должны разрешить там «/login», чтобы выполнить ваш запрос на публикацию.

Другие вопросы по теме