前端跨域及解决方案

域(origins)和跨域

域(origins)是由三部分组成的标识:协议完整的主机名端口
跨域:就是非同域,同时访问另一个域的子资源。

什么是同源策略?

同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSSCSRF等攻击。同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

不会触发同源策略的标签

TagsCross-originNote
<iframe>允许嵌入取决于X-Frame-Options
<link>允许嵌入可能需要正确的Content-Type
<form>允许写入经常用此标签进行跨域写操作
<img>允许嵌入禁止通过JavaScript跨域读取并将其加载到canvas标签中
<audio>
<video>
允许写入
<script>允许嵌入可能会禁止访问特定的API

不允许被跨域访问的资源

  • 本地存储
  • indexedDB
  • Cookie
  • Ajax(XMLHttpRequest)

跨域解决方案

  • JSONP
  • 反向代理
  • CORS
  • postMessage

JSONP

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
	}
}

反向代理

  • nginx反向代理
  • nodejs库实现反向代理

CORS

CORS简介

CORS(跨域资源共享),是一种基于HTTP头的机制,该机制允许我们使用Ajax发送跨域请求,只要HTTP相应头中包含了相应的CORS相应头。
CORS需要浏览器和服务器同时支持,CORS机制在老版本的浏览器中不支持,现代浏览器都支持CORS。在使用CORS方Ajax请求时需要浏览器端代码和过去一致,服务器端需要配置CORS的响应头。

  • 简单请求
  • 复杂强求
  • 带凭证的请求(Cookie)

简单请求

不会发起CORS预检请求的请求,称为简单请求。满足下列要求的请求都是简单请求:

使用下面的请求方式

  • GET
  • POST
  • HEAD

请求头中只包含

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type

Content-Type 只能是下面三种

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

复杂请求

不满足简单请求的条件即为复杂请求,会发送两次请求,一次是预检请求OPTIONS(可缓存),后面才是真正的请求。
如:

  • 当发送请求方式为PUT/DELETE 复杂请求 =》请求方法不是简单请求中的3种
  • Content-Type值为application/json时 复杂请求 =》 Content-Type 值不满足
  • header 加token参数时 复杂请求 =》 有多余的请求头参数

axios默认发送的是Content-Type值为application/json,默认是复杂请求

使用axios发送简单请求

  1. 修改请求头为application/x-www-form-urlencoded
  2. 参数正确化
    URLSearchParams
    qs
const qs = new URLSearchParams()
qs.append("user","xxx")
qs.append("content","xxx")
qs.append("time","xxx")

axiso.post("url",qs.toString(),{
	headers: {
		token: ""
	}
})

复杂请求后端CORS配置(nodejs)

  • 手动设置请求头,实现对CORS的支持
// 设置允许的源 如果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)
  • 利用中间件Cors 帮我们设置请求头
    详细配置看官网 cors
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
}))
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥肥呀呀呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值