浏览器跨域的细节
关于什么是跨域,一句话可以说清楚,不同协议,不同子域,不同主域, 不同端口。都可以算成跨域。具体的可以去网上进行搜索。
那么今天来说一下具体前后端如何跨域的实现代码。
从前端说起的话
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里添加这个选项
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这个模块。