4

I have some url secured with spring (configured through xml). It works. However when I try to hit that endpoint with an ajax request I get a 302 (found) response. This redirects my ajax call to the login page (so I GET the html). However I'd like to get a 401 (unauthorized) response with the url of the login page available to the client application, so I can redirect the user there with javascript. This question seems to be the closest to what I want, but there's no example and it suggests changing the controller again. Is there no configuration in spring-security that will give me a 401 and a url (or some other sensible error message and the url of the login page)?

1
  • Do you want all URLs in your application to return 401 if you're not logged in, or do you want only some URLs (the AJAX ones only) to return 401? Commented Dec 8, 2011 at 6:25

2 Answers 2

16

You can extend LoginUrlAuthenticationEntryPoint. Here is my one:

package hu.progos.springutils;
// imports omitted
public class AjaxAwareLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
    public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException, ServletException {
        if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
        } else {
            super.commence(request, response, authException);
        }
    }
}

Then configure spring to use your implementation:

<beans:bean id="authEntryPoint" class="hu.progos.springutils.AjaxAwareLoginUrlAuthenticationEntryPoint" scope="singleton>
    <beans:property name="loginFormUrl" value="/login.html" />
</beans:bean>

<http entry-point-ref="authEntryPoint">
  <!-- your settings here -->
</http>
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. this seems like the correct solution. we're not using ajax anymore though, so I won't need this.
This is by far a more elegant solution than using a filter to inspect every request. Thx.
Very nice solution, thanks! I made a minor change since I got a warning that setting loginFormUrl property was deprecated. I added a constructor to the AjaxAwareLoginUrlAuthenticationEntryPoint class super(loginFormUrl); and changed the bean def to use constructor-arg value="/login.html" />
I posted an answer with my code here: stackoverflow.com/a/49416672/4505142
0

There are a million ways to do this of course. But the short solution to your problem is this configuration snippet:

<bean id="customAuthEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
   <property name="loginFormUrl" value="/your-custom-login" />
</bean>

I also take a step further and turn off the security auto-config so I can map the above entry point like so:

 <security:http auto-config="false" entry-point-ref="customAuthEntryPoint">
   ...
   ...
 </security:http>

I also override a bunch of spring security classes to get the security model to do exactly what I want. It's a slippery slope, but it's nice having the control once it works the way you want it to.

1 Comment

is that the same as <http> ... <form-login login-page="/my-cutsom-login"> ... </http> in spring 3? I'm using that at the moment

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.