首页IT科技使用jsonp跨域,服务端如何改(简单易懂的JSONP和CORS跨域方案详解)

使用jsonp跨域,服务端如何改(简单易懂的JSONP和CORS跨域方案详解)

时间2025-05-27 15:11:33分类IT科技浏览4671
导读:一、了解跨域 ?何为跨域 跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果...

一            、了解跨域

?何为跨域

跨域并不是请求发不出去            ,请求能发出去                   ,服务端能收到请求并正常返回结果      ,只是结果被浏览器拦截

那为什么拦截呢         ,我们应该先了解一下什么是同源策略

MDN上的解释:同源策略是一个重要的安全策略                   ,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互            。它能帮助阻隔恶意文档         ,减少可能被攻击的媒介

具体的限制(三限制):

同源策略限制了来自不同源的 JavaScript 脚本对当前DOM对象读和写的操作 同源策略限制了来自不同源的站点读取当前的 Cookie                   、LocalStorage 等数据 同源策略限制了通过 XMLHttpRequest等方式将站点的数据发送给不同源的站点

能使的标签(能跨域请求资源的标签):

<script src="..."></script> <link rel="stylesheet" href="..."> 通过<img>展示图片 通过<video>和<audio>播放的多媒体资源 通过<iframe>载入的任何资源

那你限制了我这么多东西      ,我要正常使用肯定要跨域喽

?何为同源

如果两个 URL 的协议(Protocol)                   ,域名(domain)            ,端口(port)都相同的话   ,则这两个 URL 是同源

协议:定义了数据如何在计算机内和之间进行交换的规则的系统                   。例如:http                   ,https 域名:可以通过DNS解析为IP地址 (这里即使两个不同的域名指向同一个IP地址               ,也是属于不同源的) 端口:http默认使用80端口,https默认使用443端口

举个例子: 我们寻找跟掘金首页:https://jbzj.cn/同源的URL

URL 结果 原因 http://jbzj.cn/ 不同源 协议不同 https://jbzj.my.cn/ 不同源 域名不同 https://jbzj.cn:3030/ 不同源 端口不一样(https默认443端口) https://jbzj.cn/user/2375390426313406 同源 只有路径不一样 https://jbzj.cn/post/7151609034699718692 同源 只有路径不一样

小结:跨域的出现是因为浏览器的同源策略对不同协议                ,域名                   ,端口的URL在DOM对象的读写   ,Cookie等数据的获取            ,Ajax请求等方面有限制

二      、跨域解决方案

JSONP(JSON with Padding)

最容易记住也最容易理解的应该就是JSONP了 我们前面提到了<script src="..."></script>是可以跨域请求资源的                   ,那么JSONP就是利用了这一点了 ?简单实现 先上一个简单的例子来理解思路 在客户端
<script> function jsonp(){ return new Promise((resolve, reject) => { //在全局定义一个doSomething的函数 window[doSomething] = function(data) { resolve(data); } }) } jsonp().then(res=>{ //调用doSomething之后会在这里打印 console.log(res) }) </script> //使用script标签向后台/test路径发送参数callback为doSomething <script src="http://localhost:3000/test?callback=doSomething"></script>
在服务端
app.get(/test,(req, res) => { //通过res.send()方法-将处理好的内容      ,发送给客户端 let { callback } = req.query; //返回一个函数的执行式doSomething(‘参数) res.send(`${callback}(这里是某车在使用简单的JSONP)`) })
服务器返回doSomething(这里是某车在使用简单的JSONP)         ,因为我们已经声明过                   ,所以客户端会直接调用doSomething这个函数         ,然后打印出了:这里是某车在使用简单的JSONP ?流程图 全局声明一个回调函数 在<script>标签中      ,输入URL,向服务器传递该函数名和参数(可以通过问号传参:?callback=doSomething) 服务器接收到请求后                   ,需要进行处理:把传递进来的函数名和要返回的数据拼接为函数调用式,例如:传递进去的函数名是doSomething            ,要传回的数据是:这里是某车在使用简单的JSONP   ,那么后台返回的即为doSomething(这里是某车在使用简单的JSONP) 客户端再调用执行之前声明的回调函数(doSomething)                   ,对返回的数据进行操作 ?封装

但是在真正的开发中               ,我们不可能写一堆<script>标签在那里,所以我们需要对jsonp进行封装

function jsonp({url, params, callback}){ return new Promise((resolve, reject) => { //动态创建script标签 let script = document.createElement(script); //处理传入的参数 params = {...params, callback}; //转换参数表达式 let arr = [] for(let key in params) { arr.push(`${key}=${params[key]}`) } //在路径中                ,参数用 & 隔开 script.src = `${url}?${arr.join(&)}` //添加 script 标签 document.body.appendChild(script); //声明回调函数 window[callback] = function(data) { //执行异步函数 resolve(data); //请求完后移除该script标签 document.body.removeChild(script) } }) }
使用
jsonp({ url:http://localhost:3000/test, params:{ args:这个是参数 }, callback: doSomething }).then(res=>{ console.log(res) })
?优缺点 优点: 简单兼容性好                   ,可用于解决主流浏览器的跨域数据访问的问题 缺点: 仅支持get方法具有局限性,不安全可能会遭受XSS攻击

CORS(Cross-Origin Resource Sharing)

实现CORS的关键在于后端:服务端设置Access-Control-Allow-Origin就可以开启 CORS      。 该属性表示哪些域名可以访问资源   ,如果设置通配符则表示所有网站都可以访问资源 我们可以将请求分类为简单请求和非简单请求 简单请求

判定:

请求方法是以下方三种方法之一

HEAD GET POST

请求头仅包含安全的字段            ,如以下几种字段

Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值 application/x-www-form-urlencoded         、multipart/form-data                   、text/plain 请求过程 客户端代码
btn.addEventListener(click,()=>{ const xhr = new XMLHttpRequest(); xhr.open(get, http://localhost:3000/test); //向端口号为3000的发起请求 xhr.send(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4) { if(xhr.status >= 200 && xhr.status < 300) { console.log(xhr.response) //如果请求成功                   ,则打印后台返回的数据 } } } })
服务端设置
app.get(/test,(req,res)=>{ //通过res.send()方法-将处理好的内容      ,发送给客户 res.send(`你好呀某车         ,你已经成功发起请求了`) })
当你发送请求的时候(客户端为5500端口                   ,服务端为3000端口)         ,什么也不设置就会报跨域错误 此时我们看一下当浏览器会给它的请求头加上Origin      ,值为它本身的协议+域名+端口                   ,这个时候服务器就能知道是谁在对他发送请求 那么服务器如果想要允许它访问的话            ,则在响应头加上Access-Control-Allow-Origin字段   ,值可以为*表示允许所有源的访问                   ,也可以为具体的源               ,我们这里给他设置为我们上述的Origin值,同时也加上Access-Control-Allow-Methods字段                ,设置可访问的请求方法
app.all("*",function(req,res,next){ //设置允许跨域的域名                   ,*代表允许任意域名跨域 res.header("Access-Control-Allow-Origin","http://127.0.0.1:5500"); res.header("Access-Control-Allow-Methods",PUT,POST,GET,DELETE,OPTIONS) next(); })
此时你再点击发送请求就会发现:请求已经能够正常返回了 响应头显示的Access-Control-Allow-Origin即为我们可访问的源 复杂请求 我们上述已经讲过什么是简单请求了   ,那么不符合上述条件的即为复杂请求 复杂请求发起请求的时候则是会在正式通信之前进行一次预检请求(preflight request) 浏览器先询问服务器,当前源当前请求是否可以访问服务器资源            ,只有得到正确的答复,才会进行正式的请求

请求过程

我们依旧使用上面的代码                   ,然后就请求方式改为put      ,此时发送的即为复杂请求         ,可以看到发送了两次请求,由于我们put方法在上述已经被设置为可访问的方法                   ,所以现在预检可以通过         ,我们也能正常请求到资源

如果我们将put方法从Access-Cntrol-Allow-Methods移除      ,此时再进行请求                   ,则发提示            ,在预检请求中发送PUT方法是不被允许的

此时test正式请求则报CORS错误

写到这里   ,我就想到了曾经看过的面试题:跨域请求如何携带cookie

扩展 但是我想测试的时候受到了SameSite的限制                   ,不允许第三方cookie               ,本来想要关掉浏览器设置的,搜索了一下发现这个方法自从版本91之后就用不了                ,那么浅浅说一下方法就得了 只需要前端在发送Ajax请求的时候将withCredentials设置为true
const xhr = new XMLHttpRequest(); xhr.withCredentials = true;
后端设置"Access-Control-Allow-Credentials为true                   ,同时注意Access-Control-Allow-Origin值不为*
res.header("Access-Control-Allow-Credentials", "true");
缺点

IE10以下不支持

小结:后端是关键   ,主要是设置Access-Control-Allow-Origin

关于postMessage和webSocket的跨域方案我写在嗦嗦postMessage和webSocket这里了

以上就是简单易懂的JSONP和CORS跨域方案详解的详细内容            ,更多关于JSONP CORS跨域方案的资料请关注本站其它相关文章!

声明:本站所有文章                   ,如无特殊说明或标注      ,均为本站原创发布         。任何个人或组织         ,在未征得本站同意时                   ,禁止复制         、盗用      、采集                   、发布本站内容到任何网站            、书籍等各类媒体平台                   。如若本站内容侵犯了原著者的合法权益         ,可联系我们进行处理         。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
bat 调用powershell(如何在bat中进入虚拟环境) 伪原创文章有用吗(免费伪原创文章生成器在线工具软件,文章一键伪原创神器)