正确添加Restlet 2.3 CORS的方法

时间:2015-09-30 13:25:30

标签: java ajax rest cors restlet

标题说明了......向Restlet 2.3添加适当的CORS支持的正确/推荐方法是什么,它实现ChallengeAuthenticator以允许Pre-flight选项访问没有Authorization标头的标头信息?

最初我以为我可以将@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 pre-flight 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的实例化方式大致相同,除了它附加到RoutercreateInboundRoot()方法中。但是,我不明白如何与ChallengeAuthenticator一起实施。

附录:

  • 我在代码中发现this表示应该处理飞行前。

1 个答案:

答案 0 :(得分:2)

您需要设置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