Невозможно получить доступ к конечным точкам отдыха даже после успешного входа в систему Spring Security через форму реагирования

Я пытаюсь реализовать аутентификацию входа в систему при весенней загрузке, я использовал Spring безопасность и использовал форму реагирования во внешнем интерфейсе для аутентификации, я использую axios для вызова моего /login, который работает хорошо, форма открывается и аутентифицируется отлично, но проблема заключается здесь заключается в том, что после успешного входа в систему я не могу получить доступ к другим конечным точкам, объявленным в моем контроллере Spring

Это моя конфигурация безопасности Spring

   @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        return http
                .authorizeHttpRequests(auth->auth
                        .requestMatchers("/","/login/**","/register")
                        .permitAll()
                        .anyRequest()
                        .authenticated())
                .logout(logout->logout
                        .logoutUrl("/logout")
                        .logoutSuccessUrl("/")
                        .deleteCookies("JSESSIONID")
                        .invalidateHttpSession(true))
                .csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(session->session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
                .build();
    }

Мой контроллер входа

    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody RegisterUser registerUser) {
        try {
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(registerUser.getEmail(), registerUser.getPassword())
            );
            if (authentication.isAuthenticated()) {
                return ResponseEntity.ok().body("Login successful");
            } else {
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Login failed");
            }
        } catch (AuthenticationException e) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Login failed");
        }
        
    }

Это моя форма реакции

axios.defaults.baseURL = "http://localhost:8080"
axios.defaults.withCredentials=true;

const Login=()=>{
    const [email, setEmail]=React.useState('');
    const [password, setpassword]=React.useState('');
    const [error, setError] = React.useState('');
    const navigate =useNavigate();

    const handlesubmit= async (e)=>{
        e.preventDefault();
        try {
            const response = await axios.post("/login" ,{
                email,
                password,
            });

            if (response.status===200){
                console.error(email,password)
                navigate('/');
            }
            else {
                navigate('/logs')
            }
        }
        catch (e){
            console.error(e)
            setError("login failed")
        }
    }

Пробовал использовать login->login.form("/login") и loginprocesssurl("/login") в конфигурации безопасности, но не работает, я также установил прокси-сервер на порт, на котором работает Spring, но у меня нет результатов

Теперь я хочу, чтобы после успешного входа в систему (это так) я хочу получить доступ к другим конечным точкам, доступ к которым могут получить только прошедшие проверку подлинности пользователи.

Невозможно получить доступ — бесполезное описание. Какую именно ошибку или симптомы вы видите?

aled 21.07.2024 02:50

@aled не может получить доступ даже после успешного входа в систему, когда я дохожу до конечной точки /mydata я получаю 404

Pretham 21.07.2024 06:47

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

Toerktumlare 21.07.2024 21:44

@Toerktumlare, блин, я написал это на простом английском с хорошим описанием, я ничего не могу поделать, если ты не можешь решить, в любом случае я нашел свое собственное решение и нашел способ его обойти

Pretham 22.07.2024 08:02
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
4
82
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

В пользовательской конечной точке отсутствует одна небольшая деталь: SecurityContext не заполняется во время запроса/ответа на вход. Без его сохранения дальнейшие запросы будут анонимными, несмотря на успешную аутентификацию.

Предпочтительный способ — использовать логику входа в SecurityFilterChain:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
            .authorizeHttpRequests(...)
            .formLogin(it -> it
                .loginPage("/") // mapped to index.html, letting react handle it
                .loginProcessingUrl("/login")
                .successHandler((request, response, authentication) -> {
                    response.setStatus(HttpStatus.OK.value());
                    response.getWriter().print("Login successful");
                })
                .failureHandler((request, response, exception) -> {
                    response.sendError(HttpStatus.UNAUTHORIZED.value(), "Login failed");
                })
            )
            .logout(...)
            ...
            .build();
}

Почему это? Он добавляет дополнительный UsernamePasswordAuthenticationFilter, который содержит логику аутентификации вашей конечной точки @PostMapping("/login") + , в которой хранится SecurityContext в ThreadLocal. Позже он сохраняется с помощью SecurityContextRepository в другом фильтре по цепочке. (Обратите внимание: начиная с версии 6 требуется явное сохранение)

Если вы действительно хотите контролировать процесс входа в свою конечную точку (возможно, из-за некоторых побочных эффектов), сохраните контекст там:

...
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody RegisterUser registerUser) {
try {
    Authentication authentication = authenticationManager.authenticate(
        new UsernamePasswordAuthenticationToken(registerUser.getEmail(), registerUser.getPassword())
            );
            if (authentication.isAuthenticated()) {

                // storing context in ThreadLocal, later will be saved in SecurityContextPersistenceFilter
                SecurityContext context = SecurityContextHolder.createEmptyContext();
                context.setAuthentication(authentication);
                SecurityContextHolder.setContext(context);

                return ResponseEntity.ok().body("Login successful");
            } else {
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Login failed");
            }
        } catch (AuthenticationException e) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Login failed");
        }
        
    }
...

Привет, я опробовал ваш код, но, похоже, он все еще не работает. Когда я добавил форму входа в цепочку фильтров безопасности, аутентификация формы не удалась и меня перенаправили, даже если данные для входа неверны, но даже в этом случае я не могу получить доступ к другие конечные точки, это дает мне 404

Pretham 21.07.2024 08:40

Подскажите, пожалуйста, какая версия Spring Security? Да, он перенаправляет даже в случае сбоя, потому что вы проверяете его на response.status===200 в своей форме реагирования (при этом в ответе есть статус 403). Другие URL-адреса верны? Нет префикса типа «/api»? Я спрашиваю, как вы получите 404, а не 403 или 200. Будет ли еще присутствовать 404, если у вас .anyRequest().permitAll()?

lo-fi wi-fi 21.07.2024 20:09

Привет, когда я выполнил Anyrequest().permitall(), я получил доступ к другой конечной точке API, спасибо, но я нашел собственное решение. Я разрешил Spring Security разрешать/разрешать весь доступ к API, но теперь, когда защищенный конечные точки не защищены. Я реализовал JWT на стороне реагирования, когда вход в систему успешно выполнен со стороны Spring, я устанавливаю JWT в своем локальном хранилище реагирования и аутентифицирую, защищаю и защищаю все API, работает как шарм, я не знаю, хорошая ли это практика но это работает!

Pretham 22.07.2024 08:11

это не так, потому что использование JWT в браузере не рекомендуется, вы не можете выходить из системы. Но удачи

Toerktumlare 22.07.2024 18:50

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