Название говорит об этом ... Каков правильный/рекомендуемый способ добавления правильной поддержки 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 в коде предполагая, что перед полетом должны быть обработаны.
Это должно работать ... но это не так. Наверно, есть ошибка. Использование 'getServices(). Add (CorsService)' не добавляет заголовков в ответ! Добавление 'setSkippingResourceForCorsOptions' на самом деле приводит к тому, что ресурс пропускается, но ни один из заголовков, указанных в службе, не отвечает независимо от того, использую ли я' setSkippingResourceForCorsOptions'. Я попробовал это в 2.3.4 и 2.3.5. – tarka
Кажется, что только заголовки добавляются, когда заголовок 'Origin:' присутствует в запросе, иначе вам не нужно CORS. Итак, работает, как я предполагаю. – letmaik
Да, мы считаем, что этот заголовок является обязательным, даже если спецификация не совсем понятна. По крайней мере, большинство браузеров установили его. –