복붙노트

[SPRING] 스프링 보안을 사용하여 실패한 로그인에서 사용자 이름을 얻으려면 어떻게해야합니까?

SPRING

스프링 보안을 사용하여 실패한 로그인에서 사용자 이름을 얻으려면 어떻게해야합니까?

우리는 스프링 보안 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>

자바

    @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에서 실패한 로그인 시도에 사용 된 사용자 이름을 얻고 싶습니다. 어떻게해야합니까?

해결법

  1. ==============================

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

    나는 봄 보안 전문가와는 거리가 멀다. 누구든지이 사실을 읽고 이유를 알고 있다면, 우리는 이런 식으로해서는 안되며, 내가 듣고 싶은 더 좋은 방법을 알고있다.

  2. ==============================

    2.나는 그것을 이렇게했다 :

    나는 그것을 이렇게했다 :

  3. ==============================

    3.대신 자신 만의 DefaultAuthenticationEventPublisher 버전을 제공하고 publishAuthenticationFailure 메서드를 재정의 할 수 있습니다.

    대신 자신 만의 DefaultAuthenticationEventPublisher 버전을 제공하고 publishAuthenticationFailure 메서드를 재정의 할 수 있습니다.

  4. ==============================

    4.이 솔루션에 대한 정보는 많지 않지만 Spring Security 구성에서 failureForwardUrl을 설정하면 리디렉션되지 않고 오류 페이지로 전달됩니다. 그러면 사용자 이름과 암호를 쉽게 검색 할 수 있습니다. 예를 들어, 귀하의 구성에서 추가 : formForLogin (). failureForwardUrl ( "/ login / failed") (* url은 로그인 페이지 URL과 달라야합니다.)

    이 솔루션에 대한 정보는 많지 않지만 Spring Security 구성에서 failureForwardUrl을 설정하면 리디렉션되지 않고 오류 페이지로 전달됩니다. 그러면 사용자 이름과 암호를 쉽게 검색 할 수 있습니다. 예를 들어, 귀하의 구성에서 추가 : formForLogin (). 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. ==============================

    5.나는 이것이 나를 위해 일하는 것을 알았다. 불행히도 SpringSecurity 문서에서 정확한 위치를 찾지 못했습니다.

    나는 이것이 나를 위해 일하는 것을 알았다. 불행히도 SpringSecurity 문서에서 정확한 위치를 찾지 못했습니다.

    모든 작업에서 로그인이 실패했는지 여부에 관계없이 마지막으로 사용한 사용자 이름을 확인할 수 있습니다.

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

    6.Spring AOP를 사용하려면 아래 코드를 Aspect 클래스에 추가하면된다.

    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.");
    }
    
  7. ==============================

    7.이것은 꽤 오래된 스레드이지만, 비교적 최근의 "spring-boot-starter-security"패키지를 사용하고 있다면, 다음과 같이 해보겠습니다 :

    이것은 꽤 오래된 스레드이지만, 비교적 최근의 "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";
    }
    
  8. from https://stackoverflow.com/questions/8676206/how-can-i-get-the-username-from-a-failed-login-using-spring-security by cc-by-sa and MIT license