跨域解决方案之JSONP实现

本文阅读时长:1分钟不到

前端面试,那可是经常问到同源策略跨域这问题啊

解决跨域的其中一种方式那必离不开JSONP,想必大伙随口都能答上来

那万一面试要手写JSONP实现时,如何写出让面试官眼前一黑的代码呢?

Webpack的异步加载模块也用到了JSONP哦

何为同源、跨域

同源就是"协议+域名+端口"三者都相同,其他没必要逼逼那么多。

同源策略会有如下限制范围:

  1. Cookie、LocalStorage 和 IndexDB
  2. DOM 无法获得
  3. AJAX发送过去,在数据从后端返回的路上被浏览器拦截了

JSONP原理

<script>标签的请求不被阻止,很多带有src属性的标签都不会组织,例如<img>。但是这些标签发起的请求都是GET,所以jsonp也只支持GET请求。

同时后端要响应的数据可以用回调函数名包裹成JavaScript,这时就得小心XSS攻击了:

// 这是一串js,回调函数的名字是'callback',回调函数的参数就是'hello,world!'
result = "callback" + "('hello,world')";    

JSONP实现

直接贴上一个HTML代码,方便运行,测试接口也是可以用滴。

不要问我为什么那么贴心又细致,因为我也是小白哈。。。要是有缺陷和其他问题,欢迎指出和讨论

百看不如一敲。敲!立马的!

<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <title>jsonp详细实现带注释</title>
  <script>
    function jsonp(url, params, callback = null) {
      // 函数调用计数,每次调用该函数时自增,避免回调函数重名
      const cb_count = ++jsonp.cnt || (jsonp.cnt = 1)
      const callbackName = callback || ('cb_' + cb_count)
	 
      // 向URL后面拼接请求参数和回调函数名
      let querystring = (url.indexOf("?") > 0 ? '&' : '?') + (`callback=${callbackName}`)
      Object.entries(params || {}).forEach(([k, v]) => querystring += (`&${k}=${v}`))

      // 创建script标签、添加src属性并添加到body中
      const scriptTag = document.createElement('script')
      scriptTag.src = url + querystring
      document.body.appendChild(scriptTag)

      return new Promise((resolve, reject) => {
        window[callbackName] = (data) => {
          resolve(data)
          scriptTag.remove()
          delete window[callbackName]
        }
      })
    }
  </script>
</head>

<body>
  <h2> JSONP的实现流程</h2>
  <ul>
    <li>声明回调函数,函数名(jsonp)作为API的请求参数,函数形参为要获取的数据</li>
    <li>创建一个&lt;script&gt;标签,src="api接口",附加上函数名e.g: ?callback=jsonp</li>
    <li>后端判断是jsonp的请求,则把数据和回调函数名进行拼接e.g: "jsonp('Merry Christmas ')"</li>
    <li>后端把拼接后的字符串返回,它将被作为&lt;script&gt;标签的脚本被浏览器执行</li>
  </ul>
</body>
    
<script>
  jsonp('https://api.asilu.com/php/web-info.php?url=https://www.qq.com/&jojo=6').then(data => {
    console.log(data)
  })

  jsonp('https://api.asilu.com/php/web-info.php', {
    url: 'https://v.douyin.com/'
  }).then(data => {
    console.log(data)
  })

  jsonp('https://suggest.taobao.com/sug', {
    code: 'utf-8',
    q: '脆脆鲨'
  }).then(data => console.log(data))
</script>

</html>

参考

MDN 浏览器的同源策略

测试接口:爱思路

阮一峰 浏览器同源政策及其规避方法

posted @   禾几元  阅读(67)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示