Обработчик сбоя входа в систему безопасности Webflux не работает

#java #spring #security #spring-webflux #reactive

#ява #весна #Безопасность #пружина-webflux #реактивный #spring-webflux

Вопрос:

Я пытаюсь настроить с помощью пользовательских строковых сообщений Spring webflux security, если вход / выход из системы был успешным или произошел сбой. Обработчики работают, за исключением «authenticationFailureHandler».

В документах упоминается что-то о «logoutSuccessUrl()», но оно не существует, и эти обработчики возвращаются с Mono< Void > .

Итак, у меня есть 2 вопроса:

  • Как мне вернуть некоторую строку в качестве ответа, например, если аутентификация завершается с ошибкой, тогда что-то вроде «Недопустимое имя пользователя или пароль» или какая-либо строка json. Я пытался перенаправить на действие, но я не могу сделать это с помощью void Mono.

  • Почему authenticationFailureHandler не работает, а любой другой обработчик работает? Это ошибка?

-Я попытался перенаправить с помощью Mono.just(«redirect:/some-url»).then(), но это ничего не дало. Для ответов

  • Я создал свои обработчики bean, попытался изменить последовательность методов, отключив / включив другие обработчики. Для обработчика ошибок аутентификации.

Вы можете найти весь мой код здесь:https://github.com/iron2414/WebFluxAuth

Это модифицированная версия кода из этой статьи:https://medium.com/@mgray_94552/reactive-authorisation-in-spring-security-943e6534aaeb

Конфигурация безопасности выглядит следующим образом:

  return http
                .exceptionHandling()
                .accessDeniedHandler((swe, e) -> {
                    System.out.println("ACCESS DENIED");
                    return Mono.fromRunnable(() -> {
                        swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                    });
                })
                .authenticationEntryPoint((swe, e) -> {
                    System.out.println("AUTHENTICATION ENTRTY POINT");
                    ServerHttpResponse response = swe.getResponse();
                    return Mono.fromRunnable(() -> {
                        swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                    });
                })
                .and()
                .authorizeExchange()
                .pathMatchers("/**").authenticated()
                .and()
                .formLogin()
                .authenticationFailureHandler(MyAuthenticationFailureHandler()) 

    .authenticationSuccessHandler(MyAuthenticationSuccessHandler()).and()
                .logout().logoutSuccessHandler(MyLogoutHandler())
                .and()
                .csrf()
                .disable()
                .build();
  

Обработчик loginFailure:

     @Bean
    public MyAuthenticationFailureHandler MyAuthenticationFailureHandler() {
        return new MyAuthenticationFailureHandler();
    }


  
 @Component
public class MyAuthenticationFailureHandler implements ServerAuthenticationFailureHandler {

    @Override
    public Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException e) {
        //TODO redirect
        System.out.println("AUTHENTICATION FAILURE");
        return Mono.empty();
    }
}
  

Комментарии:

1. Я создал полнофункциональный пример проекта, реализующего webflux webflux-security, он содержит полный рабочий процесс об обработчиках success failure, вы можете посмотреть здесь: github.com/eriknyk/webflux-jwt-security-demo

Ответ №1:

Для ответа мне пришлось использовать «RedirectServerAuthenticationSuccessHandler» для успешной аутентификации. И я создал точно такой же класс, который реализует сбой.

Не работает обработчик сбоя авторизации — известная проблема. Чтобы заставить его работать, вы должны установить loginpage. Поэтому я просто обновил его до значения по умолчанию «/ login»

Комментарии:

1. эта проблема все еще не решена. но ваш трюк для страницы входа работает 🙂 спасибо

Ответ №2:

Я столкнулся с той же проблемой и в конечном итоге использовал пользовательский defaulterrororwebexceptionhandler для ее решения:

 
@Component
public class MyGlobalWebExceptionHandler extends DefaultErrorWebExceptionHandler {

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return route(all(), this::renderErrorResponse);
    }

    @Override
    protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
        ErrorRepresentation representation = createErrorRepresentation(request);
        return ServerResponse
                .status(representation.getError().getStatus())
                .contentType(APPLICATION_JSON_UTF8)
                .body(BodyInserters.fromObject(representation));
    }

    private ErrorRepresentation createErrorRepresentation(ServerRequest request) {
        boolean includeStackTrace = isIncludeStackTrace(request, MediaType.ALL);
        Map<String, Object> error = getErrorAttributes(request, includeStackTrace);
        Throwable throwable = getError(request);


        if (throwable instanceof AuthenticationException) {
            AuthenticationFailureException failureException = new AuthenticationFailureException(throwable.getMessage());
            return new ErrorRepresentation(failureException, error.get("path").toString());
        }

    }
}