浏览器跨域的细节

Posted 小菜鸡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浏览器跨域的细节相关的知识,希望对你有一定的参考价值。

关于什么是跨域,一句话可以说清楚,不同协议,不同子域,不同主域, 不同端口。都可以算成跨域。具体的可以去网上进行搜索。

那么今天来说一下具体前后端如何跨域的实现代码。

从前端说起的话

        var headers = new Headers();
        headers.append(\'Content-Type\', \'application/json\');
        headers.append(\'x-node\', \'node\');
        fetch(\'http://127.0.0.1:3000/users/login\', {
            method: \'POST\',
            headers: headers,
            body: JSON.stringify({
                userName: \'鬼剑士\',
                userPwd: \'665533\',
            })
        });        

  比如这段代码跑在localhost:8080的端口上,那么运行以后浏览器会报错如下信息

  

XMLHttpRequest cannot load http://127.0.0.1:3000/users/login. 
Response to preflight request doesn\'t pass access control check: No \'Access-Control-Allow-Origin\' header is present on the requested resource.
Origin \'http://127.0.0.1:8080\' is therefore not allowed access.

   总而言之就是说你的服务器的响应没有返回 Access-Control-Allow-Origin 这样的响应头,怎么处理呢那么需要去服务器设置跨域的响应头

设置的代码大致如下:

以express框架举例

var cors = require(\'cors\');
var express = require(\'express\');

var app = express();

app.use(cors());

然后设置完成以后我们继续请求这个接口,那么这时候的响应头会是这样的

 有些同学可能会问,为什么我们只发送了一个POST请求,但是出来一个options请求?

这里请看另一篇博文 http://www.cnblogs.com/web-alibaba/p/7583323.html

接下来就可以愉快的运行了。

但是有些同学有问题了,你这样的话岂不是请求体里不能带上cookie了,每次都要手动加。多麻烦呀。

那么解决这个问题的办法是在我们的fetch函数里添加一个选项 credentials, 简单介绍一下credentials。

这个是为了跨域请求时候控制浏览器的cookie所设计的。参数有三个分别是

omit:永远不带cookie。

same-origin: 请求地址和网页的地址在同一个源下就发送cookie,反之不发送。

include:永远发送。

那么我们可以在fetch里添加这个选项

credentials: \'include\',然后来看一下结果
Fetch API cannot load http://127.0.0.1:3000/users/login. 
Response to preflight request doesn\'t pass access control check: The value of the \'Access-Control-Allow-Origin\' header in the response must not be the wildcard \'*\' when the request\'s credentials mode is \'include\'.
Origin \'http://127.0.0.1:8080\' is therefore not allowed access.

然后愉快的发现又报错了。解释一下错误,当浏览器设置了credentials属性的时候 相应的服务器也需要去设置credentials属性。

并且 Access-Control-Allow-Origin的域名不能为*,需要指定具体的域名

那么我们服务端的代码改动成如下

app.use(cors({
    origin: \'http://127.0.0.1:8080\',
    credentials: true,
}));

然后看一下cors内部的实现,会发现 credentials为true的时候会返回相应的响应头,浏览器得到以后就会乖乖的不报错了。

 function configureCredentials(options) {
    // 是否带cookies
    if (options.credentials === true) {
      return {
        key: \'Access-Control-Allow-Credentials\',
        value: \'true\'
      };
    }
    return null;
  }

 

然后发现终于成功了,成功的得到了我们想要的json数据

大概的流程就到这里了。接下来会解析node-cors这个模块。

 

以上是关于浏览器跨域的细节的主要内容,如果未能解决你的问题,请参考以下文章

AJAX入门

修改浏览器属性配置的作用---开发机上解决跨域的方式

跨域解决方法

跨域以及解决跨域的几种方式

h5标签canvas关于getImageData跨域的问题

CORS跨域的限制与解决