Как и в версии Chrome версии 37, запросы на междоменные запросы не выполняются (снова), если сервер имеет аутентификацию, даже если все заголовки CORS установлены правильно. Это находится на localhost
(мой dev ПК).
Некоторые из вас могут быть осведомлены об истории ошибок Chrome/CORS/auth, особенно при использовании HTTPS. Моя проблема не связана с HTTPS: у меня есть приложение AngularJS из localhost:8383
, разговаривающее с сервером Java (Jetty) на localhost:8081
, у которого активирован HTTP BASIC. GET работают нормально, но POSTs сбой 401:
XMLHttpRequest cannot load http://localhost:8081/cellnostics/rest/patient.
Invalid HTTP status code 401
Ранее я написал специальный (Java) фильтр CORS, который устанавливает правильные заголовки CORS, которые работали до v36. Он терпит неудачу в v37, а также последний v38 (38.0.2125.101 м). Он по-прежнему работает с Internet Explorer 11 (11.0.9600) и Opera 12.17 (сборка 1863).
GET выполняется успешно, но POST сбой. Похоже, что Chrome предварительно отправляет все мои POST-сообщения из-за типа контента: "application/json", и что это запрошенный запрос OPTIONS, который терпит неудачу.
В приложении Angular я явно устанавливаю следующие заголовки запросов. AFAIK этот параметр для withCredentials
должен гарантировать, что учетные данные отправляются даже для запросов OPTIONS:
//Enable cross domain calls
$httpProvider.defaults.useXDomain = true;
//Send all requests, even OPTIONS, with credentials
$httpProvider.defaults.withCredentials = true;
Ниже приведен запрос/ответ. Вы можете видеть, что метод OPTIONS включен в заголовке Access-Control-Allow-Methods
. Вы также можете увидеть, что начало приложения Javascript явно включено: Access-Control-Allow-Origin: http://localhost:8383
.
Remote Address:[::1]:8081
Request URL:http://localhost:8081/cellnostics/rest/medicaltest
Request Method:OPTIONS
Status Code:401 Full authentication is required to access this resource
Request headers:
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,af;q=0.6
Access-Control-Request-Headers:accept, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:localhost:8081
Origin:http://localhost:8383
Referer:http://localhost:8383/celln-web/index.html
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.101 Safari/537.36
Response headers:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With, Accept
Access-Control-Allow-Methods:POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin:http://localhost:8383
Access-Control-Max-Age:3600
Content-Length:0
Server:Jetty(8.1.8.v20121106)
WWW-Authenticate:Basic realm="Cellnostics"
Кто-нибудь понял, что мне еще нужно делать? Я попытался очистить кэш Chrome перед тестированием, перезапуском и убедиться, что перед перезагрузкой не осталось фоновых процессов Chrome, поэтому я уверен, что не было никаких длительных проблем с кешем кэша.
Мне пришлось переключиться на IE 11 для тестирования моей веб-разработки. Тот факт, что одна и та же настройка клиента и сервера по-прежнему работает для IE и Opera, и тот факт, что есть история ошибок Chrome/CORS, заставляет меня подозревать Chrome.
EDIT: здесь выписка из списка событий net-internals Chrome:
t=108514 [st=0] +URL_REQUEST_START_JOB [dt=4]
--> load_flags = 336011264 (BYPASS_DATA_REDUCTION_PROXY | DO_NOT_SAVE_COOKIES | DO_NOT_SEND_AUTH_DATA | DO_NOT_SEND_COOKIES | MAYBE_USER_GESTURE | VERIFY_EV_CERT)
--> method = "OPTIONS"
--> priority = "LOW"
--> url = "http://localhost:8081/cellnostics/rest/patient"
...
t=108516 [st=2] HTTP_TRANSACTION_SEND_REQUEST_HEADERS
--> OPTIONS /cellnostics/rest/patient HTTP/1.1
Host: localhost:8081
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:8383
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.101 Safari/537.36
Access-Control-Request-Headers: accept, content-type
Accept: */*
Referer: http://localhost:8383/celln-web/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,af;q=0.6
Итак, похоже, что заголовок авторизации не отправляется с предварительным полем OPTIONS, хотя я явно устанавливаю withCredentials = true
.
Однако почему IE и Opera все еще работают? Является ли Chrome более стандартизированным в этом отношении? Почему это сработало, а затем начать с отказа от версии v37?
EDIT: инструменты Chrome dev не показывают Content-Type
запроса в дампах выше, но здесь он из журнала сети. Первая фотография показывает POST, когда аутентификация сервера отключена, а тип контента правильно отправлен как "application/json". Второй рис., Когда включен auth, показывая запрос запроса OPTIONS (кажется, OPTIONS всегда отправляется с типом контента "text/plain"?).