好烦啊,为什么点个链接还让我确认一下?

lxf2023-03-18 17:45:02

万丈苍穹水更深,无限乾坤尽眼中

背景

最近经常看到各大SNS平台有这样一项功能,点击跳转链接,如果不是本站的链接,那么就会跳转到一个中转页,告诉你跳转了一个非本站链接,提醒你注意账号财产安全,如图:

好烦啊,为什么点个链接还让我确认一下?

很明显,这个是为了一定程度的避免用户被钓鱼,预防XSS或CRSF攻击,所以请不要像标题一样抱怨,多点一下也花不了2S时间。

原理

那么这个是如何实现的呢,原理其实很简单。

a标签的onclick事件可以被拦截,当返回false时不会默认跳转。

那么具体如何实现呢,拿AdminJS来举例:

        function SetSafeA(whiteDomList: string[], safeLink = 'https://link.Admin.net/?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
            }
          })
        }

可以随便找一个网页在控制台执行一下,都能跳到AdminJS的中转页,中转页的代码就不写了^_^

实践

刚好最近遇到一个使用场景,公司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,希望使用的人保持一颗爱好和平的心;当然遇到让你确认安全的链接时,也请你保持一颗感谢的心。