什么是跨域?

跨域问题是因为浏览器的同源策略造成的,是浏览器对javascript 实施的安全策略。使得浏览器不能执行网站请求。
当我们访问api接口的时候,在浏览器上会出现

Access to XMLHttpRequest at 'http://localhost:7002/test' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

同源策略:

URL 是否允许通信
同一域名 允许
同一域名,不同端口 不允许
同一域名,不同协议 不允许
域名和域名对应的IP 不允许
主域名和子域名 不允许
不同域名 不允许
怎样解决跨域问题
1.JSONP

script 标签的src 属性在同源策略问题上就不会遇到跨域的问题,因此可以使用这种请求方式来实现http请求.
前端代码:

function createJsonp(url,callback) {
        let jsonp = document.createElement('script');
        let data;
        jsonp.type = "text/javascript";
        jsonp.src = `${url}?callback=jsonCallback`;
        document.getElementsByTagName('head')[0].appendChild(jsonp);
        setTimeout(() => {
            document.getElementsByTagName('head')[0].removeChild(jsonp)
        }, 500);

        window.jsonCallback = (result) => {
            callback(result)
        }
    }
    createJsonp('http://localhost:7002/test',function(data){
        console.log(data)
    }) ;

前端可以通过回调函数获取需要的数据
后端代码:

  async test(){
    const {ctx} =this;
    const cb = ctx.queries.callback;
    ctx.set('Content-Type','application/javascript;charset=utf-8')
    let data = {
      name:'name1',
      age:20
    }
    ctx.body = cb+`(${JSON.stringify(data)})`
  }
2.使用Nginx 反向代理
# 第一种
server {
    listen      8080;
    server_name 需要代理的服务地址(localhost)
    location / {
        proxy_pass   转发到服务地址(http://localhost:7002);
    }
}
#第二种
server
{
    listen 80;
    server_name 需要代理的服务地址(localhost);
    location /ok {
        proxy_pass http://localhost:7002;
        #   允许跨域的方法,*代表所有(GET,POST,DELETE,PUT...)
        add_header Access-Control-Allow-Methods *;
        #   指定本次预检请求的有效期,单位为秒,,在此期间不用发出另一条预检请求。
        add_header Access-Control-Max-Age 3600;
        #   带cookie请求需要加上这个字段,并设置为true
        add_header Access-Control-Allow-Credentials true;
        #   表示允许这个域跨域调用(客户端发送请求的域名和端口) 
        #   $http_origin动态获取请求客户端请求的域   不用*的原因是带cookie的请求不支持*号
        add_header Access-Control-Allow-Origin $http_origin;

        #   表示请求头的字段 动态获取
        add_header Access-Control-Allow-Headers 
        $http_access_control_request_headers;

        #   OPTIONS预检命令,预检命令通过时才发送请求
        #   检查请求的类型是不是预检命令
        if ($request_method = OPTIONS){
            return 200;
        }
    }
}
3.CORS

Cors 是使用自定义的HTTP头部让浏览器与服务器进行数据交换,从而决定请求响应是否应该成功。
需要在后台服务上进行配置
例如在egg.js中使用:
需要下载安装egg-cors 插件(略过)

// 配置的参数
{String|Function(ctx)} origin `Access-Control-Allow-Origin`, default is request Origin header
{String|Array} allowMethods `Access-Control-Allow-Methods`, default is 'GET,HEAD,PUT,POST,DELETE,PATCH'
{String|Array} exposeHeaders `Access-Control-Expose-Headers`
{String|Array} allowHeaders `Access-Control-Allow-Headers`
{String|Number} maxAge `Access-Control-Max-Age` in seconds
{Boolean} credentials `Access-Control-Allow-Credentials`
{Boolean} keepHeadersOnError Add set headers to `err.header` if an error is thrown

夏末流星
152 声望2 粉丝

生命不仅要超越别人,更要超越自己。