前端通过Chrome插件跨域请求

我们肯定学过,通过jsonp实现跨域请求,或是后台通过cors实现跨域请求,这次开拓一个新思路,使用chrome插件绕过浏览器同源策略

参考文档:http://chrome.cenchy.com/ https://developer.chrome.com/extensions

这是我后面做的一个ajax劫持跨域插件:https://www.jianshu.com/p/417ffc9bf1a2

DEMO效果图

使用background请求

原理图

请求过程

background.html:background页是chrome://extensions/打开的,没有域,所以使用background请求不会被浏览器同源策略影响

content_script:通过谷歌插件注入到页面中的JS,使用他创建 EventDom 用于接收提交按钮的请求发送给background页

EventDom:因为content_script是无法直接与页面中的JS通信的,但是content_script可以操作页面中的dom,我们可以使用content_script创建一个EventDom.帮我们传递 事件数据

1. 创建一个Chrome插件项目

创建manifest.json

{
    "manifest_version": 2,
    "name": "One-click Kittens",
    "description": "This extension demonstrates a browser action with kittens.",
    "version": "1.0",
    "permissions": [
        "http://127.0.0.1/",
        "tabs"
    ],
    "browser_action": {
        "default_icon": "icon.png",
        "default_popup": "popup.html"
    },
    "background": {
        "scripts": [
            "background.js"
        ]
    },
    "web_accessible_resources": [
        "/*"
    ],
    "content_scripts": [
        {
            "matches": [
                "http://127.0.0.1/"
            ],
            "js": [
                "content_script.js"
            ]
        }
    ]
}

2.background.js

background中通过chrome.runtime中的api,可以实现background和content_script之间的的通信
background使用tabId给对应的content_script发送消息

chrome.runtime.onMessage.addListener(function (e, sender) {
  const { message, data } = e
  const tabId = sender.tab.id
  switch (message) {
    case 'XHR':
      request_proxy(data, tabId); break
  }
})
function request_proxy({ url, method, data }, tabId) {
  var XHR = new XMLHttpRequest()
  console.log(tabId)
  XHR.open(method, url)
  XHR.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
  XHR.send(data)
  XHR.onreadystatechange = function () {
    if (XHR.readyState === 4) {
      chrome.tabs.sendMessage(tabId, {
        message: 'XHR_response',
        data: XHR.responseText
      })
    }
  }
}

3.content_script

使用content_script创建EventDom。这里随便创建了个‘button’,没别的意思,任何标签都可以,只是使用element.dispatchEvent触发自定义事件。
然后通过触发(dispatchEvent)/响应(addEventListener)EventDom的事件与HTML页进行通信
并通过chrome的API 发送(chrome.runtime.sendMessage)/接收(chrome.runtime.onMessage.addListener)与background进行通信
dispatchEvent:https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/dispatchEvent

var button = document.createElement('button'); //创建EventDom
button.id = 'chrome_eventBus'
button.addEventListener('request_proxy', function (e) {
    let { eventData } = e.target.dataset
    eventData = JSON.parse(eventData)
    let { url, method, data } = eventData
    chrome.runtime.sendMessage('jencllhednpfafogdnjmoneilbiifloc', {
        message: 'XHR',
        data: {
            url,
            method,
            data
        }
    })
})
document.body.appendChild(button);
const e = new Event('content_script_Ready') //触发自定义事件,在content_script注入并添加dom后,通知html页绑定Dom的事件
document.body.dispatchEvent(e)


chrome.runtime.onMessage.addListener(function (e, sender, sendResponse) {
    console.log(e, sender, sendResponse)
    const { message, data } = e
    switch (message) {
        case 'XHR_response':
            response(data); break
    }
})

function response(data) {
    button.dataset['eventData'] = data
    const e = new Event('response')
    button.dispatchEvent(e)
}

4.Html页

html页就是你的项目,在这里你需要在content_script注入完毕后为EventDOM绑定事件。将请求通过EventDom发送给content_script
例如 登陆请求时dispatch EventDom的request_proxy事件,通过html5的dataset传递数据(也可以通过别的传,例如localstorage,indexdb。。。)

let iptUrl = document.getElementById('url')
let iptMethod = document.getElementById('method')
let iptData = document.getElementById('data')

let $ChromeEventBus = null //EventDom

document.getElementById('req-default').addEventListener('click', () => {
  let url = iptUrl.value
  let method = iptMethod.value
  let data = iptData.value

  let XHR = new XMLHttpRequest()
  XHR.open(method, url)
  XHR.send(JSON.stringify(data))
})
document.getElementById('req-background').addEventListener('click', () => {
  let url = iptUrl.value
  let method = iptMethod.value
  let data = iptData.value
  let option = {
    url,
    method,
    data
  }
  $ChromeEventBus.dataset['eventData'] = JSON.stringify(option)
  const e = new Event('request_proxy')
  $ChromeEventBus.dispatchEvent(e)
})
document.body.addEventListener('content_script_Ready', Init) //当content_script注入完毕,并且创建EventBus后,进行事件的初始化
function Init() {
  $ChromeEventBus = document.getElementById('chrome_eventBus')
  $ChromeEventBus.addEventListener('response', function (e) {
    let { eventData } = e.target.dataset
    console.log('response', JSON.parse(eventData))
  })
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • chrome扩展开发入门教程 最近在开发chrome插件,看到一篇非常适合入门的教程,特记录一下 注:转载 本文首...
    谢大见阅读 6,576评论 1 25
  • Chrome扩展开发 标签(空格分隔): Chrome扩展 1、写在前面 Chrome插件是一个用Web技术开发...
    记忆的时间差阅读 6,149评论 0 15
  • 1. 简介 Chrome插件是一个用Web技术开发、用来增强浏览器功能的软件,Chrome浏览器扩展开发算是相当简...
    overflow_hidden阅读 7,622评论 0 16
  • 架构 总括:Manifest:程序清单Background:插件运行环境/主程序Pop up:弹出页面Conten...
    程序员小逗逼阅读 10,502评论 2 18
  • 第二十二章租赁 本章考情分析 本章阐述承租人和出租人形成的融资租赁、经营租赁和售后租回交易的会计处理。分数一般在3...
    陆丁目阅读 2,782评论 0 0

友情链接更多精彩内容