首頁 > 軟體

Electron 網路攔截實戰範例詳解

2023-03-11 06:01:26

正文

Electron 提供的 webRequest API,允許開發者對網路進行過濾和監聽,並且可以修改 header 欄位甚至請求地址,功能非常強大,它的類結構如下:

不過需要注意,該模組只能在主程序中使用,接下來為大家介紹 webRequest 三個非常典型的使用場景:

自定義 UA

有些介面為了過濾非法請求,會首先校驗 UserAgent,正常的瀏覽器是無法偽造 UA 的,不過在 Electron 裡面可以很容易做到,webRequest 模組提供的 onBeforeSendHeaders 方法能夠對域名進行過濾,攔截即將發出去的請求頭,修改之後再真正的發出去。例如下面的程式碼會在存取 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 載入第三方網站的時候,預設行為和 Chrome 是一致的,都會受到同源策略的影響,為了驗證,我們首先載入本地 3020 埠上的靜態檔案:

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 埠上的服務,會發現典型的跨域報錯,果不其然被 cors 策略拒絕了:

瞭解跨域原理的同學都知道,其實網路請求是已經回來了,但是瀏覽器會檢查 response header 裡面的 Access-Control-Allow-Origin,如果當前域名不在裡面,就 block 這個響應,如下圖所示:

要想讓瀏覽器不 block 響應的話,傳統的解決方案一般有兩種:

  • 讓後端新增 Access-Control-Allow-Origin,支援當前的 Origin
  • 用 node 做本地代理來轉發請求

而在 Electron 裡面,又多了一種方案,因為 Electron 可以對網路請求進行攔截,任意修改請求或響應的 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 })
})

開啟網路面板觀察網路請求,響應檔頭裡面就有 Access-Control-Allow-Origin 了,成功繞過 cors 校驗:

請求轉發

通過 webRequest API,可以將發到介面 A 的請求轉發到介面 B。為了驗證這個能力,我們寫了一個 http 服務,同時監聽 3030 和 4040 埠,並響應 JSON 資料,裡面包含了 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' })
  },
)

在控制檯傳送 3030 埠請求,結果返回了 4040 埠的資料:

這個能力非常強大,例如可以做下面的事情:

  • 後端介面未部署之前,前端自己做本地介面 mock
  • 把某個頁面的 js 攔截掉,換成自己的 js 來偵錯
  • 故意請求一個不存在的地址,然後僅對授權使用者轉發到真實地址

以上就是Electron 網路攔截實戰範例詳解的詳細內容,更多關於Electron 網路攔截的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com