Проблема с фильтром AngularJS/Alfresco/CORS: нет заголовка «Access-Control-Allow-Origin»

У меня возникла проблема с Alfresco (5.0.d), моим клиентом AngularJS (1.4.3) и настройками CORS (обычно междоменный / заголовок No'Access-Control-Allow-Origin' присутствует в запрошенном ресурсе проблема).

Я вызываю REST API Alfresco из приложения AngularJS, работающего на локальном хосте: 3000, в экземпляр Alfresco, работающий на локальном хосте: 8080 (Tomcat, без обратного прокси-сервера впереди) .

Этот вызов XHR отлично работает:

http://localhost:8080/alfresco/service/slingshot/live-search-docs?t=Project&u=admin&pw=admin&alf_ticket=TICKET_9d9780c83b8b9525c7acb9d3d8da66c5c902fb76

Этот

http://localhost:8080/alfresco/service/api/login?u=admin&pw=admin

работает отлично только в Internet Explorer 11, но в Chrome и Firefox я получаю код состояния 200, возвращаемый с 0 байтами, и ошибку в консоли JS:

XMLHttpRequest не может загрузить http://localhost:8080/alfresco/service/api/login?u=admin&pw=admin. В запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». Таким образом, доступ к источнику 'http://localhost:3000' запрещен.

В файле Alfresco web.xml я включил фильтр CORS следующим образом:

   <!-- CORS Filter Mappings Begin -->
   <filter-mapping>
      <filter-name>CORS</filter-name>
      <url-pattern>/api/*</url-pattern>
      <url-pattern>/service/*</url-pattern>
      <url-pattern>/s/*</url-pattern>
      <url-pattern>/cmisbrowser/*</url-pattern>
   </filter-mapping>
   <!-- CORS Filter Mappings End -->

   <!-- CORS Filter Begin -->
   <filter>
      <filter-name>CORS</filter-name>
      <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
      <init-param>
         <param-name>cors.allowGenericHttpRequests</param-name>
         <param-value>true</param-value>
      </init-param>
      <init-param>
         <param-name>cors.allowOrigin</param-name>
         <!-- <param-value>http://localhost:3000 http://localhost:8081 http://localhost:8080 https://localhost</param-value> -->
         <param-value>*</param-value>
      </init-param>
      <init-param>
         <param-name>cors.allowSubdomains</param-name>
         <param-value>true</param-value>
      </init-param>
      <init-param>
         <param-name>cors.supportedMethods</param-name>
         <param-value>GET, HEAD, POST, PUT, DELETE, OPTIONS</param-value>
      </init-param>
      <init-param>
         <param-name>cors.supportedHeaders</param-name>
         <param-value>origin, authorization, x-file-size, x-file-name, content-type, accept, x-file-type</param-value>
      </init-param>
      <init-param>
         <param-name>cors.supportsCredentials</param-name>
         <param-value>true</param-value>
      </init-param>
      <init-param>
         <param-name>cors.maxAge</param-name>
         <param-value>3600</param-value>
      </init-param>
   </filter>-->
   <!-- CORS Filter End -->

Вызовы из Angular:

Тот, который работает нормально:

$http.get('http://localhost:8080/alfresco/service/slingshot/live-search-docs?t=Project&alf_ticket=TICKET_9d9780c83b8b9525c7acb9d3d8da66c5c902fb76').then(function(response) {
    console.log('DATA LOADED: ' + response.items);
    $scope.contents = response.items;
});

Заголовки ответа:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Content-Length: 85
Date: Thu, 13 Aug 2015 06:37:24 GMT

Тот, который терпит неудачу:

$http.get('http://localhost:8080/alfresco/service/api/login?u=' + $scope.user.email + '&pw=' + $scope.user.password).
      then(function(response) {
        console.log('ALF_TICKET: ' + response.data.ticket);
        $scope.alfTicket = response.data.ticket;
        $state.go('admin-panel.default.introduction');
      }, function(response) {
        console.log('LOGIN FAILED');
      });

Заголовки ответа:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000
Vary: Origin
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 13 Aug 2015 06:38:36 GMT

У меня настроен $httpProvider в моем приложении AngularJS, просто чтобы быть уверенным:

.config(['$httpProvider', function($httpProvider) {
        $httpProvider.defaults.useXDomain = true;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];
    }

Запрос CURL, смоделированный с другого хоста, работает нормально, однако интересно то, что я не получаю заголовок Access-Control-Allow-Origin в ответе, несмотря на включенный фильтр CORS в Alfresco:

curl -H "Origin: http://www.microsoft.com" --verbose "http://alfresco.mycompany.ch:8080/alfresco/service/api/login?u=admin&pw=12@echo"

* Hostname was NOT found in DNS cache
*   Trying 10.10.0.183...
* Connected to alfresco.mycompany.ch (10.10.0.183) port 8080 (#0)
> GET /alfresco/service/api/login?u=admin&pw=12@echo HTTP/1.1
> User-Agent: curl/7.37.1
> Host: alfresco.mycompany.ch:8080
> Accept: */*
> Origin: http://www.microsoft.com
> 
< HTTP/1.1 200 OK
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< Cache-Control: no-cache
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Pragma: no-cache
< Content-Type: application/json;charset=UTF-8
< Content-Length: 85
< Date: Thu, 13 Aug 2015 08:11:15 GMT
< 
{
   "data":
   {
"ticket":"TICKET_7d07634afbb25a7e823c0348d907e0790eeff97e"
   }
}
* Connection #0 to host alfresco.mycompany.ch left intact

поэтому я думаю, что это связано с клиентом/AngularJS.

=== Обновление 1: ===

Я попытался добавить перехватчик в $httpProvider, как показано ниже, но это не помогает. Я не вижу заголовков, которые я устанавливаю, ни в одном из ответов, хотя перехватчик вызывается.

    $httpProvider.interceptors.push(function() {
      return {
       'request': function(request) {
           return request;
        },
        'response': function(response) {
           console.log('Interceptor called.');
           response.config.headers['MyTestHeader'] = '12345';
           response.config.headers['Access-Control-Allow-Origin'] = '*';
           return response;
        }
      };
    });

=== Обновление 2: ===

Еще несколько находок, но теперь немного странных со стороны Alfresco. Я делаю два почти одинаковых вызова API для следующих двух URL-адресов:

Как видите, они отличаются только в конце. Тот, у кого /whatever, возвращает заголовок ответа Access-Control-Allow-Origin, тот, у кого /login, нет. Это должно быть связано с конфигом/веб-скриптом Alfresco, но я пока не нашел его происхождение.

curl -H "Origin: http://www.microsoft.com" --verbose "http://localhost:8080/alfresco/service/api/login"

*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /alfresco/service/api/login HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://www.microsoft.com
>
< HTTP/1.1 400 Bad Request
< Server: Apache-Coyote/1.1
< Cache-Control: no-cache
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Pragma: no-cache
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Thu, 13 Aug 2015 12:49:46 GMT
< Connection: close
<

Но этот:

curl -H "Origin: http://www.microsoft.com" --verbose "http://localhost:8080/alfresco/service/api/whatever"

*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /alfresco/service/api/whatever HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://www.microsoft.com
>
< HTTP/1.1 404 Not Found
< Server: Apache-Coyote/1.1
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Origin: http://www.microsoft.com
< Vary: Origin
< Cache-Control: no-cache
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Pragma: no-cache
< Content-Type: text/html;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Thu, 13 Aug 2015 12:52:15 GMT
<

Я также попробовал фильтр CORS Tomcat, тот же результат.

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Вопросы:

(1) Я что-то упустил на стороне клиента/AngularJS $http? Должен ли я использовать angular-http-interceptor? (Извините, новичок в AngularJS). Я думаю, что это, скорее всего, причина здесь, но не уверен, чего не хватает.

(2) Я не понимаю, почему фильтр CORS не добавляет заголовок «Access-Control-Allow-Origin» к обоим ответам, а только к одному вызову API, поскольку оба URL-адреса API начинаются с /alfresco/service, что должно обрабатываться фильтром CORS согласно <url-pattern>/service/*</url-pattern>

(И почему для одного URL API работает, а для другого нет? Единственное отличие, которое я вижу, это то, что в одном случае я уже аутентифицирован и использую alf_ticket, а в другом — нет. Но даже если я добавьте (ненужный) alf_ticket к вызову входа в систему, это не имеет никакого значения.)

(3) Почему тогда он вообще работает в IE? (кстати: с расширением Chrome https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi, он также работает в Chrome.)

Связанный вопрос SO: междоменный вызов с использованием REST Alfresco


person Mathias Conradt    schedule 13.08.2015    source источник


Ответы (2)


У меня та же проблема, по какой-то причине вызов API входа в систему «GET» не возвращает «Access-Control-Allow-Origin» в заголовках. ВРЕМЕННОЕ РЕШЕНИЕ: вызов «POST» работает нормально!

person bjorn    schedule 23.10.2015
comment
Но на самом деле это хороший намек, я никогда не обращал внимания на метод POST, что API входа также принимает POST. Я дам ему попробовать. Я еще не понял причину вышеупомянутой проблемы с GET, я даже уже проверил исходный код Alfresco. - person Mathias Conradt; 23.10.2015

Я столкнулся с подобной проблемой и решил ее, используя «/alfresco/s/» вместо «/alfresco/service/».

В вашем случае попробуйте нажать с помощью

http://localhost:8080/alfresco/s/api/login?u=admin&pw=admin.

Попробуйте, если это работает.

person Anshu Kumar    schedule 29.10.2015
comment
Мне не терпится узнать, можем ли мы делать междоменные запросы, используя общий прокси. Это сработает?? Это означает, что я пытаюсь использовать hostname:port/share/proxy/alfresco/api.... Но я получаю XMLHttpRequest, который не может загрузить имя хоста:port/share/proxy/alfresco/api/people/VGARGNE/. В запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». Следовательно, доступ к источнику 'localhost:8080' запрещен. - person Anshu Kumar; 29.10.2015
comment
Не работает для меня. И оба шаблона URL фактически включены в сопоставления фильтров CORS. Все, что сработало для меня, это переключиться с метода GET на метод POST. - person Mathias Conradt; 11.12.2015