Restlet 2.3 覆盖 WWW-Authenticate Header

Restlet 2.3 Override WWW-Authenticate Header

Restlet 2.3 中,我使用 ChallengeAuthenticatorChallengeScheme.HTTP_BASIC 来保护应用程序资源。当服务器收到一组不正确的凭据时,服务器会正​​确 returns 一个 401 Unauthorized 响应。它也正确地添加了以下 header:

WWW-Authenticate → Basic realm="My security Realm"

问题是当响应返回到浏览器而不是服务器时(AngularJS 应用程序 GUI 就是这种情况),浏览器会本地解释 401 响应并启动一个'Authentication Required'模态。

我想尝试实现的是读取请求 headers(很容易完成),如果 X-Requested-With: XMLHttpRequest header 存在,我想抑制 WWW-Authenticate header 在“401”响应中。

目前 WWW-Authenticate header 是自动设置的,所以我的问题是如何覆盖此默认设置 header 并手动处理它?

在您的情况下,您应该使用过滤器从响应中删除 header WWW-Authenticate。此 header 对应于响应中的质询请求。

过滤内容如下:

public class SecurityPostProcessingFilter extends Filter {
    public SecurityPostProcessingFilter(
              Context context, Restlet next) {
        super(context, next);
    }

    @Override
    protected void afterHandle(Request request, Response response) {
        String requestedWith
           = request.getHeaders().getFirstValue("X-Requested-With");
        if ("XMLHttpRequest".equals(requestedWith)) {
            response.getChallengeRequests().clear();
        }
    }
}

您需要将其添加到您的 Restlet 应用程序的 createInboundRoot 方法中,如下所述

public class RestletApplication extends Application {
    (...)

    @Override
    public Restlet createInboundRoot() {
        Router router = new Router(getContext());
        (...)

        ChallengeAuthenticator guard = new ChallengeAuthenticator(
                null, ChallengeScheme.HTTP_BASIC, "testRealm");
        (...)
        guard.setNext(router);

        Filter filter = new SecurityPostProcessingFilter(
             getContext(), guard);

        return filter;
    }
}

当 header X-Requested-From 的值等于请求中的 XMLHttpRequest 时,这将从响应中删除 header WWW-Authenticate

仅供参考,Restlet 网站上有一个页面描述了 HTTP headers 和 Restlet API 之间的映射:http://restlet.com/technical-resources/restlet-framework/guide/2.2/core/http-headers-mapping

希望对你有帮助, 蒂埃里

另一种方法是覆盖 ChallengeAuthenticator#challenge 方法。 默认情况下,它设置响应状态并添加一个挑战请求:

    ChallengeAuthenticator guard = new ChallengeAuthenticator(getContext(), ChallengeScheme.HTTP_BASIC, "realm") {
        public void challenge(org.restlet.Response response, boolean stale) {
            String requestedFrom = response.getRequest().getHeaders().getFirstValue("X-Requested-With");
            if (!"XMLHttpRequest".equals(requestedFrom)) {
                super.challenge(response, stale);
            } else {
                response.setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
            }

        };
    };