域(origins)是由三部分组成的标识:
协议
、完整的主机名
和端口
。
跨域:就是非同域,同时访问另一个域的子资源。
同源策略
是一种约定
,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS
、CSRF
等攻击。同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
Tags | Cross-origin | Note |
---|---|---|
|
允许嵌入 | 取决于X-Frame-Options |
|
允许嵌入 | 可能需要正确的Content-Type |
|
允许写入 | 经常用此标签进行跨域写操作 |
|
允许嵌入 | 禁止通过JavaScript跨域读取并将其加载到canvas 标签中 |
|
允许写入 | – |
|
允许嵌入 | 可能会禁止访问特定的API |
jsonp原理
利用script 标签请求不会触发同源策略,动态创建script标签,和接受数据的回调函数,让后端接受到请求后,执行函数方法,塞进数据。
后端node.js jsonp支持接口
router.get("/jsonp",(req,res) =>{
// 默认是callback的值为服务器回调函数名,也就是浏览器已经创建定义的函数,服务端会执行,并将数据放入进去
const cb = req.query.callback ?? "cb"
res.send(`${cb}(${JSON.stringify(db.messages)})`)
})
前端 jquery请求
$.ajax({
url: "http:....../jsonp",
dataType: "jsonp",
jsonp:"callback",
jsonpCallback:"cb",
success(data) {
console.log(data)
}
})
axios 不支持jsonp
jsonp npm库
jsonp
手写实现jsonp
function jsonp(url,callback) {
const cb ='__jp0'
const script = document.createElement("script")
script.src = `${url}?callback=${cb}`
docoment.body.appendChild(script)
window[cb] = function(data) {
clear();
callback(data)
}
function clear() {
document.body.reamoveChild(script)
window[cb]=null
}
}
CORS简介
CORS(跨域资源共享),是一种基于HTTP头的机制,该机制允许我们使用Ajax发送跨域请求,只要HTTP相应头中包含了相应的CORS相应头。
CORS需要浏览器和服务器同时支持,CORS机制在老版本的浏览器中不支持,现代浏览器都支持CORS。在使用CORS方Ajax请求时需要浏览器端代码和过去一致,服务器端需要配置CORS的响应头。
不会发起CORS预检请求的请求,称为简单请求。满足下列要求的请求都是简单请求:
使用下面的请求方式
请求头中只包含
Content-Type 只能是下面三种
不满足简单请求的条件即为复杂请求,会发送两次请求,一次是预检请求OPTIONS
(可缓存),后面才是真正的请求。
如:
axios默认发送的是Content-Type值为application/json,默认是复杂请求
使用axios发送简单请求
const qs = new URLSearchParams()
qs.append("user","xxx")
qs.append("content","xxx")
qs.append("time","xxx")
axiso.post("url",qs.toString(),{
headers: {
token: ""
}
})
// 设置允许的源 如果Credentials 没有开启就设置为*
res.setHeader("Access-Control-Allow-Origin","*")
// 设置允许的 复杂请求的方法
res.setHeader("Access-Control-Allow-Methods",["PUT","POST","DELETE"])
// 设置允许的 复杂请求 请求头允许的参数
res.setHeader("Access-Control-Allow-Headers",["Content-Type","token"])
// 设置允许的 复杂请求 预检请求的缓存 0为没有缓存,每次都要出现
res.setHeader("Access-Control-Max-Age",86400)
// 设置复制请求 携带cookie
res.setHeader("Access-Control-Allow-Credentials",true)
var cors = require('cors')
router.use(cors({
"origin": "*",
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
"preflightContinue": false,
"optionsSuccessStatus": 204,
"allowedHeaders": ["Content-Type","token"],
"credentials": true,
"maxAge": 86500
}))