cors跨域
cors(Cross-Origin Resource Sharing),跨域资源共享
基于安全的考虑浏览器实施了同源策略,但是由于跨域访问资源的不可避免,w3c又指定了cors标准来实现跨域资源的访问
cors通信过程中浏览器会自动完成,若请求是跨域的,浏览器会自动在请求头中添加一些字段,所以要实现cors跨域只需要在服务端进行相应字段的设置
简单请求
1.get,post,head
2.http请求头中,除了自动设置的字段外,允许人为设置的字段只能是以下几个字段
1)Accept
2)Accept-Language
3)Content-Language
4)Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
符合以上俩个条件的就是简单请求(详细内容可以在MDN中查看)
复杂请求
复杂请求就是非简单请求,可能会对服务器数据产生副作用的请求。
首先浏览器会自动使用options方法发起一个预检请求,询问服务器是否允许该跨域请求,若允许则发起正式的请求
cors相关字段
1.Access-Control-Allow-Origin(必须)
该字段的值表示允许访问服务器资源的域
若允许任意域的请求则可以设置为‘*’
2.Access-Control-Allow-Methods
请求允许的方法
3.Access-Control-Allow-Headers
请求允许携带的首部字段
4.Access-Control-Allow-Credentials
表示是否允许发送Cookie,值为true表示请求时可以携带cookie
5.Access-Control-Max-Age
预检请求的结果能缓存的时长,单位为秒
实现cors跨域
1.用node.js开启俩个服务器,web.js和server.js
2.web.js监听3001端口,该服务器中有一个index.html
3.server.js监听3000端口,该服务器中有一个a.html
4.在index.html中点击按钮触发ajax请求去访问a.html,该请求跨域
web.js
var http = require('http')
var fs = require('fs')
var server = http.createServer()
server.on('request', function (req, res) {
if (req.url === '/index.html') {
fs.readFile('./index.html', 'utf-8', function (err, data) {
res.end(data)
})
}
})
server.listen(3001, function () {
console.log('server is open')
})
在web.js同一目录下创建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="context"></div>
<p>当前域为http://localhost:3001</p>
<button onclick="login()">
访问http://localhost:3000中的资源a.html
</button>
<script>
function login () {
var dom = document.getElementById('context')
var xml = new XMLHttpRequest()
xml.open('get', 'http://localhost:3000/a.html')
xml.onreadystatechange = function () {
if (xml.readyState === 4 && xml.status === 200) {
dom.innerHTML = xml.responseText
}
}
xml.send()
}
</script>
</body>
</html>
server.js
var http = require('http')
var fs = require('fs')
var server = http.createServer()
server.on('request', function (req, res) {
// 允许访问本服务器的的域
var allowOrigins = ['http://localhost:3001', 'http://localhost:3002']
if (allowOrigins.includes(req.headers.origin)) {
// 设置允许的域
res.setHeader('Access-Control-Allow-Origin', req.headers.origin)
if (req.url === '/a.html') {
fs.readFile('./a.html', 'utf-8', function (err, data) {
res.end(data)
})
}
}
})
server.listen(3000, function () {
console.log('server is open')
})
在server.js同一目录下创建a.html
<div>
server中的资源
</div>
服务器都开启后,在浏览器地址栏输入http://localhost:3001/index.html
点击按钮进行ajax请求
可以看到跨域请求成功
在index.html中加一行代码,给请求头添加一个字段,让请求变成复杂请求
xml.setRequestHeader('Content-Type', 'application/json')
同时还要在服务端设置允许添加该首部字段
res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
重启服务器,刷新页面后再次点击按钮发起ajax请求
可以看到因为是复杂请求,所以一开始先进行了options预检请求,然后才是正式的请求
(在谷歌浏览器中可能是因为某些默认的浏览器设置,导致看不到options请求,截图中的结果是在火狐浏览器中查看的)