最近在開發的時候遇到了一個微信分享的bug,就是不管你在哪一個路徑下的頁面,發送給朋友後點開都只會跳到項目的首頁。原本微信分享這個只算是一個小功能,也很好解決,但因爲項目的特殊性,使得在這個bug解決起來並無那麼順手,因此記錄一下備之後翻閱。前端
Vue單頁面應用,前端經過Hash控制路由——iOS在微信中不能正常地改變瀏覽器的hash值,分享出去的頁面地址被莫名其妙地添加了參數。vue
微信的安全策略——因爲存在js安全域名限制,使得在本地調試更難。vue-router
jssdk配置簽名。後端
在傳統開發中,路由一般都是在後端完成的,可是在Vue單頁面中,都是經過控制history interface來控制頁面之間的跳轉,在咱們的項目中咱們使用hash的方式,可是在分享給朋友後卻發現分享地址被加上了一些參數,好比:api
我分享出去的地址是:market.lenkuntang.cn/#/home
,分享後會變成了market.lenkuntang.cn/?from=singlemessage#/home
。這到底會不會影響到咱們的分享操做呢?這就要了解vue-router的工做原理了,翻看了一下vue-router的源碼,發現以下代碼:瀏覽器
// this is delayed until the app mounts
// to avoid the hashchange listener being fired too early
setupListeners () {
const router = this.router
const expectScroll = router.options.scrollBehavior
const supportsScroll = supportsPushState && expectScroll
if (supportsScroll) {
setupScroll()
}
window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {
const current = this.current
if (!ensureSlash()) {
return
}
this.transitionTo(getHash(), route => {
if (supportsScroll) {
handleScroll(this.router, route, current, true)
}
if (!supportsPushState) {
replaceHash(route.fullPath)
}
})
})
}
複製代碼
hash.js安全
原來在vue-router初始化的時候,會監聽window
對象的hashchange
屬性,如想發現瀏覽器的hash
值發生變化了,就會調用History.transitionTo
方法,關鍵就在這個方法會傳入一個getHash
方法爲做參數,若是在這種地址market.lenkuntang.cn/?from=singlemessage#/home
也能正確地拿到正確的hash
的話,那咱們就能夠判定這種意外對咱們的分享是沒有影響的。當咱們繼續去看getHash
方法,在hash.js
往下翻點會找到這個方法的實現:bash
export function getHash (): string {
// We can't use window.location.hash here because it's not
// consistent across browsers - Firefox will pre-decode it!
const href = window.location.href
const index = href.indexOf('#')
return index === -1 ? '' : href.slice(index + 1)
}
複製代碼
咱們能夠清楚地知道,當這條地址market.lenkuntang.cn/?from=singlemessage#/home
通過getHash
以後會直接返回#
號後面的字符串,也就是 /home
,因此能夠得出是不會對咱們分享的功能有影響的。服務器
在Vue-router實現前端控制路由都是經過HTML5 新增的History Interface接口來控制頁面之間的跳轉的,在跳轉的同時經過修改window
中loaction
的hash
屬性反映回瀏覽器的地址,可是當遇到iOS時卻意外地發現這個hash
屬性一直沒有被改變,致使每次分享出去的地址都是首頁,在網上一查發現這原來是個通病,解決的方法就是引入微信的JsSDK來手動控制分享的地址。微信
在引入了JsSDK後,首先要對它進行配置,相關配置項以下:
wx.config({
debug: true, // 開啓調試模式,調用的全部api的返回值會在客戶端alert出來,若要查看傳入的參數,能夠在pc端打開,參數信息會經過log打出,僅在pc端時纔會打印。
appId: '', // 必填,公衆號的惟一標識
timestamp: , // 必填,生成簽名的時間戳
nonceStr: '', // 必填,生成簽名的隨機串
signature: '',// 必填,簽名
jsApiList: [] // 必填,須要使用的JS接口列表
});
複製代碼
說明一下這裏的參數分別從哪裏來,appId是從微信公衆號裏獲取的,timestamp
和nonceStr
還有signature
是從服務器中返回的。jsApiList能夠在全部JS接口列表中找到。
注:
timestamp
和nonceStr
實際上是能夠在前端生成而後傳給服務器再參與簽名的計算的,但通常在考慮到安全緣由,timestamp
,nonceStr
這些參數應該從服務器返回回來(由於它參與了簽名的計算)。
注意:這裏的傳入的隨機字符串字段
nonceStr
是駝峯命名!!!
而後就是引入JsSDK中遇到最大的問題——簽名問題,要正確地實現使用JsSDK,在服務器端首先要集齊這四種元素:
而後把這些元素按字典序(ASCII 碼從小到大排序)排後使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串,再對字符串進行sha1加密,字段名和字段值都採用原始值,不進行URL 轉義,便可獲得所謂的簽名。
注意:這裏的傳入的隨機字符串字段
noncestr
是全小寫!!!
最後附上簽名檢驗工具的地址:mp.weixin.qq.com/debug/cgi-b…
還有示例代碼:demo.open.weixin.qq.com/jssdk/sampl…
獲得簽名後再把timestamp
,nonceStr
和signature
傳回給前端進行JsSDK的初始化配置。
這裏再說說參與簽名的url,由於這裏傳過去的是當前見面的URL且不包括#及其後面部分,這對於使用Hash模式的單頁面應用來講是個好消息,這樣就表明咱們只須要在頁面加載時初始化一次後即可以在全部頁面上使用(對於傳統的路徑導航,由於URL變了因此要從新初始化,也就是說要在使用到的JsSDK功能的頁面中都要從新請求後臺接口拿簽名再初始化!!)。因此,通常來講咱們一般會在App.vue
這個文件中做JsSDK的初始化操做,當初始化正確後即可在其它頁面上直接使用JsSDK接口的功能。
次外,因爲微信存在對JsSDK的使用限定在微信公衆號裏所設置的JS接口安全域名範圍裏,因此對於本地調度用的localhost
域名來講是不可行的,直接提示invalid url domain
,在這裏有兩種方式能夠解決這個問題,一種是經過修改host
的方法來實現本地調試,方法以下:
進入系統盤目錄(一般是C盤): C:\Windows\System32\drivers\etc
,找到hosts
文件,打開後文件末尾添加一條記錄127.0.0.1 market.lenkuntang.cn
,這條記錄的意思是當你訪問market.lenkuntang.cn
這個地址的時候會重定向到127.0.0.1
這個ip地址,從而實現本地調試的目的。
打開一個finder,而後按快捷鍵command+shift+G,輸入private/etc/hosts
回車後就能找到對應的hosts文件,因爲是權限問題,是沒法直接在那個目錄中修改hosts文件的,因此要把文件複製到桌面或者其它有修改權限的目錄,而後打開後也是相似window同樣在文件末尾添加一條記錄127.0.0.1 market.lenkuntang.cn
,保存後拖回原目錄肯定覆蓋。
另外一種是使用騰訊雲的開發者實驗室的在線Web IDE來登陸到測試服務器,而後直接在服務器上進行修改,線上驗證。可是因爲這個Web IDE目前不支持SSH密鑰方式登陸,只能用帳號和密碼的方式登陸。因此也是有必定的侷限性的。
附上Web IDE工具地址:cloud.tencent.com/developer/l…
點擊其中一個教程,而後選擇開始上機下方的使用已有雲主機標籤,在彈出的登陸界面中正確填寫你服務器的IP地址和帳號密碼即可直接登入服務器內進行相關操做。
當咱們配置好了全部東西后,打開瀏覽器咱們能夠在控制檯的輸出中看到JsSDK的相關信息,可是咱們殊不知道是否能夠正確分享,難道咱們每次都要使用手機來訪問本地服務來驗證嗎?並且在使用手機來訪問本地服務的時候,使用的是本地電腦的ip地址,這樣去拿到簽名確定是不對,會報invalid url domain
錯誤,固然也能夠改手機的hosts
,可是這就不是那麼容易改了,安卓的話要root,蘋果的話...算了算了。仍是換種方法,這個時候咱們應該使用微信開發者工具來進行調試,微信開發者工具能夠模擬微信環境,能夠進行微信想着的操做,因此使用這個工具咱們就能夠愉快地在本地進行調試啦。
並且,在遇到須要微信登陸的頁面時,如何是用普通的瀏覽器來打開就會跳到微信的受權登陸頁,而用開發者工具來打開則會像手機同樣彈出受權頁:
經過這幾天對微信分享的研究,整體對微信的JsSDK的使用有了大概的認識和了解,雖然其中也遇到很多的坑和麻煩的地方,可是既然問題出現就只能儘可能地去簡化問題再解決它。