2

I have some kind of controller:

    @Controller
    public class DefaultController {

    @RequestMapping(value="/index.html", method=RequestMethod.GET)
        public String indexView(){
            return "index";
        }

    @RequestMapping(value="/some.action", method=RequestMethod.POST)
    @ResponseBody
        public MyObject indexView(some parametrs.... ){
            MyObject o= daoService.getO(id);
                    return o; 
        }
}

I'm using Spring Security:

<security:global-method-security secured-annotations="enabled" />
<security:http  auto-config="true" access-denied-page="/accessDenied.jsp">
  <security:form-login login-page="/login.html" login-processing-url="/login" authentication-failure-url="/login.html?login_error=1" default-target-url="/"/> 
  <security:http-basic/>
    <security:intercept-url pattern='/**' access='ROLE_USER' />
  <security:logout logout-url="/logout" logout-success-url="/"/>
  <security:remember-me services-ref="rememberMeServices"/>
    </security:http>

Now, my problem is th following:

when accessing /some.action using AJAX with none authenticated user Spring Security returns 301 command (Redirect to access denied page).

What I need is even if user is not authenticated to return 200 OK and send authentication error message to the client or event or in worst case to return 400 something error.

I understand that I need to create custom authentication success handler, but can I do it and how can I apply this handler on *.action URIs?

danny.lesnik
  • 18,032
  • 28
  • 123
  • 194

1 Answers1

2

For AJAX authentication, I added a custom security entry point ref to check to see if the user is authenticated. If they are not, I send them a 4xx error code. Then on my Ajax call, I check to see if an error is returned and if so I redirect them to my login page.

Here's a snippet of my security-config.

<security:http entry-point-ref="myAuthenticationEntryPoint" auto-config="true" use-expressions="true">
...
...
</security:http>
<bean id="myAuthenticationEntryPoint" class="com.security.AjaxAuthenticationEntryPoint" >
        <property name="loginFormUrl" value="/login"/>
</bean>

Here's my custom entry point:

public class AjaxAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint
{   
    @Override
    /**
     * This method only gets call when the user logs out or when the session is invalid
     * 
     * It checks to see if the request is an ajax request
     * if so then return an error
     * else then do the natural check 
     */
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
            throws IOException, ServletException 
    {                       
        if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) 
        {
            if (request.getSession() != null)
            {
                Object targetUrl = request.getSession().getAttribute(WebAttributes.SAVED_REQUEST);
                if (targetUrl != null)
                {                   
                    response.sendError(HttpServletResponse.SC_EXPECTATION_FAILED);                                      
                }
            }   
        }
        else
        {
            super.commence(request, response, authException);
        }

    }
}

Here's a snippet of my JQuery call, reload causes the login page to appear.

error: function (xhr, textStatus, errorThrown) 
               {    
                    // 417 is sent from the server to indicate that
                    // page needs to be reloaded
                    //
                    if (xhr.status == 417)
                    {
                        xhr = null;
                        window.location.reload();                       
                    }
               }
Joe Intrakamhang
  • 489
  • 2
  • 7
  • 14