Rails APP 页面分享口令 Rails 实现

lanzhiheng · 2022年06月29日 · 最后由 lanzhiheng 回复于 2022年07月01日 · 354 次阅读

最近都比较少写技术文章,今天写一篇简单的总结。 原文链接:https://step-by-step.tech/posts/command-for-app-in-rails

前言

最近回流 APP 准备做页面分享的功能,然而 APP 跟网页不同。几乎所有设备都有浏览器(哪怕是 kindle),只要分享相应的 URL,其他人都能够打开你所分享的网页。然而 APP 不一样,如果用户没有下载你的 APP,就永远都无法使用该 APP 里面的功能。分享更是无从谈起。

如果用户已经下载了你的 APP,那么最直接分享页面的做法就是,告诉那个 APP 你要分享的页面路径,当它接收到这串东西时则可以跳转到对应页面,以达到分享的目的。口令是较为常见的分享方式,淘宝,抖音这类平台经常以此方式传播他们的数据。这篇文章简单总结一下,回流平台是如何制作这种口令的。

步骤

先来简单讲讲口令的使用步骤。

  1. 分享者创建口令,并把口令记录到粘贴板。
  2. 把口令复制给你要分享的人。
  3. 对象用户拷贝口令,并打开对应的 APP。
  4. APP 读取对象用户粘贴板的内容,解析口令,然后跳转到对应的页面。

这篇文章重点讲解步骤 1,4 中的创建口令以及解析口令,两个阶段。

口令的创建与解析

在讲如何创建口令之前先来看看,常见的口令是啥样子的

拜托帮我点一下!双11狂欢节非常赞!我有一张【金稻旗舰店】20元限量优惠券送给你,快来看看!】,復zんíゞ整句话¥aUKYOA¥后咑閞?淘灬寳?
1.

几乎不知道它在说什么对吧,而 APP 要跳转的路径大概是长这个样子的

/BidderGoodsDetailPage?id=999

似乎没见过哪个厂家会把自家 APP 的跳转路径明文放在口令里面。这应该涉及一个 “加密” 与 “解密” 的过程。我简单琢磨了两种做法。这边先假定回流的口令大概长这样

回流直播看货!成为推荐人!我发现一件不错的货品【翡翠挂件一手2件一起走 个别有纹 s925印记】,復zんíゞ整句话¥###¥后咑閞?huí灬琉?

其中###是占位符。原理大概是分享者的 APP 通过对当前路径编码得到一串不可名状的编码串并替换占位符的内容,进而得到一串完整的口令。而目标对象的 APP 则通过提取占位符的内容,解码后获得对应的路径,然后进行跳转。关于编码与解码我这里想到两个简单的方案,便用 Rails 来简单实现了。

省事儿的做法

一件较为省事儿的做法是直接对路径进行 Base64 编码,这样生成的 “密文” 也是有模有样。

a. 口令生成

首先实现口令生成的代码。

def generate_command(string, title)
  result = Base64.strict_encode64(string)
  "回流直播看货!成为推荐人!我发现一件不错的货品【#{title}】,復zんíゞ整句话¥#{result}¥后咑閞?huí灬琉?"
end

那么生成的口令就是

> generate_command('/BidderGoodsDetailPage?id=999', '翡翠挂件一手2件一起走 个别有纹 s925印记')
=> "回流直播看货!成为推荐人!我发现一件不错的货品【翡翠挂件一手2件一起走 个别有纹 s925印记】,復zんíゞ整句话¥L0JpZGRlckdvb2RzRGV0YWlsUGFnZT9pZD05OTk=¥后咑閞?huí灬琉?"

这串玩意看起来有点那个味道了,当别人拿到这串东西的时候需要对口令进行解析。

b. 口令解析

口令解析的过程也很简单,两个夹着的字符串才是关键信息,其余部分其实并不影响大局。故而,最终解析的时候我们只需要提取两个夹着的部分就可以了。解析脚本如下

def parse_command(string)
  key_string = string.split('¥')[1]
  Base64.strict_decode64(key_string)
end

运行看看效果

> parse_command('回流直播看货!成为推荐人!我发现一件不错的货品【翡翠挂件一手2件一起走个别有纹 s925 印记】,復zんíゞ整句话¥L0JpZGRlckdvb2RzRGV0YWlsUGFnZT9pZD05OTk=¥后咑閞?huí灬琉?')
=> "/BidderGoodsDetailPage?id=999"

结果还是可以的,当链接分享给别人的时候,他们也可以通过这个方法,解析口令,并获取跳转路径,并跳转到对应页面中去。

这个方案直接利用 Base64 的编码/解码过程来对路径进行处理,好处便在于实现起来十分简便。然而呢,美中不足的地方有二

  1. Base64 编码是可逆的,别人知道了这种编码规则之后依旧可以解析出目标路径(虽然很少人这样做)。
  2. 当需要编码的字符串越长的时候,Base64 编码串也会更长,影响美观。

下面来介绍一种稍微麻烦一点的方案,一并解决上述两个美中不足的地方。

稍微麻烦点的做法

这种稍微麻烦一点的做法需要借助 Redis,采用 Redis 的键值对机制来存储路径,键是唯一的,可以直接拼接进口令中,在网络间传输。

a. 口令生成

REDIS_CLIENT = Redis.new(host: 'localhost', port: 6379, db: 1)

HUILIU_COMMAND_KEYS = 'HUILIU_COMMAND_KEYS'
HUILIU_COMMAND_MAP = 'HUILIU_COMMAND_MAP'

# key生成器
def key_generator
  num = REDIS_CLIENT.incr(HUILIU_COMMAND_KEYS) # 利用redis的自增机制来规避重复问题
  number = num.to_s.rjust(7, '0') # 1 => '0000001' 等宽,保证在一定范围内,键的长度都不变。
  Base64.strict_encode64(number) # 对上面生成的字符串数值进行编码 '0000001' => 'MDAwMDAwMQ==',B格会高一些
end

def generate_command(string, title)
  key = key_generator
  REDIS_CLIENT.hset(HUILIU_COMMAND_MAP, key, string) # 直接以键值对的形式存储
  "回流直播看货!成为推荐人!我发现一件不错的货品【#{title}】,復zんíゞ整句话¥#{key}¥后咑閞?huí灬琉?"
end

这样生成的口令就更短了

> generate_command('/BidderGoodsDetailPage?id=999', '翡翠挂件一手2件一起走个别有纹 s925印记')
=> "回流直播看货!成为推荐人!我发现一件不错的货品【翡翠挂件一手2件一起走 个别有纹 s925印记】,復zんíゞ整句话¥MDAwMDAxMw==¥后咑閞?huí灬琉?"

而且这样看起来逼格更高一些,而且保密性更强,解析特定的口令只会得到对应的键,如果不访问内部的数据库,完全无法得知跳转路径是什么样子的。

b. 口令解析

其实这种方案的口令解析的过程更简单,直接访问数据库就是了

def parse_command(string)
  key_string = string.split('¥')[1]
  REDIS_CLIENT.hget(HUILIU_COMMAND_MAP, key_string) # 直接访问对应的数据库
end

运行结果

> parse_command('回流直播看货!成为推荐人!我发现一件不错的货品【翡翠挂件一手2件一起走 个别有纹 s925印记】,復zんíゞ整句话¥MDAwMDAxMw==¥后咑閞?huí灬琉?')
=> "/BidderGoodsDetailPage?id=999"

这种方案需要借助 Redis 数据库来生成对应的键,稍微麻烦一些。然而生成的指令会更短,利用等宽技术,编码后的键长度波动较小,B 格会更高一些。

总结

为了提高自家 APP 页面的传播度,越来越多厂商采用口令的做法。不得不说效果还是挺可观的。这里简单分享了一下,笔者在项目中采用的做法。一种只需要利用简单的编码机制,实现方便依赖性少,然而保密性差,了解算法之后能够很容易得到跳转路径的值。另一种需要稍微依赖数据库,实现稍微麻烦一丢丢,然而保密性强一些,解析后也只能获得对应的键,口令较短,B 格更高一些。我个人更喜欢第二种,不知道您的意见如何?

以前了解淘口令的实现,将 10 进制的 ID 转换成 62 进制结果,再借助 Redis 可以更短。

jijin 回复

我好像也看过那篇文章。不过我没找到 Rails 里面已有的生成 62 进制的方法。于是就直接用 Base64 来做的。感觉大同小异。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号