前言
定义
浏览器为了保证用户信息的安全,防止恶意网站窃取数据,禁止不同域之间的js交互。对于浏览器而言,只要协议、域名、端口其中有一个不同就会触发同源策略,造成跨域,从而限制交互
为什么要限制跨域访问
如果一个网页可以随意的访问另一个网站的资源,就有可能在用户完全不知情的情况下出现安全问题
浏览器出于安全问题,对同源请求放行,对异源请求限制,这些限制规则统称为同源策略,因为限制造成的开发问题,称之为跨域(异源)问题
对标签发出的跨域请求轻微限制,对 AJAX 发出的跨域请求严厉限制
方法
常用方法
跨域资源共享(CORS)
CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。
是一套机制,用于浏览器校验请求。只要服务器明确表示允许,则校验通过;服务器明确拒绝或没有表示,则校验不通过。CORS将请求分为两类,简单请求和预检请求:
简单请求
-
请求方法为GET、HEAD、POST
预检请求
浏览器发送预请求
-
从哪个源发送的请求:Origin:http://my.com
服务器进行响应
jsonp
前端写一个函数,服务端调用函数传入参数,通过参数获取,根本不是AJAX
// 获取返回结果
function callback(resp){
console.log(resp);
}
// 向服务端请求js文件
function request(url){
// 生成一个 script 标签
const script = document.createElement('script')
// 标签引用 js 路径为填入路径
script.src = url
// 标签解析完成之后删除
script.onload = function(){
script.remove()
}
// 插入 body 中
document.body.appendChild(script)
}
Nginx代理跨域
差别
方法
// 引入库
const express = require('express')
// 创建服务器
const app = express()
// 接受对路径 /hero 的 GET 请求
app.get('/hero',async (req,res)=>{
// 使用 cors 解决对代理服务器的跨域
res.header('assess-control-allow-origin','*')
// 响应一段测试文本
res.send('你好,我是代理服务器')
// 在这里请求目标服务器,然后返回给前端
})
// 监听9527端口
app.listen(9527,()=>{
console.log('服务器已启动');
})
扩展学习
Node中间件代理跨域
在vue.config.js文件中配置
module.export = {
...
devServer: {
proxy: {
[ process.env.VUE_APP_BASE_API ]: {
target: 'http://xxxx', // 代理跨域目标接口
ws: true,
changeOrigin: true,
pathRewrite: {
[ '^' + process.env.VUE_APP_BASE_API ] : ''
}
}
}
}
Node/Express中配置:
const express = require('express')
const proxy = require('http-proxy-middleware')
const app = express()
app.use('/', proxy({
// 代理跨域目标接口
target: 'http: // xxxx:8080',
changeOrigin: true,
// 修改响应头信息,实现跨域并允许带cookie
onProxyRes: function(proxyRes, req, res) {
res.header('Access-Control-Allow-Origin', 'http://xxxx')
res.header('Access-Control-Allow-Credentials', 'true')
},
// 修改响应信息中的cookie域名
cookieDomainRewrite: 'www.domain1.com' // 可以为false,表示不修改
}));
app.listen(3000);
Websocket
WebSocket是HTML5标准中的一种基于TCP但是区别于HTTP的通信协议,因为是长连接,该协议不实行同源政策。以ws://(非加密)和wss://(加密)作为协议前缀。
因为WebSocket请求头信息中有Origin字段,表示请求源来自哪个域,服务器可以根据这个字段判断是否允许本次通信。
// 创建websocket
var socket = new WebSocket('ws://www.baidu.com');
// 发送消息
socket.send('hello WebSocket');
// 接收消息
socket.onmessage = function(event){
var data = event.data;
}
postMessage
是HTML5引入的一个全新的API:跨文档通信 API(Cross–document messaging)。 这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。
窗口之间传递消息
// 父窗口发起
window.opener.postMessage("我是来自a页面的","http://b.com")
// 子窗口接收
window.onmessage = function(e){
e = e || event;
console.log(e.data);//我是来自a页面的
}
// 子窗口发送
window.opener.postMessage('我是来自b页面的', 'http://a.com');
读取其他窗口LocalStorage
// 父窗口调用方法
var obj = { name: 'Jack' };
// 存入对象
window.parent.postMessage(JSON.stringify({key: 'storage', method: 'set', data: obj}), 'http://b.com');
// 读取对象
window.parent.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");
window.onmessage = function(e) {
// 判断消息是否来自a窗口
if (e.origin != 'http://a.com') return;
// "Jack"
console.log(JSON.parse(e.data).name);
}
b窗口接收消息,获取自己的localStorage之后再传递给a窗口
window.onmessage = function(e) {
// 消息来自自己,不予理会
if (e.origin !== 'http://b.com') return;
var payload = JSON.parse(e.data);
// 判断方法进行操作
switch (payload.method) {
case 'set':
localStorage.setItem(payload.key, JSON.stringify(payload.data));
break;
case 'get':
var parent = window.parent;
var data = localStorage.getItem(payload.key);
// 如果是获取,获取之后传递给a窗口
parent.postMessage(data, 'http://a.com');
break;
case 'remove':
localStorage.removeItem(payload.key);
break;
}
}
单向跨域
原文地址:https://blog.csdn.net/wind_notcare/article/details/129548232
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_31578.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!