• 跨域请求中常见的几个问题


    一. Header相关的几个概念

    CORS: 跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP头来告诉浏览器  让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。

    出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。

    origin: web的origin 被定义为由协议,域和端口组成的 URL访问。仅当协议,域和端口全部匹配,两对象才具有相同的origin。

    Access-Control-Allow-Origin: 该响应是否可以与来自给定的请求代码共享origin。

    Access-Control-Allow-Origin:*  #允许任何源的代码访问资源
    Access-Control-Allow-Origin: https://developer.mozilla.org  #允许请求来自https://developer.mozilla.org 的代码访问资源。
    

    Access-Control-Allow-Methods: 在对preflight request(预检请求)的应答中明确了客户端所要访问的资源允许使用的方法或方法列表

    Access-Control-Allow-Methods POST,GET,OPTIONS,PUT
    

    Access-Control-Allow-Headers:  用于preflight request(预检请求)种,列出了将会在正式请求的Access-Control-Expose-Headers 字段中出现的首部信息,用于响应包含在Access-Control-Request-Headers 首部的预检请求。

    Access-Control-Allow-Headers Content-Type,access-control-allow-credentials,access-control-allow-origin
    

    Access-Control-Max-Age: 这个响应首部表示preflight request(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久。

    Access-Control-Max-Age: 600 #
    

    CORS中的预检请求(option): 在 CORS 中,可以使用 OPTIONS 方法发起一个预检请求(一般都是浏览检测到请求跨域时,会自动发起),以检测实际请求是否可以被服务器所接受。预检请求报文中的 Access-Control-Request-Method首部字段告知服务器实际请求所使用的 HTTP 方法;Access-Control-Request-Headers 首部字段告知服务器实际请求所携带的自定义首部字段。服务器基于从预检请求获得的信息来判断,是否接受接下来的实际请求。

    OPTIONS /resources/post-here/ HTTP/1.1
    Host: bar.other
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Connection: keep-alive
    Origin: http://foo.example
    Access-Control-Request-Method: POST
    Access-Control-Request-Headers: X-PINGOTHER, Content-Type
    

    服务器所返回的 Access-Control-Allow-Methods 首部字段将所有允许的请求方法告知客户端。该首部字段与 Allow 类似,但只能用于涉及到 CORS 的场景中。

    想要了解更多的http header信息 请访问 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers

    二. 跨域常见问题排查(CORS场景)

    2.1. 未配置 Access-Control-Allow-Origin。

    Access to XMLHttpRequest at 'http://foo1.example.com/' from origin 'http://foo2.example.com/' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
    

    解决方法: 在域为foo1.example.com 的虚拟主机添加 Access-Control-Allow-Origin 值为http://foo2.example.com。

    server {
        ...
        server_name foo1.example.com;
        ...
        add_header 'Access-Control-Allow-Origin' 'http://foo2.example.com';
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    
        if ($request_method = "OPTIONS")  {
            return 204;
        }
        ...
    }
    

    2.2. 跨域访问

    Access to XMLHttpRequest at 'http://foo1.example.com/' from origin 'http://foo3.example.com/' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'http://foo2.example.com/' that is not equal to the supplied origin.
    

    解决方法:请注意观察上述报错, Access-Control-Allow-Origin 已经至少有一个值为http://foo2.example.com 的设定。所以现在配置一个允许多源访问的配置。

    server {
        ...
        server_name foo1.example.com;
        ...
        if ( $http_origin ~ .*.(example|aldwx).(net|com)) {
            set $other_domain $http_origin;
        }
    
        add_header Access-Control-Allow-Origin $other_domain;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    
        if ($request_method = "OPTIONS")  {
            return 204;
        }
        ...
    }
    

    2.3.  Access-Control-Allow-Headers 中首部缺失

    Access to XMLHttpRequest at 'http://foo1.example.com/' from origin 'http://foo2.example.com/' has been blocked by CORS policy: Request header field <u>cookies</u> is not allowed by Access-Control-Allow-Headers in preflight response.
    

    解决方法: 遇到这一类的问题时,需要仔细阅读报错,在报错里面基本已经写明了答案。例如上面的这个报错信息。域foo2.example.com 请求域foo1.example.com 时,因首部cookies 未包含在 Access-Control-Allow-Headers 中,所以foo1无法响应客户端请求。并且这一类问题可能同时会出现几个首部缺失的请求,但是报错是单个出现,所以呢,要仔细阅读错误。下面也是其中一个报错

    Access to XMLHttpRequest at 'http://foo1.example.com/' from origin 'http://foo2.example.com/' has been blocked by CORS policy: Request header field <u>access-control-allow-credentials</u> is not allowed by Access-Control-Allow-Headers in preflight response.
    
    server {
        ...
        server_name foo1.example.com;
        ...
         
        if ( $http_origin ~ .*.(example|aldwx).(net|com)) {
            set $other_domain $http_origin;
        }
    
        add_header Access-Control-Allow-Origin $other_domain;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'access-control-allow-credentials,cookies,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
    
        if ($request_method = "OPTIONS")  {
            return 204;
        }
        ...
    }
    

    2.4.  Mixed Content: https域名下请求http接口

    Mixed Content: The page at 'https:foo.example.com' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://bar.example.com'. This request has been blocked; the content must be served over HTTPS.
    

    解决方法: 同样,遇到这一类的问题时,需要仔细阅读报错。在报错里面也写明了一种解决方法。简言之,就是要求bar.example.com 必须配置https。这是一种解决方法。当然还有其他的方法,其中之一就是,foo.example.com 也换成http,那么也就没有被bolck这回事了。

    2.5.  net::ERR_FAILED 网络错误

    Access to XMLHttpRequest at 'https:foo.example.com/' from origin 'http://bar.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    
    POST https:foo.example.com/ net::ERR_FAILED
    

    解决方法: 遇到这类问题,通常是后端应用服务器端资源不能及时响应引起的,此时不应该重点去排查是否因前端跨域引起。可以从下面几个方面去排查

    1. 检查与后端应用服务器的网络响应速度(排除网络问题)
    2. 单独请求对应后端应用服务器资源,检查应用服务器对单一接口的响应速度

    排查网络的工具主要有:ping, traceroute/tracert(路由追踪),telnet(端口监测),tcpdump/wireshark(抓包分析),这些工具的使用方法可以直接在终端利用man手册进行查看,如下命令:

    $ man ping
    

    也可上网查询其使用方法,见如下链接
    ping: https://www.runoob.com/linux/linux-comm-ping.html
    traceroute: https://www.runoob.com/linux/linux-comm-traceroute.html
    telnet: https://www.runoob.com/linux/linux-comm-telnet.html
    tcpdump: https://www.runoob.com/linux/linux-comm-tcpdump.html
    ...

    另外,当被访问应用服务器端存在限流控制时,如果客户端频繁去请求,也可能出现某一时间段的网络中断,在排查过程中也应该将这种情况考虑进去


    参考文章:
    Nginx配置跨域请求 Access-Control-Allow-Origin *

    https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers

  • 相关阅读:
    原始mvc1
    ssh3,hibernate和maven
    hibernate1
    mybatis和spring一起用
    python怎么生成requirements.txt文件
    selenium.common.exceptions.ElementNotVisibleException: Message: element not interactable (Session info: chrome=74.0.3729.108) (Driver info: chromedriver=2.43.600210
    Android SDK 安装与配置
    pip超时问题解决
    爬取网页数据
    pip安装报错: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy
  • 原文地址:https://www.cnblogs.com/guoew/p/10986125.html
Copyright © 2020-2023  润新知