2014-09-24 3 views
4

Я работаю над проектом, который использует встроенный Jetty (к сожалению, я просто «унаследовал» серверную часть проекта и не очень хорошо знаком с использованием Jetty и его конфигурацией).Как настроить встроенный Jetty для обработки запросов предварительной предвыборки?

Странный случай просто выскочила - я сделаю все возможное, чтобы описать:

Веб-интерфейс (с помощью AngularJS, из другого домена, поэтому используется CORS) отправляет запрос POST об изменении размера состояние чего-то на сервере. Это работало в какой-то момент в прошлом (последнее использовалось, вероятно, месяц назад).

Вчера это перестало работать. Проверяя вызовы REST, я увидел, что сначала выполняется запрос OPTIONS. Тип контента POST - application/json, поэтому на основе прочитанного я считаю это правильным. Я не уверен, почему это было ранее не отправлено - возможно, что у компании недавно была обновлена ​​версия Chrome, а старая версия не отправляла запросы на предполетные вопросы, но это всего лишь предположение. В любом случае, вот что я думаю, что соответствующий код в моем приложении для настройки Jetty для CORS:

FilterHolder holder = new FilterHolder(new CrossOriginFilter()); 
holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*"); 
holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true"); 
appHandler.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST)); 

Все отлично работает для запросов POST. Я могу проверить это, запустив Chrome с помощью флага --disable-web-security. Запрос OPTIONS не отправляется, и POST работает так, как следует.

Мое мышление заключается в том, что, поскольку он работает для POST, это не проблема авторизации или безопасности - это просто, что Jetty неправильно настроен для обработки запроса предварительной проверки (он просто возвращает 401).

Я не могу найти много документации для встроенного Jetty и какой из констант CrossOriginFilter использовать в качестве ключей свойств в вызовах setInitParameter (и, кроме того, поскольку второй аргумент этого вызова метода является строкой, у меня действительно есть не знаю, как форматировать значения).

Какие параметры следует устанавливать на CrossOriginFilter для дескрипторов свойств запросов OPTIONS? И если я сказал что-нибудь ошибочное выше или сделал какие-то ложные предположения, пожалуйста, исправьте меня! У меня очень ограниченный опыт в этом.

+1

Вы решили эту проблему? Если да, можете подать здесь ответ? – sag

ответ

1

Документация для CrossOriginFilter:

http://www.eclipse.org/jetty/documentation/current/cross-origin-filter.html

Javadoc для CrossOriginFilter:

http://download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/servlets/CrossOriginFilter.html

Фактический Исходный код: (иногда это помогает людям понять, тоже):

https://github.com/eclipse/jetty.project/blob/jetty-9.2.3.v20140905/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java

Короче говоря, вы, скорее всего, захотите добавить OPTIONS к разрешенным методам.

(Подобно тому, как Javadoc говорит)

FilterHolder holder = new FilterHolder(new CrossOriginFilter()); 
holder.setInitParameter("allowedMethods", "GET,POST,HEAD,OPTIONS"); 
appHandler.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST)); 

Теперь, чтобы решить другую ошибку у вас есть ...

Это не делает ничего ...

holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, 
    "true"); 

То есть а не ключ параметра init.(На самом деле это константа имени заголовка для Access-Control-Allow-Credentials), если вы хотите разрешить учетные данные, тогда сделайте так, как говорит javadoc.

holder.setInitParameter("allowCredentials", "true"); 
+0

Спасибо - я нашел это, но я действительно все еще не знаю, почему я получаю 401 в ответ на запрос OPTIONS. – Jer

+0

Я не уверен, если технически запрос OPTIONS попадает под «зонтик» CORS, но запрос OPTIONS по-прежнему поступает из другого домена, конечно (поскольку POST выполняется из другого домена). Я не уверен, что должен показать этот код. Это просто говорит, что для того, чтобы быть предполетным запросом, метод * должен быть * ВАРИАНТЫ. Я мог бы что-то упустить, но ничего не отвергается - если что-то, все *, но * ВАРИАНТЫ отбрасываются. – Jer

-2

Обновление: я пробовал ваш код точно, но я добавил фильтр в обработчик контекста, а не в приложение. Он работает таким образом.

 FilterHolder holder = new FilterHolder(new CrossOriginFilter()); 
    holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://localhost:8100"); 
    holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true"); 

    contextHandler.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST)); 
+0

Извините, у меня не было достаточно кода. 'appHandler' * есть * ServletContextHandler, похоже:' ServletContextHandler appHandler = новый ServletContextHandler (ServletContextHandler.SESSIONS); ' – Jer

0

Я решил эту проблему с помощью следующей конфигурации для фильтродержатель:

FilterHolder cors = new FilterHolder(CrossOriginFilter.class); 
cors.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*"); 
cors.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*"); 
cors.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "OPTIONS,GET,POST,HEAD"); 
cors.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin,Cache-Control"); 
cors.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, "false"); 

Chrome посылает заголовок «Cache-Control», если вы не позволяете этот заголовок с вашим CORS фильтром, затем на запрос OPTIONS не будут отвечать правильные заголовки. Большинство примеров CrossOriginFilter в Интернете не включают этот заголовок.

Вы можете опционально установить CHAIN_PREFLIGHT_PARAM на номер false (по умолчанию true). Если вы установите его на false, фильтр ответит на запрос без отправки запроса сервлету. Если вы хотите обработать запрос OPTIONS самостоятельно, вам не нужно устанавливать этот параметр.

Смежные вопросы