Ajax跨域请求之同源政策、跨域请求 & 实现跨域请求之jsonp原理、jQuery实现跨域请求、CORS跨域 & XML格式-过时 & ajax请求遵循http协议
3. Ajax跨域请求
3.1 同源政策
1995年,同源政策由 Netscape(网景) 公司引入浏览器。目前,所有浏览器都实行这个政策。
最初,它的含义是指,A 网站设置的 Cookie,B 网站不能打开,除非这两个网页同源。所谓同源指的是三个相同。
- 协议相同(http https)
- 域名相同
- 端口相同(http默认80端口,https默认443端口)
随着互联网的发展,同源政策越来越严格。目前,如果非同源,共有三种行为受到限制。
- Cookie无法读取。
- DOM 无法获得。
- AJAX 请求无效(可以发送,但浏览器会拒绝接受响应)。
3.2 什么是跨域请求
其实,了解了什么是同源政策,就知道什么是跨域请求了。
在发送Ajax请求的时候,请求的地址只要违反了同源政策,那么就属于跨域请求。
3.3 实现跨域请求的方案–JSONP
1)JSONP简介
JSON with Padding,是一种借助于 script
标签发送跨域请求的技巧。
其原理就是在客户端借助 script
标签请求服务端的一个地址,服务端的这个地址返回一段带有调用某个全局函数调用的 JavaScript 脚本(而非一段 HTML),将原本需要返回给客户端的数据通过参数传递给这个函数,函数中就可以得到原本服务端想要返回的数据。
以后绝大多数情况都是采用 JSONP 的手段完成不同源地址之间的跨域请求
2)使用JSONP实现跨域请求
- 首先得创建两个服务器,一个服务器(:3000)向另外一个服务器(:4000)发送请求
- 在3000里面写一个HTML页面index.html
- 在3000里面,app.js中,返回index.html
app.get('/index.html', (req, res) => { res.sendFile(__dirname + '/index.html'); })
重启服务器,此时,访问127.0.0.1:3000/index.html 就可以看到页面
- 在3000中的 index.html 中,通过script的src属性,请求4000网站中的一个接口
<script src="http://127.0.0.1:4000/getHeroes"></script>
- 到4000中,写接口 getHeroes,完成响应
app.get('/getHeroes', (req, res) => { // 返回的内容,只要符合JS的语法即可 // res.send('hello'); res.send('alert(123)'); })
写好之后,4000要重启服务器
- 刷新页面就可以看到弹出框了
<script src="http://127.0.0.1:4000/getHeroes"></script>
3)实现跨域传输数据
前面实现了跨域请求。如果4000网站返回一个调用函数的字符串,那么3000网站接收到之后,也会执行一个函数。然后给函数传递一个参数,这个参数就是要传输的数据。
- 4000网站,返回一个调用函数的字符串
app.get('/getHeroes', (req, res) => { // res.send('hello'); // res.send('alert(1234);'); let heroes = [ { name: '曹操', age: 30}, { name: '鲁达', age: 31} ]; heroes = JSON.stringify(heroes); res.send('abc('+heroes+')'); });
- 3000网站,要提前准备好一个叫做abc的函数,用于接收4000返回的数据
<script> // 输出4000网站返回的内容 // console.log(aa); // 为了配合4000网站的要求,所以要定义一个abc函数 function abcd (res) { console.log(res); } </script> <script src="http://127.0.0.1:4000/getHeroes"></script>
这样就可以实现跨域请求了。并且也实现了数据的传输。
问题是两个网站的函数名字如何统一?大家有一个约定,请求的时候,要把你的函数名传递给4000网站,并且参数名必须是callback。
- 3000网站中,将函数名以参数的形式,传递过去
<script> // 输出4000网站返回的内容 // console.log(aa); // 为了配合4000网站的要求,所以要定义一个abc函数 function abc(res) { console.log(res); } </script> <script src="http://127.0.0.1:4000/getHeroes?callback=abc"></script>
- 4000网站中,获取地址栏的callback参数,值就是函数的名字
app.get('/getHeroes', (req, res) => { // res.send('hello'); // res.send('alert(1234);'); let heroes = [ { name: '曹操', age: 30}, { name: '鲁达', age: 31} ]; heroes = JSON.stringify(heroes); // 获取函数名 let fn = req.query.callback; // res.send('alert(' + heroes + ')'); res.send(fn + '('+heroes+')'); });
实例
1、新建客户端3000文件夹和服务器端4000文件夹,并初始化
npm init -y npm i express
2、新建app.js
3000/app.js
const express = require('express'); const ap = express(); app.listen(3000, () => console.log('3000 start'));
4000/app.js
const express = require('express') const app = express() app.listen(4000, () => console.log('4000 start'))
3、启动项目
node .\app.js nodemon .\app.js
效果
4、jsonp代码
代码
3000/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <img src="https://gss3.bdstatic.com/84oSdTum2Q5BphGlnYG/timg?wapp&quality=80&size=b150_150&subsize=20480&cut_x=0&cut_w=0&cut_y=0&cut_h=0&sec=&srctrace&di=0767d0a97b3985dc5e75e&wh_rate=null&src=http%3A%2F%2Fimgsrc.baidu.com%2Fforum%2Fpic%2Fitem%2F562c11dfa9ec8af0ffa0ecc0b3.jpg" /> <script src="https://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script> <!-- JSONP原理代码 --> <script> // 4000网站返回的内容,被3000网站当做js代码执行了 function abcd (res) {
console.log(res); } </script> <script src="http://127.0.0.1:4000/getHeroes?callback=abcd"></script> </body> </html>
4000/app.js
const express = require('express') const app = express() app.listen(4000, () => console.log('4000 start')) // 定义一个接口 app.get('/getHeroes', (req, res) => {
// res.send('hello'); // res.send('alert(1234);'); let heroes = [ {
name: '曹操', age: 30 }, {
name: '鲁达', age: 31 }, ] heroes = JSON.stringify(heroes) // 获取函数名 let fn = req.query.callback // res.send('alert(' + heroes + ')'); res.send(fn + '(' + heroes + ')') })
4)jQuery封装的ajax方法跨域请求
- 在3000网站中,jsonp2.html 中引入一个jQuery文件,为了方便(引入自己的jQuery,自己就得写处理静态资源文件的代码),引入的是百度提供的jquery
- 使用jQuery提供的ajax方法,实现跨域访问
3000/index.html
<!-- 使用jQuery提供的ajax方法,实现跨域请求 --> <!-- 下面引入百度提供的jQuery,需要联网 --> <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script> <script> $.ajax({ type: 'GET', url: 'http://127.0.0.1:4000/getHeroes', dataType: 'jsonp', / 这里一定要使用jsonp success: function (res) { console.log(res) } }); </script>
4000/app.js文件不变,同上
3000/index.html完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <img src="https://gss3.bdstatic.com/84oSdTum2Q5BphGlnYG/timg?wapp&quality=80&size=b150_150&subsize=20480&cut_x=0&cut_w=0&cut_y=0&cut_h=0&sec=&srctrace&di=0767d0a97b3985dc5e75e&wh_rate=null&src=http%3A%2F%2Fimgsrc.baidu.com%2Fforum%2Fpic%2Fitem%2F562c11dfa9ec8af0ffa0ecc0b3.jpg" /> <script src="https://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script> <script> $.ajax({ type: 'GET', url: 'http://127.0.0.1:4000/getHeroes', dataType: 'jsonp', success: function(res) { console.log(res) } }); </script> <!-- JSONP原理代码 --> <!-- <script> // 4000网站返回的内容,被3000网站当做js代码执行了 function abcd (res) { console.log(res); } </script> <script src="http://127.0.0.1:4000/getHeroes?callback=abcd"></script> --> </body> </html>
打开页面效果
3.4 实现跨域请求的方案–CORS
通过在被请求的路由中设置header头,可以实现跨域。不过这种方式只有最新的浏览器(IE10)才支持。
Cross Origin Resource Share,跨域资源共享
app.get('/time', (req, res) => {
// // 允许任意源访问,不安全 // res.setHeader('Access-Control-Allow-Origin', '*') // 允许指定源访问 res.setHeader('Access-Control-Allow-Origin', 'http://www.xxx.com') res.send(Date.now().toString()) })
这种方案无需客户端作出任何变化(客户端不用改代码),只是在被请求的服务端响应的时候添加一个 Access-Control-Allow-Origin
的响应头,表示这个资源是否允许指定域请求。
实例
cors效果
代码-cors代码
代码
3000客户端系列代码
3000/app.js
const express = require('express'); const app = express(); app.listen(3000, () => console.log('3000 start')); // 显示index.html app.get('/index.html', (req, res) => {
res.sendFile(__dirname + '/index.html'); }); app.get('/cors.html', (req, res) => {
res.sendFile(__dirname + '/cors.html'); });
3000/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <img src="https://gss3.bdstatic.com/84oSdTum2Q5BphGlnYG/timg?wapp&quality=80&size=b150_150&subsize=20480&cut_x=0&cut_w=0&cut_y=0&cut_h=0&sec=&srctrace&di=0767d0a97b3985dc5e75e&wh_rate=null&src=http%3A%2F%2Fimgsrc.baidu.com%2Fforum%2Fpic%2Fitem%2F562c11dfa9ec8af0ffa0ecc0b3.jpg" /> <script src="https://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script> <script> $.ajax({
type: 'GET', url: 'http://127.0.0.1:4000/getHeroes', dataType: 'jsonp', success: function(res) {
console.log(res) } }); </script> <!-- JSONP原理代码 --> <!-- <script> // 4000网站返回的内容,被3000网站当做js代码执行了 function abcd (res) { console.log(res); } </script> <script src="http://127.0.0.1:4000/getHeroes?callback=abcd"></script> --> </body> </html>
3000/cors.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <script> var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://127.0.0.1:4000/aa'); xhr.send(); xhr.onload = function () {
console.log(this.response) } </script> </body> </html>
4000服务端系列代码
4000/app.js
const express = require('express') const app = express() app.listen(4000, () => console.log('4000 start')) // 定义一个接口 app.get('/getHeroes', (req, res) => {
// res.send('hello'); // res.send('alert(1234);'); let heroes = [ {
name: '曹操', age: 30 }, {
name: '鲁达', age: 31 }, ] heroes = JSON.stringify(heroes) // 获取函数名 let fn = req.query.callback // res.send('alert(' + heroes + ')'); res.send(fn + '(' + heroes + ')') }) // 实现CORS跨域的接口 app.get('/aa', (req, res) => {
// 加入CORS头 // res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:3000') res.end('hello') })
4.XML
HTML:超文本标记语言
XML: eXtension Markup Language 可扩展标记语言
一种数据描述手段
老掉牙的东西,简单演示一下,不在这里浪费时间,基本现在的项目不用了。
淘汰的原因:数据冗余太多
<?xml version="1.0" encoding="UTF-8" ?> <students> <stu id="1"> <name>张三</name> <age>18</age> <sex>男</sex> <other height="175cm" weight="65kg" /> </stu> <stu id="2"> <name>李四</name> <age>20</age> <sex>女</sex> <other height="170cm" weight="60kg" /> </stu> </students>
XML语法规范:
- 和html写法差不多
- 有且只有一个根标签
- 标签区分大小写
- 标签必须闭合
- 属性值必须加引号
如果服务器返回的是XML格式的数据,JS收到数据之后,把收到的数据当做document对象来处理即可。
5.原生的xhr获取请求报文和响应报文的信息
ajax请求,也是遵循http协议的。
ajax请求过程中,可以设置请求报文、也可以获取响应报文
<script> // 请求报文: // 行 // 头 // 体 // 响应报文: // 行 // 头 // 体 var xhr = new XMLHttpRequest(); xhr.open('post', '/abc'); // 体现了请求行的内容(请求方式和接口地址) xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 体现了请求头 xhr.send('aa=xxx&bb=yyy'); // 体现了请求体 xhr.onload = function () {
console.log(this.status); // 体现了响应行的状态码 console.log(this.statusText); // 体现了响应行的状态描述信息 console.log(this.getAllResponseHeaders()); // 体现了所有的响应头 console.log(this.getResponseHeader('content-length')); // 体现了所有的响应头 console.log(this.response); // 体现了响应体的内容 } </script>
实例
1、新建http文件夹,并初始化
npm init -y npm i express
2、搭建服务器
http/app.js
const express = require('express'); const app = express(); app.listen(3000, () => console.log('kaiqi')); app.get('/index.html', (req, res) => {
res.sendFile(__dirname + '/index.html'); }); app.post('/abc', (req, res) => {
res.send('hello'); });
3、访问页面
http/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <script> // 请求报文: // 行 // 头 // 体 // 响应报文: // 行 // 头 // 体 var xhr = new XMLHttpRequest(); xhr.open('post', '/abc'); // 体现了请求行的内容(请求方式和接口地址) xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 体现了请求头 xhr.send('aa=xxx&bb=yyy'); // 体现了请求体 xhr.onload = function () {
console.log(this.status); // 体现了响应行的状态码 console.log(this.statusText); // 体现了响应行的状态描述信息 console.log(this.getAllResponseHeaders()); // 体现了所有的响应头 console.log(this.getResponseHeader('content-length')); // 体现了所有的响应头 console.log(this.response); // 体现了响应体的内容 } </script> </body> </html>
4、http终端中,启动服务
node ./app.js
5、页面访问,显示数据
地址——http://127.0.0.1:3000/index.html
6、效果
到此这篇Ajax跨域请求之同源政策、跨域请求 & 实现跨域请求之jsonp原理、jQuery实现跨域请求、CORS跨域 & XML格式-过时 & ajax请求遵循http协议的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/haskellbc/10823.html