如何根据我得到的错误自定义SPRING_SECURITY_LAST_EXCEPTION.message

MDP*_*MDP 4 java spring jsp spring-mvc spring-security

我用Spring Security制作了一个登录系统.这是我的spring-security.xml

... 
<session-management invalid-session-url="/login">
       <concurrency-control max-sessions="1" expired-url="/login" error-if-maximum-exceeded="true"/>
</session-management>

<form-login 
        login-page="/login"                         
        default-target-url="/index" 
        always-use-default-target="true"
        authentication-failure-url="/login?error=true"          
        username-parameter="j_username"         
        password-parameter="j_password" />

<logout
        logout-success-url="/login"          
        delete-cookies="JSESSIONID" 
        invalidate-session="true" />     
    ...
Run Code Online (Sandbox Code Playgroud)

因为我有这行 authentication-failure-url="/login?error=true" 我知道,如果 error'true'有一个错误:它可能是" 坏凭据 "或" 最大会话数突破 ".但我想知道哪些错误真的occorred?

有没有办法,在java类(@controller)中,知道Spring给我的错误类型,以便自定义这些错误消息?

MDP*_*MDP 9

我发现这个解决方案,它似乎工作.

扩展SimpleUrlAuthenticationFailureHandler您可以将用户发送到不同的页面,并打印您想要的消息.

我的主要目标不是"覆盖",SPRING_SECURITY_LAST_EXCEPTION.message而是根据Spring安全性给我的各种错误定制错误消息.

web.xml中

  <listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
  </listener>
Run Code Online (Sandbox Code Playgroud)

security-config.xml(只是一些代码)

会话管理

   <session-management invalid-session-url="/login" session-authentication-error-url="/login" >
                   <concurrency-control max-sessions="1" expired-url="/login" error-if-maximum-exceeded="true"/>
            </session-management> 
Run Code Online (Sandbox Code Playgroud)

form-login,您可以在其中调用自己的AuthenticationFailureHandler(customFailureHandler)

  <form-login 
                    login-page="/login"         
                    default-target-url="/index" 
                    always-use-default-target="true"                  
                    authentication-failure-handler-ref="customFailureHandler"   
                    username-parameter="j_username"         
                    password-parameter="j_password" />
Run Code Online (Sandbox Code Playgroud)

您自己的AuthenticationFailureHandler 的bean

 <beans:bean id="customFailureHandler" class="com.springgestioneerrori.controller.CustomAuthenticationFailureHandler"/>
Run Code Online (Sandbox Code Playgroud)

这是实现SimpleUrlAuthenticationFailureHandler的类

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.session.SessionAuthenticationException;

public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { 

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {

     if(exception.getClass().isAssignableFrom(BadCredentialsException.class)) {
            setDefaultFailureUrl("/url1");
      }
      else if (exception.getClass().isAssignableFrom(DisabledException.class)) {         
          setDefaultFailureUrl("/url2");
      }
      else if (exception.getClass().isAssignableFrom(SessionAuthenticationException.class)) {       
          setDefaultFailureUrl("/url3");    
      }

      super.onAuthenticationFailure(request, response, exception);  

    }

}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助别人.

  • 一般来说,解决方案非常可靠,但在重写方法中调用setter以在super方法中执行自定义行为是非常糟糕的做法.整个应用程序将有一个`CustomAuthenticationFailureHandler`实例,因此在多线程场景中无法知道将发生什么(另一个线程可能在第一个线程执行`onAuthenticationFailure`之前调用`setDefaultFailureUrl`) .使方法同步可以解决问题,但它仍然是非常讨厌的. (2认同)