Chrome v37/38 CORS no (de nuevo) con 401 para las OPCIONES de pre-vuelo de las solicitudes de

Como de Chrome versión 37, pre-sinfín, de la cruz-dominio de las solicitudes están fallando (de nuevo) si el servidor tiene habilitado la autenticación, aunque todos los CORS encabezados están configurados correctamente. Esto es en localhost (mi dev PC).

Algunos de ustedes pueden estar consciente de la historia de Chrome/CORS/auth errores, especialmente cuando HTTPS estaba involucrado. Mi problema no no implican HTTPS: tengo una aplicación AngularJS sirve de localhost:8383 hablando de Java (Jetty) server en localhost:8081 que ha BÁSICA de HTTP auth activado. Consigue trabajo bien, pero Puestos a fallar con un 401:

XMLHttpRequest cannot load http://localhost:8081/cellnostics/rest/patient.
Invalid HTTP status code 401

Que he escrito anteriormente una costumbre (Java) CORS filtro que establece el correcto CORS cabeceras, que trabajó hasta v36. Se produce un error en la v37 y también la última v38 (38.0.2125.101 m). Es todavía funciona como se espera con Internet Explorer 11 (11.0.9600) y Opera 12.17 (construir 1863).

OBTENER solicitudes de éxito, pero POSTfalle. Se ve como el Cromo es pre-espiral todos mis POSTs debido a que el tipo de contenido: «application/json», y que es la pre-sinfín de OPCIONES de solicitud que está fallando.

En el ángulo de aplicación de establecer explícitamente los siguientes encabezados de solicitud. AFAIK esta configuración para withCredentials debe asegurarse de que las credenciales se envían, incluso para las OPCIONES de solicitudes:

//Enable cross domain calls
$httpProvider.defaults.useXDomain = true;

//Send all requests, even OPTIONS, with credentials
$httpProvider.defaults.withCredentials = true;

A continuación es el de solicitud/respuesta. Se puede ver que el método de OPCIONES está activada en el Access-Control-Allow-Methods encabezado. También se puede ver que la aplicación de Javascript origen está explícitamente permitido: 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"

Ha alguien tiene alguna idea de qué más debo hacer? De hecho estoy seguro que para borrar la caché de Chrome antes de la prueba, reiniciar y asegurándose de que no había antecedentes de Chrome procesos que queda en funcionamiento antes de reiniciar, así que estoy bastante seguro de que no había persistente auth problemas de caché.

He tenido que cambiar a IE 11 para probar mi desarrollo web. El hecho de que el mismo cliente y la configuración del servidor todavía funciona para IE y Opera, y el hecho de que hay un historial de Chrome/CORS errores, me hace sospechar que Chrome.

EDIT: he Aquí un extracto de la Chrome net-internals lista de eventos:

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

Por lo que se ve como el encabezado de Autorización no se envía con las OPCIONES pre-vuelo, a pesar de que yo establezca explícitamente withCredentials = true.

Sin embargo, ¿por qué habría de IE y Opera todavía funcionan? Es el Cromo más compatible con los estándares en este sentido? ¿Por qué el trabajo y, a continuación, comenzar a fallar de v37?

EDICIÓN: Chrome dev tools no mostrar la Content-Type de la solicitud en los vertederos más arriba, pero es a partir del registro de la Red. La primera foto muestra el POST cuando el servidor de autenticación está deshabilitado, con el tipo de contenido enviado correctamente como «application/json’. La 2da pic es cuando la autenticación está habilitada, mostrando la solicitud de OPCIONES no (parece que las OPCIONES se envía siempre con el tipo de contenido text/plain’?).

Chrome v37/38 CORS no (de nuevo) con 401 para las OPCIONES de pre-vuelo de las solicitudes de
Chrome v37/38 CORS no (de nuevo) con 401 para las OPCIONES de pre-vuelo de las solicitudes de

  • Todavía no se muestran todos los encabezados de la respuesta. Podría usted mostrar la respuesta completa para la solicitud de OPCIONES así? Si no lo puedes ver en las herramientas de desarrollo, visite chrome://net-internals/#events, a continuación, hacer la solicitud, a continuación, volver a la página de chrome y encontrar el URL_REQUEST que describe su solicitud.
  • Cuando tengo un problema con el CORS, era debido a que «content-type». Y no veo ningún tipo de contenido en su consulta.
  • Véase mi edición anterior muestra el registro de la red con el Tipo de Contenido

4 Kommentare

  1. 7

    @Cornel Masson, ¿se resuelve el problema? Yo no entiendo por qué el servidor está pidiendo para autenticar la solicitud de OPCIONES, pero estoy frente a esta misma cuestión, en contra de un servidor SAP NetWeaver. He leído todo el CORS especificación (recomiendo) para que yo pueda aclarar algunas de tus dudas.

    Acerca de su sentencia

    En el ángulo de aplicación de establecer explícitamente los siguientes encabezados de solicitud. AFAIK esta configuración para withCredentials debe asegurarse de que las credenciales se envían, incluso para las OPCIONES de solicitudes:

    • De acuerdo a la CORS especificación cuando un agente de usuario (por lo tanto, un navegador) preflights una solicitud (solicitudes con OPCIONES de método HTTP), DEBE excluir las credenciales de usuario (cookies de autenticación HTTP…) para cualquier solicitud de OPCIONES no se pueden solicitar autenticado. El navegador solicitará como autenticada de la solicitud real (el uno con el solicitado método HTTP como GET, POST…), pero no la comprobación previa solicitud.
    • Para navegadores no DEBE enviar las credenciales en la solicitud de OPCIONES. Que van a hacer en peticiones concretas. Si usted escribe withCredentials = true el navegador debe hacer lo que yo digo.

    De acuerdo con tu frase:

    Se ve como el Cromo es pre-espiral todos mis POSTs debido a que el tipo de contenido: «application/json»:

    • La especificación también dice que una de las comprobaciones solicitud será hecha por el navegador cuando el encabezado no es un simple «encabezado» y aquí tenéis lo que significa:

      Un encabezado que dice ser un simple encabezado si el nombre de campo de encabezado es un ASCII no distingue mayúsculas de minúsculas partido para Aceptar, Aceptar-el Lenguaje, el Contenido o en el Idioma o si es un ASCII no distingue mayúsculas de minúsculas partido para el Tipo de Contenido y el campo de encabezado de valor de los medios de comunicación tipo (excepto los parámetros) es un ASCII entre mayúsculas y minúsculas coincidan para application/x-www-form-urlencoded, multipart/form-data, o text/plain.

    • application/json no está incluido por lo que el navegador DEBE de comprobación previa a la solicitud como se hace.

    Si alguien encuentra una solución sería apreciado.

    EDICIÓN: acabo de encontrar a una persona con el mismo problema que refleja los problemas reales, y si usted utiliza el mismo servidor como él puede tener suerte, https://evolpin.wordpress.com/2012/10/12/the-cors/

    • No he encontrado una solución, pero una solución. Dado que el problema sólo se produce en localhost, he configurado mi proceso de construcción para deshabilitar la autenticación en el servidor cuando se ejecuta en localhost (es decir, mi dev PC). Para todas las otras implementaciones (dev server, prueba, producción), se habilita la autenticación. No me gusta esta solución, porque prefiero tener completa la paridad entre lo que puedo desarrollar y lo que se implementa. Para mitigar el riesgo, siempre me implementar primero en una máquina virtual local que ha auth encendido para hacer el final de pruebas de humo antes de la liberación.
    • Acerca de su solución, hay una cosa que no entiendo. Si en tu servidor de desarrollo es en localhost como su desarrollo de la aplicación, no es necesario deshabilitar la autenticación, de modo que su aplicación y el servidor podría estar en el mismo dominio (localhost), así CORS no sería necesaria (esto entra en juego cuando el acceso a los recursos de un dominio distinto al de la aplicación).
    • está en otro puerto en localhost. CORS se aplica tan pronto como cualquiera de los componentes de la URL es diferente, es decir, el esquema (por ejemplo, http://), el dominio (por ejemplo, http://www.example.com) o el puerto (por ejemplo, 8081 vs 8080). El problema es que para el desarrollo de una página de Javascript de cliente, el desarrollador del IDE u otras herramientas dev suelen permitir la rápida porción de la aplicación de un servidor web integrado en su propio puerto, que es diferente a el puerto en el que el DESCANSO de servidor (un proyecto diferente/aplicación) está escuchando. Un problema muy común para los desarrolladores, en localhost.
    • Ahora entiendo, gracias. Estoy frente a este mismo tema, sino dejar que el habilitada la autenticación. Una aproximación es el uso de un proxy inverso, pero luego, el proxy debe estar escuchando en el mismo puerto, ya que la aplicación de servidor web, por lo que necesito encontrar un servidor que puede ser ambas cosas a la vez (servidor web y proxy inverso). Me han hablado de que Jetty puede hacer esto. Tal vez usted quiere tener una oportunidad. Buena suerte
  2. 2

    Mismo aquí. Yo uso Windows Autenticación NTLM. Hasta Chrome versión 37 funcionó OK. En las versiones 37, 38 falla con 401 (no autorizado), debido a la solicitud de Autorización de encabezado de la falta de pre-vuelo OPCIONES en ambos puestos, y POST.

    Lado del servidor es un Web de Microsoft Api 2.1. He intentado varias CORS, incluida la última paquete de NuGet de Microsoft fue en vano.

    Tengo a la solución de Cromo mediante el envío de solicitud GET en lugar de POST, y rompiendo en lugar de datos de gran tamaño en varias solicitudes, ya que la URL tiene un límite de tamaño natural.

    Aquí están encabezados de Solicitud y Respuesta:


    Request URL: http://localhost:8082/api/ConfigurationManagerFeed/
    Method: OPTIONS
    Status: 401 Unauthorized
    
    Request Headers
    Accept: */*
    Accept-Encoding: gzip,deflate,sdch
    Accept-Language: en-US,en;q=0.8,ru;q=0.6
    Access-Control-Request-Headers: accept, content-type
    Access-Control-Request-Method: POST
    Connection: keep-alive
    Host: localhost:8082
    Origin: http://localhost:8383
    Referer: http://localhost:8383/Application/index.html
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36
    X-DevTools-Emulate-Network-Conditions-Client-Id: 49E7FC68-A65C-4318-9292-852946051F27
    
    Response Headers
    Cache-Control: private
    Content-Length: 6388
    Content-Type: text/html; charset=utf-8
    Date: Fri, 24 Oct 2014 13:40:07 GMT
    Server: Microsoft-IIS/7.5
    WWW-Authenticate: Negotiate
    NTLM
    X-Powered-By: ASP.NET
    
    • Por ahora, voy a conseguir alrededor de esto, mediante la desactivación de HTTP BASIC auth cuando se prueba en mi localhost. En la producción de la webapp se sirve desde el mismo host/puerto como el servidor, por lo que no CORS problema.
    • La Web de la Api de trabajo es utilizado por varias aplicaciones; de SharePoint y algunas aplicaciones Móviles son entre ellos, de manera de hosting en el mismo sitio web no es buena solución. Lo curioso es que el Violinista «corrige» a las peticiones de Chrome, ya que el Violinista proxies de las solicitudes. Así que, en su caso, usted puede evitar el uso de el Violinista en el desarrollo de las cajas.
    • Sí, que es una muy válida escenario de producción y la irritación de Chrome error. Yo no he considerado sólo la función de proxy siempre todo, que podría ser una idea, gracias.
  3. 2

    De MS IIS he implementado otra solución reemplazando estándar de Microsoft página de ciclo de vida, es decir, la elaboración de las OPCIONES de la derecha en el comienzo de la petición HTTP en el mundial.ascx:

    public class Global : HttpApplication
    {
        ///<summary>Check and cofigure CORS Pre-flight request on Begin Request lifecycle
        ///</summary>
        protected void Application_BeginRequest()
        {
            if (Request.Headers.AllKeys.Contains(CorsHandler.Origin) && Request.HttpMethod == "OPTIONS")
            {
                Response.StatusCode = (int)HttpStatusCode.OK;
                Response.Headers.Add(CorsHandler.AccessControlAllowCredentials, "true");
                Response.Headers.Add(CorsHandler.AccessControlAllowOrigin, Request.Headers.GetValues(CorsHandler.Origin).First());
                string accessControlRequestMethod = Request.Headers.GetValues(CorsHandler.AccessControlRequestMethod).FirstOrDefault();
                if (accessControlRequestMethod != null)
                {
                    Response.Headers.Add(CorsHandler.AccessControlAllowMethods, accessControlRequestMethod);
                }
                var hdrs = Request.Headers.GetValues(CorsHandler.AccessControlRequestHeaders).ToList();
                hdrs.Add("X-Auth-Token");
                string requestedHeaders = string.Join(", ", hdrs.ToArray());
                Response.Headers.Add(CorsHandler.AccessControlAllowHeaders, requestedHeaders);
                Response.Headers.Add("Access-Control-Expose-Headers", "X-Auth-Token");
                Response.Flush();
            }
        }
    }
    
    • ¿qué es CorsHandler?
  4. 2

    Estábamos teniendo este mismo problema al intentar depurar un Angular 4 front-end de la aplicación que se ejecuta en localhost:4200 (utilizando el Angular de la CLI Vivir Servidor de Desarrollo). El Angular de la aplicación hace que las peticiones http a un ASP .Net WebApi2 aplicación que se ejecuta en localhost (servidor Web IIS) con la Autenticación de Windows. El problema sólo se produjo cuando se hace una petición POST en Chrome (aunque nuestro WebApi está configurado para CORs). Hemos sido capaces de solucionar temporalmente el problema de partida hasta el Violinista y el funcionamiento de un proxy inverso hasta que encontré este post (Gracias).

    El mensaje de error en Chrome depurador:
    Respuesta a la comprobación previa petición de no pasar el control de acceso de verificación: No ‘Access-Control-Allow-Origin’ encabezado presente en el recurso solicitado

    Añadiendo el siguiente código a nuestro Web Api2 – Global.archivo asax resuelto este problema.

    Si usted está buscando la «CorsHandler», usted puede simplemente reemplazar George post con la rígida cadena de valores de la siguiente manera:

        protected void Application_BeginRequest()
        {
            if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
            {
                Response.StatusCode = (int)HttpStatusCode.OK;
                Response.Headers.Add("Access-Control-Allow-Credentials", "true");
                Response.Headers.Add("Access-Control-Allow-Origin", Request.Headers.GetValues("Origin").First());
                string accessControlRequestMethod = Request.Headers.GetValues("Access-Control-Request-Method").FirstOrDefault();
                if (accessControlRequestMethod != null)
                {
                    Response.Headers.Add("Access-Control-Allow-Methods", accessControlRequestMethod);
                }
                var hdrs = Request.Headers.GetValues("Access-Control-Request-Headers").ToList();
                hdrs.Add("X-Auth-Token");
                string requestedHeaders = string.Join(", ", hdrs.ToArray());
                Response.Headers.Add("Access-Control-Allow-Headers", requestedHeaders);
                Response.Headers.Add("Access-Control-Expose-Headers", "X-Auth-Token");
                Response.Flush();
            }
        }
    

    Saludos,

    Chris

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea