非同源限制
- cookie、LocalStorage和indexDB无法获取
- 无法操作其他源下的DOM
- Ajax请求不能发送
JSONP
原理
script标签中的src可进行跨域,且脚本具有加载完就立即执行的特点
前端将要跨域的url和要执行的函数名拼接作为src的值
服务器取出函数名,将要传的值放在函数参数中,拼接为字符串返回
缺点:
- 需要前后端配合
- 只能进行get跨域
具体操作
前端
<script>
function func(data){
//打印服务器返回的数据
console.log(data)
}
</script>
<script src="url?callack=func"></script>
服务器
router.get('/xxx',(req,res) => {
var func = req.query.callback
//data为要返回的数据
res.send(func+'('+ data + ')')
})
实现jsopn方法
function jsonp(url,callback){
//生成一个随机函数名
const cbname = 'jsonp'+ new Date().getTime()
//将函数名挂载到window上
window[cbname] = function(data){
//调用传入的callback
callback(data)
//删除创建的script标签
doucuemnt.body.removeChild(script)
}
//拼接url和回调函数
const path = url + '?' + 'callback=' + cbname
//创建script
const script = document.createElement('script')
script.scr = path
script.type = 'text/javascipt'
//将script添加到body中
document.body.appendChild(script)
}
CORS
简单请求
- 请求方式:GET、POST、HEAD之一
- Content-Type的值为:text/plain、multipart/form-data、application/x-www-form-urlencoded之一
- 服务器设置响应头:Access-Control-Allow-Oring值为*或者要跨域的url
GET请求
Content-Type: text/plain(不需要手动设置)
服务器
router.get('/',(req,res) =>{
res.setHeader('Access-Control-Allow-Orign','*')
//发送来的数据
const data = req.query
})
POST请求
Content-Type:application/x-www-form-urlencoded
前端
axios.create({
baseURL: 'xxx',
timeout: 5000,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
})
服务器
router.post('/register',(req,res) => {
res.setHeader('Access-Control-Allow-Origin','*')
//从请求体中拿出发送的数据
const {
username,password} = JSON.parse(Object.keys(req.body)[0])
})
req.body的值如下
'{"username":"admin","password":"123456zxcvb"}': ''
跨域过程
在发送跨域请求前,浏览器会为http头部加上一个额外的Origin字段,来说明本次请求来自哪个源(协议、域名、端口号)
如果Origin指定的源不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现回应头信息中没有包含Access-Control-Allow-Origin字段,会抛出一个错误,该错误被XMLHttpRequest的onError回调函数捕获
如果Origin指定的域名在许可范围内,服务器返回的响应会多出几个头信息字段
postMessage
- postMessage(data,origin):发送数据
data:使用JSON.stringify()序列化的数据
origin:协议+域名+端口号,也可设置为*,表示可以传递给任意窗口,如果要指定和当前窗口同源,可设置为’/’ - 监听onmessage事件,传递来的数据在event.data中
document.domain
可在主域名相同,子域名不同时进行跨域,比如a.test.com和b.test.com可使用该方式
给页面添加document.domain='test.com’表示主域名相同就可进行跨域