• chrome插件开发时跨域问题解决方案


    在这里插入图片描述

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言~博主看到后会去代替大家踩坑的~接下来的几篇都是uni-app的小实战,有助于我们更好的去学习uni-app~最近在写一个飞机大战的小游戏,有兴趣的小伙伴可以关注一下
    主页: oliver尹的主页
    格言: 跌倒了爬起来就好~
    准备篇:https://oliver.blog.csdn.net/article/details/127185461
    启动页实现:https://oliver.blog.csdn.net/article/details/127217681
    敌机模型的实现:https://oliver.blog.csdn.net/article/details/127332264
    requestAnimationFrame详解:https://oliver.blog.csdn.net/article/details/127377916

    一. 前言

    chrome插件开发时遇到了这么个问题,网页存在一个跨域的请求,在正常的运行web界面时是使用jsonp开发实现的,当打包成chrome插件后,安装进浏览器这个跨域请求竟然他瞄的报错了…度娘了一堆,全他瞄的是错的,然后就有了我接下来3天的焦头烂额,直到我在CSDN看到一篇博文,里面贴了一个公告以及一个链接,接着就有了这篇踩坑记录;
    耐心看完,也许你将有所收获~
    (PS:如果需要demo的可以留言留邮箱,博主看到后会发给你的~)

    二. 官方说明

    首先先说结论吧,正常情况下的跨域请求都已经被堵死了,不可再使用,在度娘,CSDN查到的文章,大多数都是在这个chrome的这个版本更新前发布的,因此,文章里面的解决方式也许在那个时候确实有效可行,但目前肯定是不行了,具体我们可以看一下这个更新公告,
    官网地址https://www.chromium.org/Home/chromium-security/extension-content-script-fetches/
    页面截图
    在这里插入图片描述

    公告中开头第一句就是:

    tl;dr: To improve security, cross-origin fetches will soon be disallowed from content scripts in Chrome Extensions. Such requests can be made from extension background pages instead, and relayed to content scripts when needed. [The document has been edited on 2020-09-17 to reflect that CORS-for-content-scripts has successfully launched in Chrome 85*.]

    简单的说,就是跨域请求更严格了,原来在content script里面可以实现的跨域请求,现在也被封了(这种方式就是现在度娘或者CSDN中搜索到的绝大多数解决方案,因此全部失效~),同时官方也给出了解决方案,如果你真的是想要实现跨域,到background pages里面去实现吧~
    好吧,那我们就到background pages里去实现吧!

    三. 解决方案及实现

    3.1 方案概述

    注意:以下的实现以"manifest_version": 3为例子,版本3和版本2是不同的,因为3中有2里没有的配置项;
    根据background的实现,简单的说就是要几处改动:

    • 第一处,在manifest.json开启权限;
    • 第二处,jsonp调用的 跨域接口改造,改造成通过background pages进行 委托发送接收

    事件的大致流程图如下:
    在这里插入图片描述

    简单的说,就是在权限开启的情况下,要对接口进行改造,原先直接通过Jsonp进行的跨域请求要改成不再直接请求后端接口,而是通过chrome提供的API,发送到background.js中,在background.js中预设好接口与消息接收函数,当消息接收函数接收到消息后立刻发送跨域接口,由于接口是在background.js中,因此不会受到跨域拦截,当跨域接口获取到结果后,通过chrome内置的API再返回给页面~

    3.2 实现代码

    manifest.json

    在配置文件manifest.json中开启这个权限,代码大致如下:

    {
        "name": "demo",
        "version": "0.1.0",
        "manifest_version": 3,
        "icons": {
            "16": "icon/icon16.png",
            "48": "icon/icon48.png",
            "128": "icon/icon128.png"
        },
        "host_permissions": ["*://*/*"],
        "externally_connectable": {
            "matches": ["*://*.baidu.com/*"]
        },
        "background": {
            "service_worker": "background.js",
            "type": "module"
        },
        "permissions": ["activeTab", "bookmarks", "background"],
        "optional_permissions": ["https://www.google.com/", "https://www.baidu.com"],
        "chrome_url_overrides": {
            "newtab": "dist/index.html"
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    这里有几个是非常重要的配置项:

    • host_permissions:这个是用来开启权限的,这个值如果不设置,那么及时在bakcground.js中跨域还是会被拦截,注意的是这个字段只有在manifest_version为3时才会生效,如果你的manifest_version版本是2,那就不是这个配置项;
    • background:这个是用来指定background pages的,必须加,否则background.js不会执行,这也就导致了我们即使在页面发出了消息,也没有地方可以接收得到,那自然跨域请求不会被执行;

    background.js

    在这个文件中我们要实现的是消息的接收,先看代码

    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
        new Promise((resolve, reject) => {
            if (typeof request !== 'object' || !request.type) {
                console.error('参数异常');
                reject(`消息 ${JSON.stringify(request)} 格式不符合规范`);
                return;
            }
            switch (request.type) {
                case 'get':
                    fetch(request.url).then((res) => {
                        resolve(res.json());
                    });
                    break;
                case 'test':
                    resolve('测试');
                    break;
            }
        }).then((res) => {
            sendResponse(res);
        });
        return true;
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    这里面有一个chrome官方的API

    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
      	// 代码...
        return true;
    });
    
    • 1
    • 2
    • 3
    • 4

    差不多可以理解成这是一个用于接收消息的监听器,当触发消息委托时,这个监听器可以捕获到发出的消息,接着里面有一个请求

    fetch(request.url).then((res) => {
         // ...请求
    });
    
    • 1
    • 2
    • 3

    这里是 以fetch执行了一个跨域请求,将请求到结果后,通过sendResponse()这个函数将值返回到发出消息的页面;

    消息委托页面

    先看代码

    /**
     * 向Chrome发送消息
     * @param message 消息
     */
    export function getData(message: any) {
        return new Promise((resolve) => {
            // @ts-ignore
            chrome.runtime.sendMessage(message, resolve);
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    使用的时候完全像正常的API接口那般使用:

    getData({
        type: 'get',
        url: `xxxx`
    }).then((data: any) => {
        console.log(data)
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    核心的代码其实就这一行

    chrome.runtime.sendMessage(message, resolve);
    
    • 1

    借助的API也是chrome浏览器内置的API,当通过 chrome.runtime.sendMessage 将消息发送出去后,在background.js中会通过 chrome.runtime.onMessage.addListener 接收到,一旦接收到消息,那么会立刻触发跨域的接口,向后台发送请求,接口返回之后又通过 sendResponse(res) 发送到页面, 此时的页面自然也就可以获取到跨域接口的值;

    四. 小结

    本文简单介绍了在chrome插件的开发中如何解决接口跨域问题,随着谷歌对跨域越来越严格,好多老的方法之前可以用,但现在已经被封了,截止到目前而言,通过background的方式进行跨域访问还是可行的,以后还可不可以那要后续根据谷歌的公告再看~
    如果有别的好的方法,可以在chrome插件里进行跨域请求,麻烦留个言,告诉一下博主,谢谢~
    已经看到这里了,请点个赞吧,谢谢~

  • 相关阅读:
    xss原理分析
    【学生管理系统】权限管理
    .Net&Web前端-大三-零食系统-零食管理
    mysql指令
    简单个人静态HTML网页设计作品——广西北海家乡旅游景点 10页 DIV布局个人介绍网页模板代码 DW个人网站制作成品 web网页制作与实现
    【ffmpeg】音频重采样
    Day24 Python函数
    高斯分解LU矩阵之MATLAB实现
    HarmonyOS USB DDK助你轻松实现USB驱动开发
    四张图片如何合成一张四宫格?
  • 原文地址:https://blog.csdn.net/zy21131437/article/details/127422180