jquery wcf authentication wcf-security cors

jquery - xmlHttp.getResponseHeader+no funciona para CORS



wcf authentication (2)

Tengo un asp.NET WCF en .NET 4. Este servicio se utiliza para autenticar usuarios. Estamos enviando un nombre de usuario y contraseña y luego se debe devolver un encabezado HTTP con la cookie de autenticación incluida. Usando una página de prueba alojada localmente, esto está funcionando correctamente. Ahora estoy intentando acceder al dominio cruzado de información de encabezado. Instalé mi página de prueba en una máquina diferente y la configuré para llamar al WCF. La llamada está funcionando y la respuesta de "datos" en la llamada es correcta. Sin embargo, no puedo acceder a la información del encabezado con ninguno de los siguientes:

alert(xmlHttp.getAllResponseHeaders());

o

alert(xmlHttp.getResponseHeader("Set-Cookie"));

Al usar el depurador en IE y el complemento ''Live HTTP Header'' para Firefox, puedo ver que se está devolviendo la información del encabezado.

En mi página global ajax estoy configurando la respuesta para manejar 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(); } }

Este es el AJAX que estoy usando para llamar al servicio:

$("#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") + "<br/>"); 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 } }); } });

A continuación se muestra la información de mi encabezado tomada de ''Encabezados HTTP en vivo''

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


Las políticas de seguridad del navegador podrían bloquear su respuesta porque no ha configurado:

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials","true");

Si eso no ayuda, intente agregar

xhrFields: { withCredentials: true }

A tu ajax opciones también pueden valer una oportunidad.


Primero, un poco de fondo:

Está utilizando Access-Control-Allow-Headers , que especifica qué encabezados de solicitud puede enviar el cliente, pero no está especificando qué encabezados de respuesta puede leer el cliente. Para permitir que el cliente lea encabezados de respuesta no simples, necesita usar Access-Control-Expose-Headers . Desde la página de HTML5 Rocks CORS :

Durante una solicitud CORS, el método getResponseHeader() solo puede acceder a encabezados de respuesta simple. Los encabezados de respuesta simple se definen de la siguiente manera:

  • Control de caché
  • Contenido-lenguaje
  • Tipo de contenido
  • Vence
  • Última modificación
  • Pragma

Si desea que los clientes puedan acceder a otros encabezados, debe utilizar el encabezado Access-Control-Expose-Headers . El valor de este encabezado es una lista delimitada por comas de los encabezados de respuesta que desea exponer al cliente.

Entonces, dada esa nueva información, podrías hacer:

HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "Set-Cookie");

... pero hay más que eso.

Ahora, la respuesta real:

Hay un problema más grave aquí: la especificación XHR explícitamente no permite leer Set-Cookie . Esto se debe a que es funcionalmente un ataque de robo de cookies entre dominios .

Supongamos que el dominio A realiza una solicitud de dominio cruzado al dominio B. Cuando el dominio B establece cookies, está configurando cookies específicas del dominio solo para el dominio B. Cualquier intento por parte del dominio A de leer las cookies del dominio B es una violación de la política del mismo origen para el acceso a las cookies.

No sé WCF, así que no estoy seguro de cuál es la mejor manera de hacer lo que realmente quieres, pero supongo que la solución podría ser pasar un token de autenticación no a través de cookies (por ejemplo, un X-WCF-Auth encabezado?) ese dominio A lee y luego establece su propia cookie.