趣谈唯一邀请码生成方法 您所在的位置:网站首页 怎么破解论坛的邀请码信息 趣谈唯一邀请码生成方法

趣谈唯一邀请码生成方法

2024-03-07 02:36| 来源: 网络整理| 查看: 265

趣谈唯一邀请码生成方法

前段时间项目上需要生成唯一邀请码!嘿嘿,多简单的一件事,心里就已默默将代码写了一遍。但小小的邀请码生成却也小有乾坤,这就是后话了。

一、最简单的实现

很多人 肯定都和我一开始一样!嘿嘿,这还不简单,26个字母+10个数字,去掉容易混淆的,O、0、I、1等字符就剩下32个,

/** * 随机字符串 */ private static final char[] CHARS = new char[] {'F', 'L', 'G', 'W', '5', 'X', 'C', '3', '9', 'Z', 'M', '6', '7', 'Y', 'R', 'T', '2', 'H', 'S', '8', 'D', 'V', 'E', 'J', '4', 'K', 'Q', 'P', 'U', 'A', 'N', 'B'};

然后再生成随机的六个重复的数字,对应着CHARS中的数字下标,邀请码生成搞定

Random random = new Random(); List list = random.ints(0,32) .distinct().limit(6).boxed().map(t -> CHARS[t]).reduce().collect(toList());

好啦,邀请码生成好了。你还要不重复是吧,OK!没问题,我们把邀请码保存到缓存里面,例如redis。每次新生成的邀请码都先去缓存判断下是否存在,如果已经存在则再生成一个,直到找到合适的。 功能完成。喝下午茶去。。。。

思考 :这种实现是否真的最佳实现了呢? 至少存在以下一些问题

唯一性判断需要通过缓存,引入第三方组件,并且消耗内存资源 在99.999%的情况下,缓存判断是否存在都是 FALSE 的,可以说是一种浪费 用户与邀请码的对应关系需要记录,如果数据库查询的话,至少需要在邀请码字段上加个索引,又是要消耗资源

那么我们有其它办法来解这个问题吗?

二、数学和密码学来实现

前提 :存在唯一的标识,例如给用户生成邀请码,那么用户id就是唯一标识(id在任何情况下都不会重复)。

那么我们首先想到的是根据唯一的id,是使用算法来生成。

/** * 生成邀请码 * * @param id 唯一的id主键 * @return code */ String gen(Long id) { //进行补位 id = id * PRIME1 + SLAT; //将 id 转换成32进制的值 long[] b = new long[CODE_LENGTH]; //32进制数 b[0] = id; for (int i = 0; i < CODE_LENGTH-1; i++) { b[i + 1] = b[i] / CHARS_LENGTH; b[i] = b[i] % CHARS_LENGTH; } b[5] = (b[2] + b[3] + b[4]) * PRIME1 % CHARS_LENGTH; StringBuilder buffer = new StringBuilder(); Arrays.stream(b).boxed().map(Long::intValue).map(t -> CHARS[t]).forEach(buffer::append); return buffer.toString(); }

大概就是像上面代码一样,先将id扩大,然后再转换成32进制的数。为啥是32进制呢,因为 CHARS 里面是32个char,那么32进制正好对应 CHARS 的下标。

好了,基于算法根据id来生成邀请码就完成了。然后再逆向下算法,就可以根据邀请码来还原成用户id,找到是哪个用户的了。

YEAH、YEAH!任务完成

然后代码一运行

public static void main(String [] args){ for(long id=10000L;id CHARS[t]).forEach(buffer::append); return buffer.toString(); }

这样我们就能对连续id生成差异化的邀请码了。

public static void main(String [] args){ for(long id=10000L;id CHARS[t]).forEach(buffer::append); return buffer.toString(); } /** * 将邀请码解密成原来的id * * @param code 邀请码 * @return id */ public static Long decode(String code) { if (code.length() != CODE_LENGTH) { return null; } // 将字符还原成对应数字 long[] a = new long[CODE_LENGTH]; for (int i = 0; i < CODE_LENGTH; i++) { char c = code.charAt(i); int index = findIndex(c); if (index == -1) { // 异常字符串 return null; } a[i * PRIME2 % CODE_LENGTH] = index; } long[] b = new long[CODE_LENGTH]; for (int i = CODE_LENGTH - 2; i >= 0; i--) { b[i] = (a[i] - a[0] * i + CHARS_LENGTH * i) % CHARS_LENGTH; } long res = 0; for (int i = CODE_LENGTH - 2; i >= 0; i--) { res += b[i]; res *= (i > 0 ? CHARS_LENGTH : 1); } return (res - SLAT) / PRIME1; } /** * 查找对应字符的index * * @param c 字符 * @return index */ private static int findIndex(char c) { for (int i = 0; i < CHARS_LENGTH; i++) { if (CHARS[i] == c) { return i; } } return -1; } }

原文:https://my.oschina.net/bravozu/blog/1827254 作者: BravoZu



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有