浏览器跨域的细节

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

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

从前端说起的话

        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这个模块。

 

posted @ 2017-09-23 22:56  小菜鸡12315  阅读(505)  评论(0编辑  收藏  举报