添加 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 的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

在 OSGi 中从 Restlet 启动 Jetty

Restlet 2.0.8:单个restlet应用程序实例的多种身份验证方法(BASIC、DIGEST)?

如何在 Angular 5 的标头中添加 CORS 请求

在 OSGi 中配置 Restlet 以使用 Jetty 连接器(非简单连接器)

CORS 错误:配置 Symfony 5 以接受 CORS 的正确方法是啥?

Camel Restlet异步发送对客户端的响应