2015-09-30 5 views
2

Название говорит об этом ... Каков правильный/рекомендуемый способ добавления правильной поддержки CORS для Restlet 2.3, которая реализует ChallengeAuthenticator, чтобы позволить предварительным возможностям доступа к информации заголовка без заголовка авторизации?Правильный способ добавления Restlet 2.3 CORS

Первоначально я думал, что я мог бы добавить @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); 
    } 

Что я ожидал, чтобы это произошло в том, что Аякса предварительно -flight Options запрос будет освобожден ChallengeAuthenticator, и вышеуказанные заголовки будут возвращены. К сожалению, это не так, и запрос ajax pre-flight 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 кроме этого привязывается к Router в методе createInboundRoot(). Однако я не понимаю, как это должно быть реализовано для работы в сочетании с ChallengeAuthenticator.

Добавление:

  • Я нашел this в коде предполагая, что перед полетом должны быть обработаны.

ответ

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.

+0

Это должно работать ... но это не так. Наверно, есть ошибка. Использование 'getServices(). Add (CorsService)' не добавляет заголовков в ответ! Добавление 'setSkippingResourceForCorsOptions' на самом деле приводит к тому, что ресурс пропускается, но ни один из заголовков, указанных в службе, не отвечает независимо от того, использую ли я' setSkippingResourceForCorsOptions'. Я попробовал это в 2.3.4 и 2.3.5. – tarka

+0

Кажется, что только заголовки добавляются, когда заголовок 'Origin:' присутствует в запросе, иначе вам не нужно CORS. Итак, работает, как я предполагаю. – letmaik

+0

Да, мы считаем, что этот заголовок является обязательным, даже если спецификация не совсем понятна. По крайней мере, большинство браузеров установили его. –