我让用户使用他们提供的短代码访问 URL,例如example.com/ABCD。我正在运行 Node 并使用 node_redis 模块,尽管我认为这并不重要。生成唯一代码的安全方法是什么?
我可以随机生成一些东西并检查它是否在使用中,但是考虑到我对 redis 的调用的异步性质,它有可能在保存回 redis 之前在其他地方使用。
一些想法:
- 我不担心有限的命名空间,如果需要我可以扩展它,但很可能不会
- ...但是保持代码简短(易于在移动设备上输入)的目标意味着我希望保持命名空间较小,从而增加发生冲突的可能性。
- 我想我可以在内存中保留已用(或未用)代码的列表,这不是最糟糕的事情,但似乎是一个奇怪的举动。
- 我知道我可以让 redis 自动递增,但我不想使用数字(我不想连续)。
如果我不想将列表保存在内存中,我应该切换数据存储吗?我认为将列表保存在内存中是可以但不是很好的想法是否正确?
最佳答案
请参阅我 2013 年 7 月的回答:https://stackoverflow.com/a/17597649/1253312
为了安全起见,我会把它复制到这里:
实际上,我建议使用 Redis 来完成这项任务。它具有使此任务适合其使用的所有功能。最重要的是,它非常擅长在大列表中搜索值。
我们将创建两个列表,buffered_ids
和 used_ids
。 cronjob 将每 5 分钟(或您喜欢的任何时间间隔)运行一次,这将检查 buffered_ids
的长度并将其保持在 5000 以上的长度。当您需要使用一个 id 时,将其从 buffered_ids
中弹出并将其添加到 used_ids
。
Redis 有集合
,它们是集合中的唯一项。将其视为一个散列,其中键是唯一的,所有值都是“真”。
你的 cronjob,在 bash 中:
log(){ local x=$1 n=2 l=-1;if [ "$2" != "" ];then n=$x;x=$2;fi;while((x));do let l+=1 x/=n;done;echo $l; }
scale=`redis-cli SCARD used_ids`
scale=`log 16 $scale`
scale=$[ scale + 6]
while [ `redis-cli SCARD buffered_ids` -lt 5000 ]; do
uuid=`cat /dev/urandom | tr -cd "[:alnum:]" | head -c ${1:-$scale}`
if [ `redis-cli SISMEMBER used_ids $uuid` == 1]; then
continue
fi
redis-cli SADD buffered_ids $uuid
done
获取下一个 uid 用于您的应用程序(在伪代码中,因为您没有指定语言)
$uid = redis('SPOP buffered_ids');
redis('SADD used_ids ' . $uid);
编辑 实际上那里存在竞争条件。要安全地弹出一个值,请先将其添加到 used_ids,然后再将其从 buffered_ids 中删除。
$uid = redis('SRANDMEMBER buffered_ids');
redis('SADD used_ids ' . $uid);
redis('SREM buffered_ids ' . $uid);
关于javascript - redis 中唯一、安全的短代码(使用 Node ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23353879/