Как я могу получить имя пользователя от неудачного входа в систему с помощью Spring Security? - PullRequest
20 голосов
/ 30 декабря 2011

Мы используем Spring Security 3.0.5, Java 1.6 и Tomcat 6.0.32.В нашем XML-файле конфигурации у нас есть:

<form-login login-page="/index.html" default-target-url="/postSignin.html" always-use-default-target="true"
 authentication-failure-handler-ref="authenticationFailureHandler"/>

и наш authenticationFailureHandler, определенный как:

<beans:bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
   <beans:property name="exceptionMappings">
      <beans:props>
    <beans:prop key="org.springframework.security.authentication.BadCredentialsException">/index.html?authenticationFailure=true</beans:prop>
    </beans:props>
   </beans:property>
</beans:bean>

Java

    @RequestMapping(params={"authenticationFailure=true"}, value ="/index.html")
    public String handleInvalidLogin(HttpServletRequest request) {
       //...  How can I get the username that was used???
       // I've tried:
       Object username = request.getAttribute("SPRING_SECURITY_LAST_USERNAME_KEY");
       Object username = request.getAttribute("SPRING_SECURITY_LAST_USERNAME");  // deprecated
    }

Итак, мы направляем все BadCredentialsExceptions на index.html и IndexControllerIndexController я хотел бы получить username, который использовался для неудачной попытки входа в систему.Как я могу это сделать?

Ответы [ 7 ]

22 голосов
/ 30 декабря 2011

Хорошо, поэтому ответ оказался чем-то чрезвычайно простым, но, насколько я могу судить, не очень обсуждаемым или документированным.

Вот все, что мне нужно было сделать (нигде не было ни одной конфигурации, просто создал этот класс) ...

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationListener implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> {
    private static final Logger LOG = Logger.getLogger(MyApplicationListener.class);

    @Override
    public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) {
        Object userName = event.getAuthentication().getPrincipal();
        Object credentials = event.getAuthentication().getCredentials();
        LOG.debug("Failed login using USERNAME [" + userName + "]");
        LOG.debug("Failed login using PASSWORD [" + credentials + "]");
    }
}

Я далеко не эксперт по весенней безопасности, поэтому, если кто-то прочитает это и узнает причину, по которой мы не должны так поступать, или знает, как мне лучше узнать об этом.

16 голосов
/ 11 декабря 2014

Я сделал это следующим образом:

  1. Создан класс, который расширяет SimpleUrlAuthenticationFailureHandler

  2. Переопределяет метод onAuthenticationFailure, который получаетHttpServletRequest в качестве параметра.

  3. request.getParameter("username"), где "username" - это имя моего ввода в моей HTML-форме.

5 голосов
/ 30 декабря 2011

Вместо этого вы можете указать собственную версию DefaultAuthenticationEventPublisher и переопределить метод publishAuthenticationFailure.

2 голосов
/ 05 февраля 2018

Похоже, что об этом решении не так много информации, но если вы установите failForwardUrl в своей конфигурации Spring Security, вы будете перенаправлены на страницу с ошибкой, а не перенаправлены. Вы можете легко получить имя пользователя и пароль. Например, в вашем конфиге добавьте: .and().formLogin().failureForwardUrl("/login/failed") (* URL-адрес должен отличаться от URL-адреса страницы входа в систему)

И в вашем контроллере входа следующее:

@RequestMapping(value = "/login/failed")
public String loginfailed(@ModelAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_USERNAME_KEY) String user, @ModelAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY) String password) {
     // Your code here
}

SPRING_SECURITY_FORM_USERNAME_KEY, SPRING_SECURITY_FORM_PASSWORD_KEY являются именами по умолчанию, но вы также можете установить их в FormLoginConfigurer:

.and().formLogin().usernameParameter("email").passwordParameter("password").failureForwardUrl("/login/failed")
1 голос
/ 14 февраля 2019

Если вы хотите использовать Spring AOP, вы можете добавить следующий код в свой класс Aspect:

private String usernameParameter = "username"; 

@Before("execution(* org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure(..))")
public void beforeLoginFailure(JoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = (HttpServletRequest) joinPoint.getArgs()[0];
        AuthenticationException exceptionObj = (AuthenticationException) joinPoint.getArgs()[2];

        String username = request.getParameter(usernameParameter);

        System.out.println(">>> Aspect check: AuthenticationException:  "+exceptionObj.getMessage());
        System.out.println(">>> Aspect check: user: "+ username + " failed to log in.");
}
1 голос
/ 07 июня 2012

Я нашел это работает для меня.К сожалению, я до сих пор не нашел точное местоположение этого в документах SpringSecurity:

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

    String  username = (String) request.getSession().getAttribute("SPRING_SECURITY_LAST_USERNAME");
0 голосов
/ 28 октября 2018

Это довольно старый поток, но если вы используете относительно актуальный пакет "spring-boot-starter-security", вот как я это сделал:

Я установил свой AuthenticationFailureHandler следующим образом:

SimpleUrlAuthenticationFailureHandler handler = new SimpleUrlAuthenticationFailureHandler("/my-error-url");
handler.setUseForward(true);

Это установит последнее исключение в запросе:

//from SimpleUrlAuthenticationFailureHandler source
request.setAttribute("SPRING_SECURITY_LAST_EXCEPTION", exception);

Тогда из моего контроллера я могу получить неверное имя пользователя:

RequestMapping("/impersonate-error")
public String impersonateErrorPage(Map<String, Object> model, HttpServletRequest request) {

    AuthenticationException ex = (AuthenticationException)request.getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
    if(ex != null) {
        logger.debug("Impersonate message: " + ex.getMessage());
        model.put("badName", ex.getMessage());
    }
    return "impersonate-error";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...