Подтвердить что ты не робот

Как я могу получить имя пользователя из отказавшего входа с помощью spring безопасности?

Мы используем 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 и IndexController. В IndexController я хотел бы получить username, который использовался для неудачной попытки входа в систему. Как я могу это сделать?

4b9b3361

Ответ 1

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

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

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 + "]");
    }
}

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

Ответ 2

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

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

  • Оверлейте метод onAuthenticationFailure, который получает HttpServletRequest как параметр.

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

Ответ 3

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

Ответ 4

Похоже, что об этом решении не так много информации, но если вы установили 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")

Ответ 5

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

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

    String  username = (String) request.getSession().getAttribute("SPRING_SECURITY_LAST_USERNAME");

Ответ 6

Это довольно старый поток, но если вы используете относительно актуальный пакет "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";
}

Ответ 7

Попробуйте этот подход

import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

String username = request.getParameter(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_USERNAME_KEY);