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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26484440/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 09:59:59  来源:igfitidea点击:

How to customize SPRING_SECURITY_LAST_EXCEPTION.message according to the error I get

javaspringjspspring-mvcspring-security

提问by MDP

I made a login system with Spring Security. This is my spring-security.xml

我用 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" />     
    ...

Since i have this line authentication-failure-url="/login?error=true"I know that if erroris 'true'there's an error: it might be "bad credentials" or "Maximum sessions number exceeded".But I'd like to know which error really occorred?

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

Is there a way, inside a java class (@controller), to know what kind of error Spring is giving me, in order to customize those error messages?

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

回答by MDP

I found this solution, it seems to work.

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

Extending SimpleUrlAuthenticationFailureHandleryou can send the user to different pages, and print the message you want.

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

My main goal wasn't to "override" SPRING_SECURITY_LAST_EXCEPTION.messagebut was customizing the error message according to the various kind of errors Spring security gives me.

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

web.xml

网页.xml

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

security-config.xml (just some code)

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

session-management

会话管理

   <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-loginwhere you call your own AuthenticationFailureHandler (customFailureHandler)

您在其中调用自己的 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" />

the beanof your own AuthenticationFailureHandler

您自己的 AuthenticationFailureHandler的bean

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

and this is the class implementing SimpleUrlAuthenticationFailureHandler

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

    }

}

Hope this can help someone.

希望这可以帮助某人。

回答by Janendra

Instead of the authentication-failure-url, you need to use authentication-failure-handler-ref and refer the failure handler bean which you need to create and map different urls (or different params to the same url) to different type of exceptions.

您需要使用 authentication-failure-handler-ref 代替 authentication-failure-url 并引用您需要创建的失败处理程序 bean,并将不同的 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>

There are bunch of other exceptions, mentioned in the docs. Please refer the doc

文档中提到了许多其他例外。请参考文档

EDIT:

编辑:

There is an exception for the same, SessionAuthenticationException is thrown typically because the same user has exceeded the number of sessions they are allowed to have concurrent. But this is at container level only and won't work if you have multiple containers.

有一个例外,通常会抛出 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>

回答by marthursson

This is an old question, but since the answer marked as correct actually contains a nasty subtle bug it should be noted that the correct solution would be to use built-in ExceptionMappingAuthenticationFailureHandlerinstead of the CustomAuthenticationFailureHandlersuggested in the answer from @mdp.

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