跨域请求的解决方案(跨域请求有那些方案)

跨域请求的解决方案(跨域请求有那些方案)h4 同源 h4 同源 ajax 请求的 url 和网页所在的 url 具有相同的协议 域名 ip 和端口 同源策略 为了数据安全 浏览器禁止通过 ajax 请求读取非同源的数据 注意 同源策略的两个关键点 1 浏览器 2 ajax 请求 同源策略下 浏览器会拦截跨域数据并报错 拦截的响应数据 跨域 跨源

大家好,我是讯享网,很高兴认识大家。



 <h4>同源&#xff1a;</h4> 

讯享网

同源:ajax请求的url和网页所在的url具有相同的协议,域名,ip和端口

同源策略:为了数据安全,浏览器禁止通过ajax请求读取非同源的数据(注意:同源策略的两个关键点:1,浏览器 2,ajax请求)

同源策略下,浏览器会拦截跨域数据并报错,拦截的响应数据

跨域/跨源:ajax请求的url和网页所在的url具有不同的协议,域名,ip和端口

1,解决跨域请求报错的三种解决办法

1.1 COR头跨域

原理:在ajax请求的响应头中,添加cors字段,相当于令牌/通行证,可以避免浏览器拦截这个跨域数据(浏览器在接受ajax跨域数据时,会优先判断响应头中是否存在cors字段,如果有,则不拦截数据,如果没有,则报错)

步骤:在后端服务器接口响应之前,添加响应头

讯享网 // 在响应头中添加cors字段, 允许这个接口跨域访问 res.setHeader(“Access-Control-Allow-Origin”, “*”) ​ //或 ​ // 使用第三方cors模块允许跨域 (可一次设置所有接口跨域) var cors = require(“cors”) app.use(cors())

前端代码:

&lt;h1 id=“h1”&gt;这是主页&lt;/h1&gt;    &lt;script&gt;        // 访问目标服务器的登录接口        \(.get(&#34;http://localhost:5000/login?name&#61;张三&#34;, function(data){            h1.innerText &#61; data       })    &lt;/script&gt;</pre> <ul><li> <p>优点&#xff1a;简单方便&#xff0c;容易操作&#xff0c;前端请求无需修改ajax代码</p> </li><li> <p>缺点&#xff1a;数据安全性降低&#xff0c;完全受后端限制&#xff0c;前端无法控制</p> </li></ul> <p>1.2 jsonp跨域</p> <p><strong>原理&#xff1a;同源策略只对ajax请求有限制&#xff0c;非ajax请求无限制&#xff0c;非ajax请求(如&#xff1a;form表单请求、标签属性请求&#xff0c;a标签的href&#xff0c;img标签的src&#xff0c;script标签的src)不会被同源策略拦截&#xff0c;所以使用script标签的src属性发起的跨域请求不会被同源策略拦截。</strong></p> <p><strong>步骤&#xff1a;前端(3种)&#xff1a;</strong></p> <p><strong>1&#xff0c;原生的jsonp请求&#xff1a;</strong></p> <p>前端&#xff1a;</p> <pre> &lt;script&gt;        function myMethod(res){            console.log(res)            alert(res.name)       }    &lt;/script&gt;    &lt;script src&#61;&#34;http://192.168.124.43:3000/userInfo?callback&#61;myMethod&#34;&gt;&lt;/script&gt;</pre> <ul><li> <p>callback这个字段不能自定义&#xff0c;是jsonp内部规定好的字段&#xff0c;不用callback调用不了</p> </li></ul> <p>后端&#xff1a;</p> <pre>app.get(&#39;/userInfo&#39;, function(req, res) {    console.log(req.query)    req.query.callback({ name: &#34;李四&#34; }) })</pre> <p>2,常规的开发习惯写法</p> <p>前端&#xff1a;</p> <pre>  &lt;script&gt;        function myMethod2(res){            alert(res.name)       }        \)(“&lt;script&gt;”).attr(“src”, “http://192.168.124.43:3000/userInfo?callback=myMethod2").appendTo("body")    &lt;/script&gt;

后端同1一样

3,jquery封装jsonp请求,使用\(.getJSON()实现</p> <p>前端&#xff1a;</p> <pre> &lt;script&gt;        // 由于jquery封装后,回调函数是匿名函数, 所以参数写成 callback&#61;? ?代表后边匿名函数        \).getJSON(”http://192.168.124.43:3000/userInfo?callback=?", function(res) {            alert(res.name)       })    &lt;/script&gt;

后端:

讯享网app.get(‘/userInfo’, function(req, res) {    console.log(req.query)     res.jsonp({ name: ‘李四’ }) })
  • jsonp()函数内部会自动调用get请求参数种的callback字段传入的回调函数,jsonp()参数作为callback回调函数的参数返回响应
  • jsonp函数的作用有两个:1,调用参数种的callback回调函数 2,返回响应数据

优点:不降低数据安全性,不完全受后端控制,相比于代理服务器跨域更简单

缺点:比cors头跨域复杂,受客户端和服务器共同控制,原理较复杂

1.3 代理服务器 跨域

原理:同源策略只对浏览器发起的ajax请求有限制,非浏览器请求无限制,所以可以使用网页所在的同源服务器发起ajax跨域请求,获取跨域数据后返回给同源客户端

步骤:创建同源服务器,在服务器种添加代理

前端:

 &lt;h1 id=“h1”&gt;这是主页&lt;/h1&gt;    &lt;script&gt;        // 访问目标服务器的登录接口        \(.get(&#34;/myApi/login?name&#61;张三&#34;, function(data) {                h1.innerText &#43;&#61; data           })            // 访问目标服务器的注册接口        \).post(“/myApi/register?name=张三”, function(data) {            h1.innerText += data       })    &lt;/script&gt;

后端:

讯享网var proxy = require(“http-proxy-middleware”).createProxyMiddleware app.use(“/myApi”, proxy({    // 这个对象是代理的配置对象    target: “http://localhost:5000",   //目标服务器地址    changeOrigin: true,  // 修改请求路径    pathRewrite: {       // 路径修改方案        ”^/myApi“: ”“   } })) ​ // http://localhost:3000/myApi/login?name=张三 // 以上请求url代理后的url如下 // http://localhost:5000/login?name=张三 ​ // http://localhost:3000/myApi/register?name=张三 // 以上请求url代理后的url如下 // http://localhost:5000/register?name=张三
  • 使用代理服务器跨域必须在前端服务器接口种下载并导入代理模块,并直接创建代理函数
  • 使用代理模块,调用代理函数,实现请求代理,这相当于创建了一个请求接口,同同源网页index.html访问,而参数”/myApi“就是同源请求的接口地址


    讯享网

2,四种ajax请求方式

2.1 原生的ajax请求方式

get请求方式

var xhr = new XMLHttpRequest();        xhr.open(”get“, ”http://open.douyucdn.cn/api/RoomApi/live?page=1")        xhr.send()        xhr.onreadystatechange = function() {            if (xhr.readyState == 4) {                console.log(1, JSON.parse(xhr.responseText))           }       }

post请求方式:

讯享网        var xhr = new XMLHttpRequest()        xhr.open(“post”, “http://open.douyucdn.cn/api/RoomApi/live")        xhr.setRequestHeader(”Content-Type“, ”application/x-www-form-urlencoded“)        xhr.send(”page=1“)        xhr.onreadystatechange = function() {            if (xhr.readyState == 4) {                console.log(2, xhr.responseText);           }       }
  • 第一步:创建一个xhr对象 var xhr = new XMLHttpRequest();
  • 第二步:设置请求方式和请求URL xhr.open( ) 参数1为请求方式get/post,如果请求方式是get,则参数2的请求URL带传递参数;如果为post,则参数2的请求URL不带传递参数(即不带URL中的 ?后边的一系列参数)
  • 第三步:发送请求 xhr.send(); get请求,send不带参数;post请求,send参数是post请求的请求体, 也是键值对结构
  • 第四步:监听readystatechange ,判断readyState的请求准备状态是不是4;请求准备状态有1-4,1表示xhr创建;2表示数据处理完成;3表示请求已发送;4表示服务器返回结果,请求完成 responseText: ”用户名已存在,注册失败“

2.2 jquery封装的ajax请求方式

 \(.get(&#34;http://open.douyucdn.cn/api/RoomApi/live&#34;, {            page: 1       }, function(data) {            console.log(3.1, data);       }) ​ \).post(”http://open.douyucdn.cn/api/RoomApi/live", {            page: 1       }, function(data) {            console.log(3.2, data);       }) ​ $.ajax({            type: “get”,            url: “http://open.douyucdn.cn/api/RoomApi/live",            data: {                page: 1           },            success: function(data) {                console.log(3.3, data);           }       })

2.3 axios封装的ajax请求方式

使用axios前必须引入插件

讯享网    &lt;script src=”https://unpkg.com/axios/dist/axios.min.js&#34;&gt;&lt;/script&gt;

get请求方式:

 axios.get(“http://open.douyucdn.cn/api/RoomApi/live", {            params: {                page: 1           }       }).then(function(res) {            console.log(4.1, res.data);       })

post请求方式:

讯享网axios.post(”http://open.douyucdn.cn/api/RoomApi/live", “page=1”, {            headers: {                “Content-Type”: “application/x-www-form-urlencoded”           }       }).then(function(res) {            console.log(4.2, res.data);       })
  • post请求数据没有在params字段中,get请求数据在params字段中
  • axios请求的回调函数在then函数中,而不是第三个参数

2.4 fetch函数请求

ES6中提供了一个函数fetch,是对原生ajax的封装,不需要插件,直接调用

fetch(“http://open.douyucdn.cn/api/RoomApi/live?page=1").then(function(res) {  // res是响应信息对象,里边没有响应体数据,需要使用json函数解析后拿到响应体      console.log(4, res);      var obj = res.json(); //调用json函数解析数据,返回的是promise对象            console.log(5, obj);      obj.then(function(data) { //使用promise对象调用then函数拿到数据                console.log(data);           })                //实际开发直接写            res.json().then(function(data) {                console.log(6, data);           })     })
  • 响应数据也是通过then函数拿到,而回调函数的res是响应对象,没有响应体数据,需要解析之后才能拿到响应体数据,只能解析一次。解析之后是个promise对象直接调用then拿到data数据

报错:TypeError: Response.json: Body has already been consumed.(响应体已经被解析过了)

原因:res调用json()只能调用一次,也就是只能解析一次

小讯
上一篇 2025-05-13 20:36
下一篇 2025-05-27 22:57

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/191214.html