Java 如何根据我得到的错误定制SPRING\u SECURITY\u LAST\u EXCEPTION.message

Java 如何根据我得到的错误定制SPRING\u SECURITY\u LAST\u EXCEPTION.message,java,spring,jsp,spring-mvc,spring-security,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> &l

我用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" />     
    ...
。。。
...
因为我有这一行
身份验证失败url=“/login?error=true”
我知道如果
error
'true'
则会出现错误:可能是“错误凭据””或“超出了最大会话数””。但我想知道到底是哪个错误造成的


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

您需要使用身份验证失败处理程序ref并引用失败处理程序bean来创建和映射不同的url,而不是身份验证失败url(或同一url的不同参数)设置为不同类型的异常

 <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" />


<beans:bean id="customFailureHandler"
    class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
    <beans:property name="exceptionMappings">
        <beans:props>
            <beans:prop
                key="org.springframework.security.authentication.BadCredentialsException">/url1</beans:prop>
            <beans:prop
                key="org.springframework.security.authentication.AuthenticationServiceException">/url2</beans:prop>
            <beans:prop key="org.springframework.secuirty.authentication.DisabledException">/url3</beans:prop>
        </beans:props>
    </beans:property>
    <beans:property name="defaultFailureUrl" value="/url4" />
</beans:bean>

/url1
/url2
/url3
文档中提到了大量其他例外情况。请参考

编辑:

同一个存在异常,通常会引发SessionAuthenticationException,因为同一用户超过了允许其并发的会话数。但这仅限于容器级别,如果您有多个容器,则不会起作用

<security:session-management session-authentication-strategy-ref="sas"/>

<bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
<bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy" >
    <constructor-arg name="sessionRegistry" ref="sessionRegistry" />
    <property name="maximumSessions" value="2" />
 </bean>

我找到了这个解决方案,它似乎有效

扩展
SimpleRuthenticationFailureHandler
可以将用户发送到不同的页面,并打印所需的消息

我的主要目标不是“覆盖”
SPRING\u SECURITY\u LAST\u EXCEPTION.message
,而是根据SPRING SECURITY给我的各种错误定制错误消息

web.xml

  <listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
  </listener>

希望这能对某人有所帮助。

这是一个老问题,但由于标记为正确的答案实际上包含一个令人讨厌的微妙错误,因此应该注意,正确的解决方案是使用内置的
异常映射AuthenticationFailureHandler
而不是ans中建议的
CustomAuthenticationFailureHandler
wer from@mdp.

谢谢你,伙计。不幸的是,如果用户试图同时从许多不同的设备登录(超过了最大会话数),则没有任何特定的例外情况。我应该如何处理这个问题?我不知道我是否已经编辑了答案以包含会话控制。谢谢你。我找到了另一个解决方案并发布了。总之,你的解决方案很好!总体上解决方案相当可靠,但在重写方法中调用setter以在超级方法中发生自定义行为是非常糟糕的做法。将有e整个应用程序的一个
CustomAuthenticationFailureHandler
实例,因此在多线程场景中,无法知道会发生什么(在第一个线程执行
onAuthenticationFailure
之前,另一个线程可能调用了
setDefaultFailureUrl
)。使方法同步将解决问题,但这仍然是相当糟糕的。
   <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> 
  <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" />
 <beans:bean id="customFailureHandler" class="com.springgestioneerrori.controller.CustomAuthenticationFailureHandler"/>
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);  

    }

}