Spring Security - различайте неверную комбинацию имени пользователя и пароля и неавторизованных пользователей - PullRequest
0 голосов
/ 12 июня 2019

В приложении Spring Boot + Spring Security я написал собственный AuthenticationProvider.Он выполняет аутентификацию на другом сервере, который содержит информацию об именах пользователей и их паролях.

Пока все работает нормально - с помощью failureUrl(String) на formLogin() в конфигурации безопасности я могу сказать людям, что они использовали недопустимые комбинации имени пользователя и пароля.Spring также автоматически перенаправляет неавторизованные запросы в форму входа.

Однако существует вероятность того, что пользователь предоставит правильную комбинацию имени пользователя и пароля, но ему все равно просто не разрешат использовать приложение.Такой пользователь, конечно же, не должен получать такой же отзыв о «неправильном имени пользователя / пароле», поскольку это может сбить его с толку.В моем AuthenticationProvider есть какой-нибудь способ или, возможно, в конфигурации безопасности я могу каким-то образом реализовать различие между этими двумя вариантами?До сих пор я не вижу никакого способа, возвращая нуль в AuthenticationProvider, заставляет Spring предполагать, что это «сбой» и, таким образом, просто перенаправляет на путь, указанный в failureUrl(String).

Ответы [ 4 ]

1 голос
/ 12 июня 2019

Я бы предложил вам провести различие между аутентификацией и авторизацией. Пользователь с действительными учетными данными должен всегда проходить проверку подлинности. В доступе по-прежнему может быть отказано из-за отсутствия авторизации.

Итак, как насчет предоставления роли «ПОЛЬЗОВАТЕЛЬ» всем пользователям, которым действительно разрешено использовать ваше приложение, и настройке вашего приложения так, чтобы эта роль требовалась для определенных запросов, например:

protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()                   
        .antMatchers("/api/**").hasRole("USER")                                                            
        .anyRequest().authenticated()                                                               
        .and()
        // ...
        .httpBasic();   
}
1 голос
/ 13 июня 2019

Spring Security поддерживает этот сценарий, используя два разных интерфейса.

AuthenticationFailureHandler

Spring Security использует этот API, чтобы определить, как бороться с ошибкой аутентификации (например, плохие кредиты). Очень часто хочется перенаправить обратно на страницу входа в систему, поэтому это происходит по умолчанию. Тем не менее, вы можете настроить его с помощью

http
    .formLogin()
        .failureUrl(myUrl)

или

http
    .formLogin()
        .failureHandler(myFailureHandler)

для более сложных нужд.

AccessDeniedHandler

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

По умолчанию Spring Security возвращает 403, но его также можно настроить как страницу отказа в доступе:

http
    .exceptionHandling()
        .accessDeniedPage(myAccessDeniedPage)

или

http
    .exceptionHandling()
        .accessDeniedHandler(myAccessDeniedHandler)

для более сложных нужд.

Ваш AuthenticationProvider должен просто сосредоточиться на аутентификации пользователя - вы можете бросить AuthenticationException, чтобы указать на сбой. UsernamePasswordAuthenticationFilter позаботится о подборе URL-адреса ошибки, а ExceptionTranslationFilter - странице отказа в доступе.

0 голосов
/ 13 июня 2019

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

public class UnauthorizedException extends AuthenticationException {

    public UnauthorizedException(String msg) {
        super(msg);
    }

}

Важно расширить AuthenticationException Spring Security, если вы используете его из своей реализации AuthenticationProvider. Просто используйте это как:

throw new UnauthorizedException("Unauthorized to use this application.");

Возможно, вы захотите локализовать сообщение.

Такое исключение будет помещено в сеанс в атрибуте с именем SPRING_SECURITY_LAST_EXCEPTION. Если вы, например, используете Thymeleaf, вы можете напечатать сообщение следующим образом:

<p data-th-if="${param.error != null and session.SPRING_SECURITY_LAST_EXCEPTION != null}"
   data-th-text="${session.SPRING_SECURITY_LAST_EXCEPTION.message}">
</p>
0 голосов
/ 12 июня 2019

Надеюсь, это поможет вам

    @RequestMapping(value = "/login")
public String getLoginPage(@RequestParam(name = "error", required = false) String error, Model model,
        @RequestParam(name = "logout", required = false) String logout) {
    if (error != null) {
        model.addAttribute("message", "Invalid Username or Password");
    }
    if (logout != null) {
        model.addAttribute("logout", "You have Successfully Logged Out");
    }

    return "login";
}

@RequestMapping(value = "/logout-user")
public String logout(HttpServletRequest request, HttpServletResponse response) {
    // fetch the authentication object
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null) {
        // logout and clear out the session and remove the authentication from the
        // security context
        new SecurityContextLogoutHandler().logout(request, response, auth);
    }
    return "redirect:/login?logout";
}

Spring-security configuration

<http>

    <intercept-url pattern="/**" access="permitAll" />
    <!-- navigate to login url -->
    <form-login login-page="/login" username-parameter="username"
        password-parameter="password" />
    <!-- access forbidden for unauthorized user -->
    <access-denied-handler error-page="/access-denied" />
    <csrf />
</http>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...