模拟拼夕夕短链微信落地页防封实现

601 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情

前言

Q: 实现微信落地页防封拢共分几步?

A: 三步

  • 提前在各oss厂商处上传处理路径参数的html,并设置oss路由解析规则
  • 后台接收前端传递的活动id与用户id
  • 调用短链服务生成短链地址, 将短链通过接口的形式返回给前端

参数解析html与oss相关配置

这里参数解析我们仅演示针对ua的判断及动态生成二维码的伪代码,oss相关配置以阿里云为例,这里我们以前端动态创建图片二维码来进行实现,真实情况有可能是前端通过一系列参数直接拼接地址,获取后台动态生成好的图片。

  • 已经上传到oss内的参数解析html ua判断与动态生成二维码
<script>
  var u = navigator.userAgent;
  var ua = navigator.userAgent.toLowerCase();
  
  // 判断是否在微信内置浏览器打开
  if(ua.match(/MicroMessenger/i) == "micromessenger"){
    createQrImage()
  } else {
  // 判断安卓
    if (u.indexOf("Android") > -1 || u.indexOf("Linux") > -1) {
      dosomething()
    // 判断iOS
    } else if (!!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)) {
      dosomething()
    }
  }
  // 生成二维码的伪代码
  function createQrImage () {
    let search = location.search
    根据返回的路径参数,拆分uid与activityId
    if(search) {
      let str = search.split('?')[1]
      let uid = str.split('=')[1]
      let activityId = str.split('=')[0]
      // 异步生成二维码base64
      doQr().then(res => {
        document.body.html = res
      })
    }
  }
  async function doQr () {...}
  function dosomething () {
    alert('nonono')
  }
</script>
  • oss内的相关配置

首先就是要配置静态页的规则,默认首页以及404页的处理,以及404之后的重定向 image.png 然后还需要配置允许跨域相关的处理

image.png

通过上面的两步,我们就已经完成了落地页的实现,通过基于代码的判断,动态创建html,很大程度上避免了机器扫描导致的域名拦截

用户id+活动id 生成图床地址

前端通过点击按钮触发接口调用,传递参数为uid及activityId

$('.btn').click(createUrl)
 function createUrl () {
    let activityId = '624EA4B'
    let uid = 'nYXbXL82L822f'
    fetch("https://zhen.juele.com/createUrl?activityId="+activityId+'&uid='+uid, {
      "headers": {
      },
      "mode": "cors",
      "credentials": "omit"
    }).then(res => res.json()).then(res => {
      document.body.innerHTML = res.data.url
    })
  }

后端接收参数,随机返回oss地址,为什么是随机返回呢,因为访问量大的情况下,即使通过短链,依然会有被拦截的风险,所以我们可以集成多个oss的服务,随机返回oss防封落地页地址+参数,这里我们依然通过伪代码的方式来呈现相关的内容

const express = require('express')
const app = express()
const port = 3000
// oss资源池
let ossurl = [
    'aa.oss',
    'bb.oss',
    'cc.oss',
    'dd.oss',
  ]
app.get('/createUrl', (req, res) => {
let activityId = req.query.activityId
    let uid =  req.query.uid
    // 随机拼接的oss资源地址
    let url = oss[Math.ceil(Math.random()*oss.length)] + ?"+activityId+'='+uid
    // 调用生成短链接口
   http.get('sort.cn', function (resp) {
    let rawData = '';//定义一个字符变量
    resp.on('data', (chunk) => { rawData += chunk; });

    resp.on('end', function (err) {
      if (!err) {
        let sortURL = rawData
        res.send(JSON.string({url: sortURL}))
      }
    })
  }) 
})

梳理总结

我们再梳理一下步骤

  • 首先我们需要准备的是多个oss对象存储实例,然后将我们的活动文件以index.html的名字进行上传
  • 在活动页获取参数,调后台接口
  • 接口中获取参数,从oss资源池生成长链【这里拼夕夕应该还有一步处理就是 针对同一用户同一活动,应该是做了一层缓存,之后会直接走命中的缓存而不再继续去随机生成长链】
  • 长链转短链 【这一步 应该也会做一层缓存,因为短链很可能也有一个池子】
  • 前端接收返回,页面进行展示

到这里我们的模拟落地页防封实现就已经结束了,真实的业务处理只会比现在还复杂,我们没有考虑到服务可用的情况,以及redis缓存的建立等等,但是作为模拟来说,上面的内容应该已经足够说清楚原理了。

这里我留一个课后作业

既然已经做了oss对象存储了,那为什么不将oss通过cdn进行托管,从而降低流量访问的费用呢?

tips: 通过cdn访问的流量费用要远远低于直接访问oss地址,一个叫cdn下行流量 大概在180/年/TB,oss的下行流量在6000/年/TB