12

我编写了一个 HTML 5 应用程序,它使用 AngularJS 并与运行在 Tomcat 上的 Java REST 后端接口。我使用 Spring Security 来处理登录和安全性。

当用户进入网站时,他被转发到一个登录页面,该页面创建一个会话并重定向到索引页面。从服务器加载更多数据的 REST 调用然后使用该会话进行身份验证。如果没有会话,我会回退到基于 HTTP 的基本身份验证,这样就可以独立于 Web 应用程序调用 REST 端点。

我现在遇到的问题是会话何时到期。这会导致HTTP 401 Unauthenticated来自服务器的响应。我以为我可以捕捉到该错误并使用 Javascript 将用户重定向回登录页面。但是,在调用我的错误处理程序之前,浏览器首先会显示一个登录窗口,只有当我单击取消我的 Javascript 错误处理程序才能处理响应。

我的问题是,有没有办法阻止浏览器显示这个登录窗口?或者这是我的应用程序设计的普遍问题?

另一种方法可能是根本不使用会话并在应用程序中缓存用户名和密码。然后我需要使用基本身份验证在每个 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标题的原因,它导致浏览器显示登录对话框。

4

2 回答 2

11

我终于找到了解决方案。正如我在更新中提到的,原因是响应包含WWW-Authenticate标头字段。然后我的解决方案是更改 spring security 的配置以返回不同的标头:

WWW-Authenticate: FormBased

为此,我必须实现AuthenticaitonEntryPoint接口并在响应中手动设置标头和状态代码:

@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>
于 2013-09-30T20:12:55.973 回答
0

如果您想避免更改服务器并使其返回WWW-Authenticate所有其他调用者的标头,您可以更改您的客户端以发送X-Requested-With带有值的标头的请求XMLHttpRequest。默认情况下,Spring Security 不会发送WWW-Authenticate此类请求。(参见Spring 源代码

于 2017-10-15T13:39:03.720 回答