我编写了一个 HTML 5 应用程序,它使用 AngularJS 并与在 Tomcat 上运行的 Java REST 后端接口(interface)。 我使用 Spring Security 来处理登录和安全性。
当用户进入网站时,他被转发到一个登录页面,该页面创建一个 session 并重定向到索引页面。 REST 调用从服务器加载更多数据,然后使用该 session 进行身份验证。 如果没有适当的 session ,我会回退到通过 HTTP 的基本身份验证,这样就可以从 Web 应用程序中单独调用 REST 端点。
我现在遇到的问题是 session 何时过期。这会导致来自服务器的 HTTP 401 Unauthenticated
响应。我以为我可以捕获该错误并使用 Javascript 将用户重定向回登录页面。然而,在我的错误处理程序被调用之前,浏览器首先显示一个登录窗口,只有当我点击取消时,我的 Javascript 错误处理程序才能处理响应。
我的问题是,有没有办法阻止浏览器显示这个登录窗口?或者这是我的应用程序设计的普遍问题?
替代方案可能是根本不使用 session 并在应用程序中缓存用户名和密码。然后我需要使用基本身份验证在每次 REST 调用时发送它,这是更好的方法吗?
以下是来自服务器的 HTTP 响应:
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
更新:看来这是因为 WWW-Authenticate
header 导致浏览器显示登录对话框。
最佳答案
我终于找到了解决方案。正如我在更新中提到的,原因是响应包含 WWW-Authenticate
header 字段。然后我的解决方案是更改 spring security 的配置以返回不同的 header :
WWW-Authenticate: FormBased
为此,我必须实现 AuthenticaitonEntryPoint
接口(interface)并在响应中手动设置 header 和状态代码:
@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 );
}
}
然后我更改了 spring-security 的配置并将 entry-point-ref
设置为指向新类:
<http pattern="/rest/**" create-session="never" entry-point-ref="restAuthenticationEntryPoint">
<intercept-url pattern="/rest/**" access="ROLE_USER" />
<http-basic />
<session-management />
</http>
关于http - 在过期 session : HTTP 401 response causes browser to display login window 上休息调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19079687/