同源:

同源: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())

前端代码:

<h1 id="h1">这是主页</h1><script>// 访问目标服务器的登录接口$.get("http://localhost:5000/login?name=张三", function(data){h1.innerText = data})</script>
  • 优点:简单方便,容易操作,前端请求无需修改ajax代码

  • 缺点:数据安全性降低,完全受后端限制,前端无法控制

1.2 jsonp跨域

原理:同源策略只对ajax请求有限制,非ajax请求无限制,非ajax请求(如:form表单请求、标签属性请求,a标签的href,img标签的src,script标签的src)不会被同源策略拦截,所以使用script标签的src属性发起的跨域请求不会被同源策略拦截。

步骤:前端(3种):

1,原生的jsonp请求:

前端:

 <script>function myMethod(res){console.log(res)alert(res.name)}</script><script src="http://192.168.124.43:3000/userInfo?callback=myMethod"></script>
  • callback这个字段不能自定义,是jsonp内部规定好的字段,不用callback调用不了

后端:

app.get('/userInfo', function(req, res) {console.log(req.query)req.query.callback({ name: "李四" })
})

2,常规的开发习惯写法

前端:

  <script>function myMethod2(res){alert(res.name)}$("<script>").attr("src", "http://192.168.124.43:3000/userInfo?callback=myMethod2").appendTo("body")</script>

后端同1一样

3,jquery封装jsonp请求,使用$.getJSON()实现

前端:

 <script>// 由于jquery封装后,回调函数是匿名函数, 所以参数写成  callback=?  ?代表后边匿名函数$.getJSON("http://192.168.124.43:3000/userInfo?callback=?", function(res) {alert(res.name)})</script>

后端:

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跨域请求,获取跨域数据后返回给同源客户端

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

前端:

 <h1 id="h1">这是主页</h1><script>// 访问目标服务器的登录接口$.get("/myApi/login?name=张三", function(data) {h1.innerText += data})// 访问目标服务器的注册接口$.post("/myApi/register?name=张三", function(data) {h1.innerText += data})</script>

后端:

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("http://open.douyucdn.cn/api/RoomApi/live", {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前必须引入插件

    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

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()只能调用一次,也就是只能解析一次

跨域解决的三种方法、四种请求方式相关推荐

  1. AJAX异步请求解决跨域问题的三种方式

    一 什么是跨域 出于浏览器的同源策略限制.同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说We ...

  2. 几种常见的跨域解决方法

    前言 由于浏览器的同源策略,当我们请求网络资源时,所在页面的url中的协议,端口,域名其中一个与请求资源的url不同,都会出现跨域的问题.但是浏览器不能没有这个策略,这样会很危险,像csrf,xss攻 ...

  3. jquery、javascript实现(get、post两种方式)跨域解决方法

     jquery.javascript实现(get.post两种方式)跨域解决方法 一.实现get方式跨域请求数据 浏览器端 <script> $(document).ready(fun ...

  4. 介绍什么是同源和什么是跨域,以及三种解决跨域问题的路径

    什么是同源?什么是跨域? 客户端向服务器发送请求的时候,如果协议,域名(IP)和端口都一样,则称为同源,但凡有一个不一样则跨域,跨域请求默认受到浏览器的安全策略的限制,浏览器会给出相应的错误信息,对于 ...

  5. vue跨域解决的几种方案

    vue跨域解决的几种方案 一.开发环境解决跨域方法 平时使用vue开发的时候,大多会使用vue-cli搭建项目,在vue-cli搭建的项目中有一个配置文件vue.config.js,可以在该文件中进行 ...

  6. 什么是跨域 解决跨域的方法 (分分钟)

    一 ,为什么会出现跨域问题 处于浏览器的同原则策略(Sameoriginpolicy)是一种约定,它是浏览器最核心 也是基本的安全共功能,如果缺少了同源策略,则浏览器的正常功能可能会 收到影响.可以说 ...

  7. JavaScript跨域解决方法大全

    跨域的定义:JavaScript出于安全性考虑,同源策略机制对跨域访问做了限制.域仅仅是通过"URL的首部"字符串进行识别,"URL的首部"指window.lo ...

  8. Js跨域解决方法总结

    本文转载自网易博客 出于安全性的考虑,在AJAX应用中,浏览器通常都会限制跨域提交数据.但由于经常和其他部门有接口对接的业务需求,需要跨域获取数据. IE对于跨域访问的处理是,弹出警告框,提醒用户.如 ...

  9. 微信 android 闪退问题怎么解决方法,如何解决微信闪退问题 四种解决微信闪退无法登录的原因及方法分享...

    微信闪退无法登录怎么办?现在使用微信的用户越来越多,即方便又快捷,有的朋友在使用时候可能会遇到微信闪退无法登陆的情况,今天小编为大家带来了四种解决微信闪退无法登录的原因及方法分享,感兴趣的朋友快来了解 ...

最新文章

  1. djc加密数字货币_清华大学《区块链和加密数字货币》课程线上开课,与李礼辉、姚前等大佬一起交流学习吧...
  2. [拓扑排序/强联通分量] [NOIP201402] 信息传递
  3. java下載與安裝_[Java] 下載與安裝Java官方開發工具:NetBeans IDE
  4. android 机顶盒 系统开发入门,读《Android电视机(机顶盒)初次开发的一些经验分享》后的笔记...
  5. 【ArcGIS遇上Python】ArcGIS批量为多个矢量图层添加一个或多个字段(Add Field)案例实现
  6. eclipse使用技巧_有效使用Eclipse的热门技巧
  7. WinPcap笔记(1):VisualStudio2015配置WinCap
  8. openwrt gstreamer实例学习笔记(四. gstreamer Bins)
  9. logstash_output_mongodb插件用途及安装详解
  10. 为什么南派三叔要封笔?
  11. python和c语言的区别-python和c语言的区别是什么
  12. Wannafly交流赛1: D. 迷宫2(最短路)
  13. mysqlbinlog: unknown variable 'default-character-set=gbk'错误
  14. 陕西师范大学计算机专业录取,陕西师范大学计算机类专业2016年在湖北理科高考录取最低分数线...
  15. 利用Exchange 2003实现移动办公新体验
  16. MySQL数据库如何启动?
  17. 小学生c语言入门教程,小学生都看得懂的C语言入门(5): 指针
  18. DAY8:尚学堂高琪JAVA(70~76)
  19. 惊呆了!和平精英手游今天下午3点公测,这简直就是翻版的刺激战场啊
  20. android listview仿iphone通讯录ios 3dTouch

热门文章

  1. java实现冗余校验_循环冗余校验_循环冗余校验码计算_循环冗余校验 java实现
  2. Aov网络与拓补排序的实现
  3. 智慧物业,美丽家园中的充电桩应用
  4. Java--捕鱼达人
  5. springboot系列(十二):如何实现邮件发送提醒,你一定得会(准备篇)
  6. 使用BumpTop将桌面撞入3D
  7. 电子邮件管理系统 android,IM800电子邮件管理系统
  8. 20款超酷PSD按钮素材
  9. 【爬虫】Yhen手把手教你爬取表情包,让你成为斗图界最靓的仔!
  10. 第一企信CEO自述:在华为工作9年,我为什么要辞职创业