添加 Restlet 2.3 CORS 的正确方法
Posted
技术标签:
【中文标题】添加 Restlet 2.3 CORS 的正确方法【英文标题】:Correct way to add Restlet 2.3 CORS 【发布时间】:2015-12-28 07:30:37 【问题描述】:标题说...向 Restlet 2.3 添加适当的 CORS 支持的正确/推荐方法是什么,实现 ChallengeAuthenticator
以允许飞行前选项在没有授权标头的情况下访问标头信息?
本来我以为可以在资源接口上加@Options
注解:
@Options
void getCorsSupport();
然后用这样的方式实现它:
@Override
public void getCorsSupport()
Series<Header> headers = getResponse().getHeaders();
headers.set("Access-Control-Expose-Headers", "Authorization, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-OAuth-Scopes, X-Accepted-OAuth-Scopes");
Set<String> head = new HashSet<>();
head.add("Authorization");
head.add("Content-Type");
head.add("X-Requested-With");
getResponse().setAccessControlAllowHeaders(head);
Set<Method> methods = new HashSet<>();
methods.add(Method.ALL);
getResponse().setAccessControlAllowMethods(methods);
getResponse().setAccessControlAllowCredentials(true);
Series<Header> reqHeaders = getRequest().getHeaders();
String requestOrigin = reqHeaders.getFirstValue("Origin", false, "*");
getResponse().setAccessControlAllowOrigin(requestOrigin);
我预计会发生的是,ajax 飞行前Options
请求将免除ChallengeAuthenticator
,并且将返回上述标头。可悲的是,情况并非如此,ajax 飞行前Options
请求像其他所有内容一样受到ChallengeAuthenticator
的影响。这意味着请求失败,因为它没有被授予其所需的Access-Control-Allow-Origin
标头。
然后我做了一些研究,发现似乎可以在应用程序中注册CorsService
。
public class WebApi extends Application
public WebApi()
getServices().add(createCorsService());
...
private CorsService createCorsService()
CorsService corsService = new CorsService();
corsService.setAllowedOrigins(new HashSet(Arrays.asList("*")));
corsService.setAllowedCredentials(true);
corsService.setAllowedCredentials(true);
corsService.setAllowingAllRequestedHeaders(true);
Set<String> allowHeaders = new HashSet<>();
allowHeaders.add("Authorization");
allowHeaders.add("Content-Type");
allowHeaders.add("X-Requested-With");
corsService.setAllowedHeaders(allowHeaders);
Set<String> exposeHeaders = new HashSet<>();
exposeHeaders.add("Authorization");
exposeHeaders.add("Link");
exposeHeaders.add("X-RateLimit-Limit");
exposeHeaders.add("X-RateLimit-Remaining");
exposeHeaders.add("X-OAuth-Scopes");
exposeHeaders.add("X-Accepted-OAuth-Scopes");
corsService.setExposedHeaders(exposeHeaders);
return corsService;
我认为这可能是一种避免每个服务都使用@Options
方法的干净方法。但是,我一定做错了什么,因为这似乎什么也没做。
进一步研究我发现还有CorsFilter
之类的东西,它的实例化方式似乎与CorsService
大致相同,只是它在createInboundRoot()
方法中附加到Router
.但是我不明白它应该如何与ChallengeAuthenticator
一起工作。
附录:
我在代码中找到了this,提示应该处理飞行前的问题。【问题讨论】:
【参考方案1】:您需要设置 CorsService 的另一个属性,称为“skipResourceForCorsOptions”。例如:
CorsService corsService = new CorsService();
corsService.setAllowingAllRequestedHeaders(true);
corsService.setAllowedOrigins(new HashSet(Arrays.asList("*")));
corsService.setAllowedCredentials(true);
corsService.setSkippingResourceForCorsOptions(true);
这里是 javadocs:http://restlet.com/technical-resources/restlet-framework/javadocs/2.3/jse/api/org/restlet/service/CorsService.html#setSkippingResourceForCorsOptions%28boolean%29
将在用户指南中添加更详细的页面,地址为:http://restlet.com/technical-resources/restlet-framework/guide/2.3/core/services/cors。
【讨论】:
这应该可以工作......但没有。我想有一个错误。使用getServices().add(CorsService)
不会在响应中添加任何标题!添加setSkippingResourceForCorsOptions
实际上会导致资源被跳过,但无论我是否使用setSkippingResourceForCorsOptions
,服务中指定的标头都不会出现在响应中。我在 2.3.4 和 2.3.5 中尝试过。
它似乎只在请求中存在Origin:
标头时才添加标头,否则您显然不需要CORS。所以,我猜是按预期工作的。
是的,我们认为此标头是强制性的,即使规范对此并不清楚。至少大多数浏览器都设置了它。以上是关于添加 Restlet 2.3 CORS 的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
Restlet 2.0.8:单个restlet应用程序实例的多种身份验证方法(BASIC、DIGEST)?
在 OSGi 中配置 Restlet 以使用 Jetty 连接器(非简单连接器)