xmlHttp.getResponseHeader + Не работает для CORS
У меня есть asp.NET WCF на .NET 4. Эта служба используется для аутентификации пользователей. Мы отправляем имя пользователя и пароль, а затем заголовок HTTP должен быть возвращен с включенным cookie аутентификации. Используя локальную тестовую страницу, она работает правильно. Теперь я пытаюсь получить доступ к перекрестной домену информации заголовка. Я установил свою тестовую страницу на другой машине и настроен на вызов в дополнение к WCF. Вызов работает, и ответ «данные» в вызове правильный. Однако я не могу получить доступ к информации заголовка одним из следующих способов:
alert(xmlHttp.getAllResponseHeaders());
или
alert(xmlHttp.getResponseHeader("Set-Cookie"));
Используя отладчик в IE и «Live HTTP Header» для Firefox, я вижу, что информация заголовка возвращается.
- В чем разница между сервисом службы WCF и библиотекой услуг WCF?
- Правильный способ связи WSSE Usernametoken для SOAP webservice
- Как я могу использовать WCF только с базовыми атрибутами, SSL и базовой аутентификацией в IIS?
- Передача файлов cookie FormsAuthentication в службу WCF
- Служба проверки подлинности с использованием WCF
На моей глобальной странице ajax я устанавливаю ответ для обработки CORS.
private void EnableCrossDomainAjaxCall() { HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); if (HttpContext.Current.Request.HttpMethod == "OPTIONS") { HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache"); HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000"); HttpContext.Current.Response.End(); } }
Это AJAX, который я использую для вызова службы:
$("#btnLogin").click(function (e) { var geturl; geturl = $.ajax({ // type: "POST", type: "GET", contentType: "application/json; charset=utf-8", url: 'http://10.0.4.66/AuthenticationService.svc/Login?Name=test&password=pwsd', // url: '../SecurityServer/AuthenticationService.svc/Login?Name=test&password=pwsd', dataType: "jsonp", error: function (request, status, error) { alert('Error Occured'); }, crossdomain: true, success: function (data, textStatus, xmlHttp) { // alert(xmlHttp.getResponseHeader("Content-Type")); document.write(xmlHttp.getResponseHeader("Content-Type") + "
"); alert(xmlHttp.getAllResponseHeaders()); alert(xmlHttp.getResponseHeader("Set-Cookie")); var headers = ''; var headerPair = xmlHttp.getAllResponseHeaders('wcfCookie').split("\r\n"); var output = ''; $.each(headerPair, function (key, line) { var parts = line.split(':'); if (parts[0] == 'wcfCookie') { ChocChip = parts[1] return false } }); } });
Ниже приведена информация моего заголовка, взятая из ‘Live HTTP headers’
Date: Mon, 04 Feb 2013 12:12:40 GMT Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 4.0.30319 Access-Control-Allow-Origin: * Set-Cookie: wcfCookie=8D38D5D6A0F138FEB595DD016F7694EDDF3E6757C82ED3D419F5047A5294974C1885487465CEC0A0BCC2B3802C7B03FF9F5370A05D4CCBDDDABCB1558C3816044BF4F78209BF38C6B1A7CAD34CD3C85C40B8515CFB1C2B2694BC78803D8DACB4 Content-Length: 65 Cache-Control: application/json; charset=utf-8 Content-Type: application/x-javascript
Во-первых, небольшой фон:
Вы используете Access-Control-Allow-Headers
, который указывает, какие заголовки запросов клиенту разрешено отправлять , но вы не указываете, какие заголовки ответов разрешено клиенту читать . Чтобы клиент мог читать непростые заголовки ответов, вам нужно использовать Access-Control-Expose-Headers
. На странице HTML5 Rocks CORS :
Во время запроса CORS метод
getResponseHeader()
может получить доступ только к простым заголовкам ответов. Простые заголовки ответов определяются следующим образом:
- Cache-Control
- Content-Language
- Тип содержимого
- Истекает
- Последнее изменение
- Pragma
Если вы хотите, чтобы клиенты имели доступ к другим заголовкам, вам нужно использовать заголовок
Access-Control-Expose-Headers
. Значение этого заголовка представляет собой список заголовков ответов с разделителями-запятыми, которые вы хотите открыть клиенту.
Итак, учитывая эту новую информацию, вы можете:
HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "Set-Cookie");
… но есть нечто большее, чем это.
Теперь, фактический ответ:
Здесь есть еще одна серьезная проблема: спецификация XHR явно запрещает чтение Set-Cookie
. Это потому, что это функционально кросс-доменная хитрость .
Предположим, что домен A выполняет междоменный запрос в домен B. Когда домен B устанавливает cookies, он устанавливает cookie только для домена только для домена B. Любая попытка домена A для чтения файлов cookie домена B является нарушением политики одинакового происхождения для доступа к файлам cookie.
Я не знаю WCF, поэтому я не уверен, что лучше всего делать то, что вы хотите, но я бы предположил, что решение может состоять в том, чтобы передать токен аутентификации не через cookies (например, X-WCF-Auth
заголовок?), который домен A читает, а затем устанавливает свой собственный файл cookie.
Политики безопасности браузера могут блокировать ваш ответ, потому что вы не установили:
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials","true");
Если это не помогает, попробуйте добавить
xhrFields: { withCredentials: true }
к вашим вариантам ajax
также может быть стоит.