如何在本地開發環境除錯微信 JS-SDK

KentonYu發表於2018-05-20

以下篇幅將會描述不同前提下對應的除錯策略,當然也有可能不是最優解,望斧正 →_→


前言

何謂「安全域名限制」?

如何在本地開發環境除錯微信 JS-SDK

以微信 JS-SDK 的使用為例,每個公眾號被限制最多可設定三個安全域名,且必須能被騰訊伺服器所驗證(這意味著域名必須繫結在一臺可被外網訪問的伺服器上);然後只允許在這幾個域名下才能使用 JS-SDK,這就是安全域名限制。

這種策略應用還相對比較廣泛,大概可以等同於三方提供的 API 需要讓你配置 IP 白名單。

下圖大致描述了 JS-SDK 域名驗證的過程,其中

  • WeixinWebview 為微信客戶端內的瀏覽器;
  • BuServer 為我們自己的業務伺服器;
  • WeixinClient 為微信 App;

以下流程的前提是 BuServer 已經具有簽名所需的 access_token、jsapi_ticket 等資訊

如何在本地開發環境除錯微信 JS-SDK

建立在這個基礎上,我們想繞過這個安全策略,大概有兩種方案:

  1. 常規操作,將一個固定的域名作為測試專用,填入安全域名列表裡,佔掉一個坑「這邊當然可以專門申請個測試賬號」,然後通過解決內網穿透「ngrok、花生殼之流」便可以實現;
  2. 非常規操作,通過修改 DNS 解析實現,將特定資源「或所有資源」的請求重寫到本地開發服務上;

常規操作

  1. 通過 ngrok / 花生殼內網穿透,一般工具都會給你臨時域名,固定的域名需要付費;
  2. 將域名填入微信安全域名列表中,並將驗證檔案放入 Web 容器裡進行驗證;
  3. 完成了上面兩步,你就可以愉快的除錯啦;

非常規操作

從上文流程圖中可以看到 JS-SDK config 資訊是通過當前請求頁面的 URL + jsapi_ticket + appid + ...... 按照一定規則進行簽名得到的,然後將這個 config 傳入微信客戶端進行校驗是否合法。

整個驗證過程中,我們能 hack 的是將請求的資源轉發到開發伺服器上,從而能除錯本地的程式碼。

圍繞「將請求的資源轉發到開發伺服器」,可以想到下面兩個方案:

  1. 將請求攔截,轉發到開發伺服器上;
  2. 利用 DNS 解析,將安全域名解析到開發伺服器上「俗稱 DNS 劫持」;

方案一 抓包工具轉發

本文不過多贅述,可以通過 Charles,Fiddler 這些抓包工具對指定的請求進行轉發,從而達到目的。

方案二 DNS 劫持

可以先看下圖 DNS 解析過程:

如何在本地開發環境除錯微信 JS-SDK

要實現 DNS 劫持,最現實的是通過修改開發機的 hosts 檔案將安全域名解析到本地開發環境 ip 上。

HTTP 請求的劫持

如果你的網站提供的是 HTTP 服務,只需要修改開發機中 hosts 檔案,將安全域名指向開發服務。看到這裡就差不多了,可以自己去實踐了。

HTTPs 請求的劫持

但是目前大多數商業網站都 HTTPs 化了,因此並不能簡單的通過 DNS 劫持,把請求轉發到本地的 HTTP 服務上。

如果你的安全域名是一個 HTTPs 服務,那可能有點麻煩。首先我們來看看一次像 HTTPs Server 請求的時間線:

如何在本地開發環境除錯微信 JS-SDK

如上圖可以看到當像 HTTPs Server 發起一個 HTTP 請求時,將會被永久重定向成 HTTPs 請求,然後響應頭中會有一個特殊的頭「strict-transport-security」,這個頭是告知瀏覽器該域下的所有請求都將使用 HTTPs 訪問。因此接下來如果再發起一個 HTTP 的請求,瀏覽器將會內部重定向至 HTTPs 請求。

上文對 HTTPs 請求的描述是為了引出當你安全域名對應的是 HTTPs 服務時,會遇到如下問題:

  1. 將安全域名 DNS 劫持到本地 HTTP 服務後,在瀏覽器中訪問仍舊是 HTTPs 請求;
  2. 基於 1 ,我們想到清瀏覽器快取,但是微信開發者工具無法進入 chrome://net-internals/#hsts 清理;

Q1:以 Chrome 為例,進入 chrome://net-internals/#hsts,清除安全策略。

如何在本地開發環境除錯微信 JS-SDK

Q2:在微信開發者工具中,我們並不能進入這個頁面,也就意味著如果安全域名在該工具中有安全策略快取,則你無法將它劫持到一個 HTTP 服務,「這邊如果有什麼方案,可以告訴我」。

為了解決這個問題,我們只能引入終極解決方案,通過一個 HTTPs Server 對請求做一個轉發,具體流程如下:

如何在本地開發環境除錯微信 JS-SDK

ProxyServer 做了兩件事:

  • 配置了安全域名對應的 SSL 證書,支援了 HTTPs 請求;
  • 將安全域名下的請求轉發到對應開發服務上;

如果這個 ProxyServer 是作為一個通用服務存在,則需要考慮如何代理到不同開發者啟動的開發服務上。

最開始我們計劃通過 querystring 來制定需要代理到的開發服務的地址,實際情況是一個頁面中所有依賴該域下的請求都得轉發,因此 querystring 的方法不能很方便的實現這個功能。

因此最後通過 cookie 來實現這個需求,通過 cookie 指定開發伺服器地址,這樣該域下的所有資源請求都會帶上該 cookie,就能實現自定義轉發到上游服務了。

最終使用該方案除錯微信 JS-SDK 需要做如下兩步:

  1. 更改 hosts 檔案,將安全域名劫持到代理服務上;
  2. 設定 cookie ,指定需要代理到的上游服務;

這樣一來,該代理服務就可以作為通用服務所存在,任何開發者有繞過安全域名限制做一些除錯,都可以使用這個服務。

FAQ

Q1. 常規操作的優劣?

Pros:

  1. 步驟比較少,容易搞,適合偶爾需要除錯;

Cons:

  1. 固定域名要錢?啊,不固定域名又要經常改,但是一個月又只有三次修改機會啊;
  2. 微信安全域名池子沒坑怎麼辦啊。。。「申請個測試賬號也不是不行,但是這樣後端 access_token、jsapi_ticket 相關介面都得修改」;
  3. 不夠通用,其他三方登入有安全域名設定,並不能複用;

針對 Cons 1 有更優解,可以結合 DNS 劫持,在微信後臺繫結安全域名時使用花生殼驗證域名,然後其實不需要再使用花生殼了,可以修改 hosts,將驗證的域名劫持到本地開發服務,這樣既不用操心 HTTPs 也不用付費要固定域名。有興趣的小夥伴可以嘗試嘗試。

Q2. 非常規操作又有什麼優勢?

Pros:

  1. 不需要額外的域名,意味著不用改安全域名配置,服務端程式碼也不用動;
  2. 通用,有類似安全域名策略的三方服務通殺;
  3. 對於普通開發者來說日常開發除錯成本很低,也不需要什麼特殊許可權;

Cons:

  1. 搭建流程相對複雜點,需要伺服器資源;

Q3. 真機微信裡怎麼除錯啊?

祭出 Charles,Mac 用 Charles,Win 用 fiddler 開代理,如果是 HTTPs 則還需要配置證書信任,這個步驟本文不再贅述,可自行 Google。

Q4. 怎麼申請測試賬號?

mp.weixin.qq.com/debug/cgi-b…

小結

解決方案上,常規方案的額外成本較低,但是在多個開發者協同開發公眾號的情況下,綜合成本較高;非常規方案比較適合多個開發者需要除錯微信 JS-SDK,一勞永逸。

在整個過程中,其實可以瞭解到 DNS 劫持的概念、實際應用,以及對 HTTPs 的進一步瞭解。

最後,如果喜歡可以關注公眾號「茶杯蓋」

如何在本地開發環境除錯微信 JS-SDK

相關文章