小程序安全指南之如何禁止外部直接跳轉(zhuǎn)到小程序某頁(yè)面
背景
小程序也需要注意安全性。例如某些頁(yè)面是業(yè)務(wù)流程中的「第二步」、「第三步」,而非「第一步」。如果外部小程序、外部二維碼、鏈接直接跳轉(zhuǎn)到了我們小程序的「第二步」、「第三步」,可能有超出預(yù)期的事情發(fā)生。
針對(duì)外部跳轉(zhuǎn)到小程序「第二步」、「第三步」頁(yè)面的,我們應(yīng)該攔截掉,要么直接報(bào)錯(cuò):頁(yè)面來(lái)源非法,要么直接跳回首頁(yè)。
關(guān)鍵問(wèn)題在于,這種邏輯該怎么實(shí)現(xiàn)最優(yōu)雅呢?
一種不是很好的解決方案
如果你的業(yè)務(wù)流程采用了狀態(tài)機(jī)模型,并在后端存儲(chǔ)了狀態(tài),那么可以在每一個(gè)頁(yè)面onLoad時(shí),發(fā)送一個(gè)API請(qǐng)求,判斷當(dāng)前狀態(tài)和當(dāng)前頁(yè)面是否匹配,如果匹配,則正常訪問(wèn),如果不匹配,則跳回到狀態(tài)對(duì)應(yīng)的頁(yè)面。
這依賴(lài)于后端實(shí)現(xiàn),不太合適。
更好的解決方案
我們考慮純前端的實(shí)現(xiàn)。
問(wèn)題關(guān)鍵在于:我們要禁止外部直接跳轉(zhuǎn)到我們小程序的部分頁(yè)面。我們需要要區(qū)分:內(nèi)部跳轉(zhuǎn)、外部跳轉(zhuǎn)。
這部分頁(yè)面,只允許通過(guò)內(nèi)部跳轉(zhuǎn)API(wx.redirectTo
、wx.navigateTo
)來(lái)跳轉(zhuǎn),其它方式都不應(yīng)跳轉(zhuǎn)到。
只要我們?cè)谡{(diào)用wx.redirectTo
、wx.navigateTo
時(shí),都加上一個(gè)特殊參數(shù)
。然后在頁(yè)面的onLoad里面判斷,是否包含了該特殊參數(shù)
,包含該特殊參數(shù)
,表明是內(nèi)部跳轉(zhuǎn),不包含該特殊參數(shù)
,表明是外部跳轉(zhuǎn)。
這個(gè)特殊參數(shù)
不可以被猜到,如果被猜到了,那么外部跳轉(zhuǎn)時(shí)帶上特殊參數(shù)
,該方案就失效了。
所以,這個(gè)特殊參數(shù)
必須不是固定的,要是隨機(jī)的。
我們可以參考WEB中針對(duì)CSRF的解決方案,如果使用隨機(jī)的特殊參數(shù)
,讓外部無(wú)法猜到這個(gè)特殊參數(shù)
,那么問(wèn)題就解決了。
特殊參數(shù)
什么時(shí)候生成呢?可以在App onLaunch時(shí)生成,也可以在「第一步」頁(yè)面onLoad時(shí)生成。不過(guò)不論怎樣,這個(gè)特殊參數(shù)
都需要作為全局變量保存在內(nèi)存中,方便隨時(shí)引用和判斷。
具體怎么做?建議你先閱讀下文章:《如何全局重寫(xiě)小程序 Page函數(shù) wx對(duì)象?》,學(xué)會(huì)這種方法,我們?cè)賮?lái)看下方的代碼。
全局改寫(xiě)Page的onLoad生命周期,增加校驗(yàn)
const WHITE_LIST = ['pages/index']; function onLoadProxy(onLoad) { return function (query) { const app = getApp(); // 以下是token攔截邏輯: if (WHITE_LIST.includes(this.route)) { // 在允許外部跳轉(zhuǎn)來(lái)的白名單頁(yè)面,生成隨機(jī)數(shù)validEntranceToken app.validEntranceToken = `${new Date().getTime()}${Math.random().toString(36)}`; } else if (query.validEntranceToken !== app.validEntranceToken) { // 其它頁(yè)面,校驗(yàn)參數(shù)token是否與全局變量中token一致,若不一致,跳轉(zhuǎn)到報(bào)錯(cuò)頁(yè)面 wx.redirectTo({ url: `/pages/fail` }); return; } // 未被攔截,表明是正常來(lái)源。以下是正常流程: if (onLoad) { return onLoad.call(this, query); } }; } const PageProxy = (Page) => function (options) { const newOptions = { ...options, onLoad: onLoadProxy(options.onLoad), }; Page(newOptions); }; Page = PageProxy(Page);
全局改寫(xiě)wx.navigateTo方法,附帶參數(shù)
function addValidEntranceToken(url) { const app = getApp(); const symbol = url.includes('?') ? '&' : '?'; return `${url}${symbol}validEntranceToken=${app.validEntranceToken}`; } export function redirectToProxy(redirectTo) { return function (object) { return redirectTo({ ...object, url: addValidEntranceToken(object.url), }); }; } function wxProxy(wx) { const newWx = { ...wx }; newWx.navigateTo = redirectToProxy(wx.navigateTo); newWx.redirectTo = redirectToProxy(wx.redirectTo); return newWx; } wx = wxProxy(wx);
解釋
我們通過(guò)修改所有Page的onLoad方法,當(dāng)用戶(hù)訪問(wèn)「白名單」頁(yè)面時(shí),不會(huì)做任何攔截,而是直接生成一個(gè)隨機(jī)的validEntranceToken
。當(dāng)用戶(hù)訪問(wèn)「白名單」以外的頁(yè)面時(shí),則會(huì)判斷參數(shù)中是否包含正確的validEntranceToken
,若不包含,則會(huì)跳轉(zhuǎn)到報(bào)錯(cuò)頁(yè)。若包含,則繼續(xù)執(zhí)行該頁(yè)面的其它邏輯。
此外,我們還修改了原生的wx.navigateTo
和wx.redirectTo
,當(dāng)我們做內(nèi)部跳轉(zhuǎn)時(shí),會(huì)自動(dòng)帶上剛才提到的參數(shù)validEntranceToken
。
做好這些事情后,開(kāi)發(fā)時(shí),無(wú)需關(guān)心細(xì)節(jié)(意思是這套邏輯針對(duì)業(yè)務(wù)代碼是0侵入的),只需要關(guān)注「白名單」頁(yè)面有哪些即可??芍^是最優(yōu)雅的方案了。
總結(jié)
到此這篇關(guān)于小程序安全指南之如何禁止外部直接跳轉(zhuǎn)到小程序某頁(yè)面的文章就介紹到這了,更多相關(guān)小程序禁止外部直接跳轉(zhuǎn)某頁(yè)面內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
layui實(shí)現(xiàn)登陸界面驗(yàn)證碼
這篇文章主要為大家詳細(xì)介紹了layui實(shí)現(xiàn)登陸界面驗(yàn)證碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11小程序卡片切換效果組件wxCardSwiper的實(shí)現(xiàn)
這篇文章主要介紹了小程序卡片切換效果組件wxCardSwiper的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02uniapp使用scroll-view實(shí)現(xiàn)左右上下滑動(dòng)功能
最近在用uni-app開(kāi)發(fā)小程序時(shí),需要用scroll-view做出左右上下滑動(dòng)效果,所以下面這篇文章主要給大家介紹了關(guān)于uniapp使用scroll-view實(shí)現(xiàn)左右上下滑動(dòng)功能的相關(guān)資料,需要的朋友可以參考下2022-11-11基于JS實(shí)現(xiàn)簡(jiǎn)單的3D立方體自動(dòng)旋轉(zhuǎn)
這篇文章主要為大家詳細(xì)介紹了如何利用JavaScript實(shí)現(xiàn)簡(jiǎn)單的3D立方體自動(dòng)旋轉(zhuǎn)的效果,文中的實(shí)現(xiàn)代碼講解詳細(xì),感興趣的可以嘗試一下2022-06-06javascript實(shí)現(xiàn)繼承的簡(jiǎn)單實(shí)例
這篇文章主要介紹了javascript實(shí)現(xiàn)繼承的簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2015-07-07封裝好的省市地區(qū)聯(lián)動(dòng)控件附下載
封裝好的省市地區(qū)聯(lián)動(dòng)控件附下載...2007-08-08符合W3C網(wǎng)頁(yè)標(biāo)準(zhǔn)的iframe標(biāo)簽的使用方法
符合W3C網(wǎng)頁(yè)標(biāo)準(zhǔn)的iframe標(biāo)簽的使用方法...2007-07-07