Electron?網(wǎng)絡攔截實戰(zhàn)示例詳解
正文
Electron 提供的 webRequest API,允許開發(fā)者對網(wǎng)絡進行過濾和監(jiān)聽,并且可以修改 header 字段甚至請求地址,功能非常強大,它的類結(jié)構(gòu)如下:
不過需要注意,該模塊只能在主進程中使用,接下來為大家介紹 webRequest 三個非常典型的使用場景:
自定義 UA
有些接口為了過濾非法請求,會首先校驗 UserAgent,正常的瀏覽器是無法偽造 UA 的,不過在 Electron 里面可以很容易做到,webRequest 模塊提供的 onBeforeSendHeaders
方法能夠?qū)τ蛎M行過濾,攔截即將發(fā)出去的請求頭,修改之后再真正的發(fā)出去。例如下面的代碼會在訪問 github 相關域名的時候,把 header 中的 User-Agent 字段修改為 MyAwesomeAgent:
const { session } = require('electron') const filter = { urls: ['https://*.github.com/*'] } session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => { details.requestHeaders['User-Agent'] = 'MyAwesomeAgent' callback({ requestHeaders: details.requestHeaders }) })
繞過跨域限制
使用 Electron 加載第三方網(wǎng)站的時候,默認行為和 Chrome 是一致的,都會受到同源策略的影響,為了驗證,我們首先加載本地 3020 端口上的靜態(tài)文件:
win = new BrowserWindow({ width: 600, height: 400 }) win.loadURL('http://localhost:3020') win.webContents.toggleDevTools({ mode: 'bottom' })
然后在 3030 端口上啟動一個 http 服務:
const Koa = require('koa') const app = new Koa() app.use((ctx, next) => { ctx.body = { success: true, } }) app.listen(3030)
此時在控制臺請求 3030 端口上的服務,會發(fā)現(xiàn)典型的跨域報錯,果不其然被 cors 策略拒絕了:
了解跨域原理的同學都知道,其實網(wǎng)絡請求是已經(jīng)回來了,但是瀏覽器會檢查 response header 里面的 Access-Control-Allow-Origin
,如果當前域名不在里面,就 block 這個響應,如下圖所示:
要想讓瀏覽器不 block 響應的話,傳統(tǒng)的解決方案一般有兩種:
- 讓后端添加
Access-Control-Allow-Origin
,支持當前的 Origin - 用 node 做本地代理來轉(zhuǎn)發(fā)請求
而在 Electron 里面,又多了一種方案,因為 Electron 可以對網(wǎng)絡請求進行攔截,任意修改請求或響應的 header,那么只要把響應標頭里面的 Access-Control-Allow-Origin
改掉不就好了么:
代碼如下:
const filter = { urls: ['http://localhost:*/*'], } win.webContents.session.webRequest.onHeadersReceived(filter, (details, callback) => { const { responseHeaders } = details responseHeaders['Access-Control-Allow-Origin'] = ['*'] callback({ responseHeaders }) })
打開網(wǎng)絡面板觀察網(wǎng)絡請求,響應標頭里面就有 Access-Control-Allow-Origin
了,成功繞過 cors 校驗:
請求轉(zhuǎn)發(fā)
通過 webRequest API,可以將發(fā)到接口 A 的請求轉(zhuǎn)發(fā)到接口 B。為了驗證這個能力,我們寫了一個 http 服務,同時監(jiān)聽 3030 和 4040 端口,并響應 JSON 數(shù)據(jù),里面包含了 port 字段表示當前請求到了哪個端口:
const http = require('http') const URL = require('url') function listen(port) { http .createServer((req, res) => { const { url, method, headers } = req const { query, pathname } = URL.parse(url, true) res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify({ method, pathname, query, headers, port })) }) .listen(port) } listen(3030) listen(4040)
然后通過 onBeforeRequest
方法進行攔截:
win.webContents.session.webRequest.onBeforeRequest( { urls: ['http://localhost:3030/*'], }, (details, callback) => { callback({ redirectURL: 'http://localhost:4040' }) }, )
在控制臺發(fā)送 3030 端口請求,結(jié)果返回了 4040 端口的數(shù)據(jù):
這個能力非常強大,例如可以做下面的事情:
- 后端接口未部署之前,前端自己做本地接口 mock
- 把某個頁面的 js 攔截掉,換成自己的 js 來調(diào)試
- 故意請求一個不存在的地址,然后僅對授權用戶轉(zhuǎn)發(fā)到真實地址
以上就是Electron 網(wǎng)絡攔截實戰(zhàn)示例詳解的詳細內(nèi)容,更多關于Electron 網(wǎng)絡攔截的資料請關注腳本之家其它相關文章!