Alessandro Ferrucci
2014-05-28 12:00:06 UTC
Hello,
I have a Spring MVC application which loads data dynamically through AJAX.
All AJAX entry points are protected and the user must be authenticated in
order to access the AJAX endpoints.
I need for my front end code to know when a session timeout occurs when an
AJAX request is made. I have implemented this using
LoginAuthenticationEntryPoint implementation and if the HTTP request
contains the "X-Requested-With header" with a value of "XMLHttpRequest", I
send back a 403 Error Code.
This works for the most part, the issue is that on the very first AJAX
Request, spring performs a redirect and I get a 302 followed by a redirect
to my login page, on all subsequent AJAX requests the correct 403 comes
back.
Below is the relevant Spring security config and the
AjaxAwareAuthenticationEntryPoint source.
Side Note: I have also tried this using the request matcher implementation
outlined here:
http://distigme.wordpress.com/2012/11/01/ajax-and-spring-security-form-based-login/
and I get the same exact results.
Any ideas?
Thanks!
Alessandro Ferrucci
<beans:bean id="authenticationEntryPoint"
class="mojo.ocs.web.AjaxAwareAuthenticationEntryPoint">
<beans:constructor-arg name="loginUrl" value="/login"/>
</beans:bean>
<!-- ENTRY POINT REF IMPLEMENTATION -->
<http auto-config="true" use-expressions="true"
access-denied-page="/accessdenied"
entry-point-ref="authenticationEntryPoint">
<intercept-url pattern="/login" access="isAnonymous()"/>
<intercept-url pattern="/loginfailed" access="isAnonymous()"/>
<intercept-url pattern="/welcome" access="isAuthenticated()" />
<intercept-url pattern="/" access="isAuthenticated()" />
<intercept-url pattern="/private_res/**" access="isAuthenticated()"
/>
<intercept-url pattern="/tne/**" access="isAuthenticated()" />
<intercept-url pattern="/team_reports/**"
access="isAuthenticated()" />
<form-login login-page="/login" default-target-url="/welcome"
always-use-default-target="true" authentication-failure-url="/loginfailed"
/>
<logout delete-cookies="JSESSIONID" logout-success-url="/logout"
invalidate-session="true"/>
<session-management invalid-session-url="/login" />
</http>
This is the AjaxAwareAuthenticationEntryPoint:
public class AjaxAwareAuthenticationEntryPoint extends
LoginUrlAuthenticationEntryPoint {
public AjaxAwareAuthenticationEntryPoint(String loginUrl) {
super(loginUrl);
}
@Override
public void commence(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException)
throws IOException, ServletException {
String ajaxHeader = ((HttpServletRequest)
request).getHeader("X-Requested-With");
boolean isAjax = "XMLHttpRequest".equals(ajaxHeader);
if (isAjax) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Ajax
REquest Denied (Session Expired)");
} else {
super.commence(request, response, authException);
}
}
}
I have a Spring MVC application which loads data dynamically through AJAX.
All AJAX entry points are protected and the user must be authenticated in
order to access the AJAX endpoints.
I need for my front end code to know when a session timeout occurs when an
AJAX request is made. I have implemented this using
LoginAuthenticationEntryPoint implementation and if the HTTP request
contains the "X-Requested-With header" with a value of "XMLHttpRequest", I
send back a 403 Error Code.
This works for the most part, the issue is that on the very first AJAX
Request, spring performs a redirect and I get a 302 followed by a redirect
to my login page, on all subsequent AJAX requests the correct 403 comes
back.
Below is the relevant Spring security config and the
AjaxAwareAuthenticationEntryPoint source.
Side Note: I have also tried this using the request matcher implementation
outlined here:
http://distigme.wordpress.com/2012/11/01/ajax-and-spring-security-form-based-login/
and I get the same exact results.
Any ideas?
Thanks!
Alessandro Ferrucci
<beans:bean id="authenticationEntryPoint"
class="mojo.ocs.web.AjaxAwareAuthenticationEntryPoint">
<beans:constructor-arg name="loginUrl" value="/login"/>
</beans:bean>
<!-- ENTRY POINT REF IMPLEMENTATION -->
<http auto-config="true" use-expressions="true"
access-denied-page="/accessdenied"
entry-point-ref="authenticationEntryPoint">
<intercept-url pattern="/login" access="isAnonymous()"/>
<intercept-url pattern="/loginfailed" access="isAnonymous()"/>
<intercept-url pattern="/welcome" access="isAuthenticated()" />
<intercept-url pattern="/" access="isAuthenticated()" />
<intercept-url pattern="/private_res/**" access="isAuthenticated()"
/>
<intercept-url pattern="/tne/**" access="isAuthenticated()" />
<intercept-url pattern="/team_reports/**"
access="isAuthenticated()" />
<form-login login-page="/login" default-target-url="/welcome"
always-use-default-target="true" authentication-failure-url="/loginfailed"
/>
<logout delete-cookies="JSESSIONID" logout-success-url="/logout"
invalidate-session="true"/>
<session-management invalid-session-url="/login" />
</http>
This is the AjaxAwareAuthenticationEntryPoint:
public class AjaxAwareAuthenticationEntryPoint extends
LoginUrlAuthenticationEntryPoint {
public AjaxAwareAuthenticationEntryPoint(String loginUrl) {
super(loginUrl);
}
@Override
public void commence(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException)
throws IOException, ServletException {
String ajaxHeader = ((HttpServletRequest)
request).getHeader("X-Requested-With");
boolean isAjax = "XMLHttpRequest".equals(ajaxHeader);
if (isAjax) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Ajax
REquest Denied (Session Expired)");
} else {
super.commence(request, response, authException);
}
}
}