Restlet 2.3 覆盖 WWW-Authenticate Header
Restlet 2.3 Override WWW-Authenticate Header
在 Restlet 2.3 中,我使用 ChallengeAuthenticator
和 ChallengeScheme.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);
}
};
};
在 Restlet 2.3 中,我使用 ChallengeAuthenticator
和 ChallengeScheme.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);
}
};
};