I made a login system with Spring Security. This is my 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 error
is '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?
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?
I found this solution, it seems to work.
Extending SimpleUrlAuthenticationFailureHandler
you can send the user to different pages, and print the message you want.
My main goal wasn't to "override" SPRING_SECURITY_LAST_EXCEPTION.message
but was customizing the error message according to the various kind of errors Spring security gives me.
web.xml
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
security-config.xml (just some code)
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-login where you call your own 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 bean of your own AuthenticationFailureHandler
<beans:bean id="customFailureHandler" class="com.springgestioneerrori.controller.CustomAuthenticationFailureHandler"/>
and this is the class implementing 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.
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.
<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.
<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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With