Rest call on expired session: HTTP 401 response causes browser to display login window

给你一囗甜甜゛ 提交于 2020-01-01 02:30:47

问题


I have written a HTML 5 application that uses AngularJS and interfaces with a Java REST backend running on Tomcat. I use Spring Security to handle login and security.

When the user enters the website he is forwarded to a login page which creates a session and redirects to the index page. The REST calls that loads further data from the server then uses that session to authenticate. If there is no session in place, I fallback to basic authentication over HTTP, such that it is possible to invoke the REST endpoints separately from the web application.

The problem I have now is when the session expires. This causes a HTTP 401 Unauthenticated response from the server. I thought I can catch that error and redirect the user back to the login page with Javascript. However before my error handler is called, the browser first shows a login window, only if I click cancel my Javascript error handler can handle the response.

My question is, is there a way to prevent the browser from showing this login window? Or is this a general problem with my application design?

The alternative might be not to use a session at all and to cache username and password in the application. Then I need to send it with every REST call using basic authentication, would that be a better approach?

The following is the HTTP response from the server:

HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
WWW-Authenticate: Basic realm="Spring Security Application"
Content-Type: text/html;charset=utf-8
Content-Length: 999
Date: Mon, 30 Sep 2013 11:00:34 GMT

Update: It appears that the reason for this is the WWW-Authenticate header, which causes the browser to display the login dialog.


回答1:


I finally found the solution for this. As I mentioned in my update the reason is, that the response contains the WWW-Authenticate header field. My solution was then to change the configuration of spring security to return a different header:

WWW-Authenticate: FormBased

To do this I had to implement the AuthenticaitonEntryPoint interface and manually set the header and status code in the response:

@Component( "restAuthenticationEntryPoint" )
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence( HttpServletRequest request, HttpServletResponse response,
                          AuthenticationException authException ) throws IOException {
        response.setHeader("WWW-Authenticate", "FormBased");
        response.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
    }
}

then I changed the configuration of spring-security and set the entry-point-ref to point to the new class:

<http pattern="/rest/**" create-session="never" entry-point-ref="restAuthenticationEntryPoint">
    <intercept-url pattern="/rest/**" access="ROLE_USER" />
    <http-basic />
    <session-management />
</http>



回答2:


If you want to avoid changing the server and make it return WWW-Authenticate header for all other callers, you can change your client to send its request with X-Requested-With header with XMLHttpRequest value. By default, Spring Security will not to send WWW-Authenticate for such requests. (see Spring source)



来源:https://stackoverflow.com/questions/19079687/rest-call-on-expired-session-http-401-response-causes-browser-to-display-login

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!