好烦啊,为什么点个链接还让我确认一下?
万丈苍穹水更深,无限乾坤尽眼中
背景
最近经常看到各大SNS平台有这样一项功能,点击跳转链接,如果不是本站的链接,那么就会跳转到一个中转页,告诉你跳转了一个非本站链接,提醒你注意账号财产安全,如图:
很明显,这个是为了一定程度的避免用户被钓鱼,预防XSS或CRSF攻击,所以请不要像标题一样抱怨,多点一下也花不了2S时间。
原理
那么这个是如何实现的呢,原理其实很简单。
a标签的onclick事件可以被拦截,当返回false时不会默认跳转。
那么具体如何实现呢,拿掘金来举例:
function SetSafeA(whiteDomList: string[], safeLink = 'https://link.juejin.cn/?target=') {
const aArr = document.getElementsByTagName('a')
Array.from(aArr).forEach(item=>{
item.onclick = () => {
let target = item.getAttribute('href')!
if(/^\//.test(target)) {
// 相对本站链接
return true
}
const isSafe = undefined !== whiteDomList.find(item=>{
return target.indexOf(item) !== -1
})
if(!isSafe) {
window.open(`${safeLink}${target}`, '_blank')
} else {
return true
}
return false
}
})
}
可以随便找一个网页在控制台执行一下,都能跳到掘金的中转页,中转页的代码就不写了^_^
实践
刚好最近遇到一个使用场景,公司APP产品里面都有各自用户协议,其中SDK协议我们都是直接跳转链接的,结果在部分渠道如小天才,步步高等对用户信息非常敏感的平台上,要求所有的链接必须要跳转到平台默认的安全浏览器上,不能在APP内打开。那么协议有很多如何快速处理呢。由于项目用到了vue,这里就想到使用指令,通过批量添加指令来达到快速替换,比如'<a' =>'<a v-link="x"',代码如下:
Vue.directive('outlink', {
bind: (el, binding) => {
el.outlink = () => {
if (GetEnv() === 'app') {
const from = isNaN(+binding.value) ? 1 : +binding.value
const url = el.getAttribute('href')
if (url && url !== '' && url != 'javascript:;') {
window.location.href = `${GetSchemeByFrom(from)}://outside_webview?url=${url}`
}
return false
}
}
el.onclick = el.outlink
},
unbind: (el) => {
el.onclick = null
delete el.outlink
}
})
这里我们传入了from值来区分APP平台,然后调用APP提供的相应scheme跳转到客户端的默认浏览器,如下:
结语
链接拦截可以做好事,也可以做一些hack,希望使用的人保持一颗爱好和平的心;当然遇到让你确认安全的
作者:CodePlayer
来源:juejin.cn/post/7161712791089315877
链接时,也请你保持一颗感谢的心。来源:juejin.cn/post/7161712791089315877