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

时间:2014-10-21 10:26:19

标签: 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" />     
    ...

因为我有这一行authentication-failure-url="/login?error=true" 我知道如果error'true',则会出现错误:可能是“错误凭据”或“超出最大会话数”。但我我想知道哪个错误真的发生了?

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

2 个答案:

答案 0 :(得分:9)

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

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

我的主要目标是&#34;覆盖&#34; SPRING_SECURITY_LAST_EXCEPTION.message但是根据Spring安全性给我的各种错误来定制错误消息。

的web.xml

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

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> 

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

您自己的AuthenticationFailureHandler的 bean

 <beans:bean id="customFailureHandler" class="com.springgestioneerrori.controller.CustomAuthenticationFailureHandler"/>

这是实现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);  

    }

}

希望这可以帮助某人。

答案 1 :(得分:2)

而不是authentication-failure-url,您需要使用authentication-failure-handler-ref并引用您需要创建的故障处理程序bean,并将不同的url(或不同的params映射到同一个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>

文档中提到了许多其他异常。请参阅doc

编辑:

同样存在异常,因为同一用户已超过允许并发的会话数,因此抛出了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>