网页开发

CORS & JSONP 学习笔记一

2019-04-12  本文已影响0人  人话博客

什么是跨域?

首先,现代浏览器为了安全,做了一个同源限制.

也就是所谓的同源安全策略.

本质上,其实是不存在所谓的跨不跨域的.
把浏览器想象成一个发送网络请求的软件.
按照道理来说,请求都是可以发送出去的.
但是在 web 端,浏览器里,这么做的就不合适.
如果网络上的接口可以不受限制的被任意人调用.
那将是一个非常混乱的场景.
所以,为了防止这种情况,浏览器做了这个同源策略来防止这种情况发生.
对,一般服务器不管这个事情.

跨域指的是,A网站内部向B网站发送一个AJAX请求.

由于浏览器有同源策略的限制,默认情况下,是不允许 A网站向 B 网站请求数据资源的.

http://my.website.com/ ---> http://your.website.com/ 是不允许的.

具体来说,凡是发送请求中,协议,主机名,端口号 有一个不同,即为跨域请求.

上述例子:my.website.comyour.website.com 就属于主机名不同而导致的跨域.

具体可以参照下面这个表.

image.png

总结一句:

协议相同 + 域名相同 + 端口号相同

浏览器才认为是同一个网站.
才不同受到同源策略的影响.
才可以正常的发送 AJAX 请求.

其他情况下,发送 AJAX 请求,都属于跨域.

请注意: 这里说的是 XMLHttpRequest 下的 AJAX 请求.

对于 <img> , <script>, <link> 等标签,就不存在跨域请求.(除非对方后台做了防盗链)

继续补充:

所谓的同源策略是浏览器实现的,而和后台服务器无关.
A 发送请求到 B. 请求实际上是发送到了 B 后台, B后台接受到数据后.
其实也有返回.
只不过,这个数据返回到浏览器之后,浏览器把这个数据给劫持了.不让A网站使用.


为什么要跨域?

既然跨域这么麻烦,都不能从网站后台拿到数据,那为什么还要搞跨域呢?

因为当一个项目变大时,把所有的内容都丢在一个网站或者是后台服务器中是不现实的.

比如:

一个网站体量很大.有很多可以独立且复杂的业务

最后剩下的就是web的UI层面的东西.

把这个UI层面的东西和哪个数据服务API的网站集成在一起比较合适呢?

都不适合.

它应该是一个专门的网站.

image.png

所以域名可能存在如下情况:

所以,UIWeb 如果需要请求这数据.

不管请求哪个后台服务器的数据,都存在跨域的情况.

也就是无法利用 ajax 异步的获取到数据内容.


利用 jsonp 进行跨域

jsonp 跨域是里用在浏览器中,下载一个script标签是不受同源策略限制的特性.(bootcdn中不是有很多的js文件下载吗?)

具体实现原理大概分下面几步

前端端口是:8080

button.addEventListener('click', function () {
    // 利用下载script标签是不存在浏览器同源策略的特点.
    const scriptTag = document.createElement('script')
    scriptTag.type = 'text/javascript'
    // 第一 22222 端口号不同.
    // 第二 callback=show 是传递给22222后台服务器的查询字符串参数.
    // 第三 后台服务器根据拿到了这个callback = show,往前端输出一些文本流.(这里就是和利用下载script标签一模一样.)
    scriptTag.src = 'http://localhost:12345/getUserinfo?callback=show'
    document.body.appendChild(scriptTag)
  },false)

  // 这里的show 方式就是上述 jsonp 中的 callback 查询字符串指定的值.
  function show (user) {
    let dataStr = ""
    for(let prop in user) {
      dataStr += prop  + ":" + user[prop] + "<br>"
    }
    unOriginPlaceHolder.innerHTML = dataStr
  }

后端端口是:12345

const app = require('express')()
const url = require('url')
const queryString = require('querystring')

app.get('/getUserInfo', (request, response) => { 
  const queryObj = url.parse(request.url, true).query
  const callback = queryObj.callback // 获取callback参数

  const data = {
    userid: 1,
    name: '李四',
    age: 22,
    profession: '软件工程师'
  }

  const objStingIfy = JSON.stringify(data)
  console.log(objStingIfy)
  
  // 拼接 callback(数据) 字符串,返回给前端
  response.end(`${callback}(${objStingIfy})`)

})

app.listen(22222, () => { 
  console.log('服务启动成功!')
})

结果:

image.png

jsonp使用总结:


cors

corsCross-Origin-Resource-Sharing 的缩写.
也是现代浏览器普遍支持的一种非常方便的跨域方案.

它的具体工作流程是:

浏览器在检测到你发送的 ajax 请求不是同源请求时,会自动在 http 的头部添加一个 origin 字段.

image.png

之前也说过,请求怎么滴都能发送出去.

我们拿不到数据是因为浏览器在中间做了一层劫持.

image.png image.png

获取不到数据的原因也很简单:

这个时候,只需要后台在相应头里加上一个 Access-Control-Allow-Origin:* 即可完成跨域数据获取.

image.png

CORS 跨域方案简单总结:

image.png

还有一种proxy模式.

核心思想是:

让前端请求我们自己的后台,让后台去跨域请求真是的数据,然后把数据返回给前台.

实现方式,可以利用 nginx 做反向代理.以及我们自己写一个后台中转的服务器.

码云DEMO地址

上一篇 下一篇

猜你喜欢

热点阅读