素材牛VIP会员
求教url访问一次就失效的设计方法
 L***灬  分类:PHP代码  人气:1269  回帖:10  发布于6年前 收藏

比如说类似下面这种url:

https://foo.com/?timestamp=时间&nonce=随机串&sign=签名

我能想到的方法有以下几种:
1、存数据库:首次访问,把该url存库,第二次访问,查库;
2、存session,先存,后查;
3、存redis、mencache等,先存,后查;
以上几种方法虽然能够达到要求,但是每次都得先存再查,数据量小还好,如果有上千万、上亿条数据呢?也这么查吗?有没有好的解决办法?

我正在考虑能不能根据url的规则设计一个算法来对url进行是否访问过的验证,就算存数据也只存少许数据,而不用存整个url。

 标签:服务器架构php

讨论这个帖子(10)垃圾回帖将一律封号处理……

Lv6 码匠
轩***室 学生 6年前#1

通过timestamp来做就好办很多了, 一般timestamp超过一定范围就当做是无效url, 所以nonce入库或者redis, 一段时间后失效就好,因为会先用timestamp判断这个请求是否过期, 再用nonce来判断是否重复请求., timestamp范围30秒左右基本上是够用了的

Lv6 码匠
西***护 UI设计师 6年前#2

不管用上面方法存储, 服务器不存储怎么可能做的到

Lv1 新人
ke***69 PHP开发工程师 6年前#3

毫秒级时间戳加随机字符串HASH值作为key有效时间缓存任意内容(简单即可如1),先时间戳判断有效时间,再验证该缓存是否存在,这两参数必传

Lv5 码农
15***75 技术总监 6年前#4

url本身没有变化, 那服务器端总得有什么东西变化
所以若要严格保证1次, 保存这件事感觉是逃不掉的

你现在这个就不用存整个url,存nonce就可以

Lv4 码徒
54***66 学生 6年前#5

访问过之后写个cookie

Lv5 码农
ga***et 移动开发工程师 6年前#6

不需要整个url,其实说穿了就是访问你的网页需要凭密码,而且密码只能用一次。
你自己设想的方法中,session不是全局的,所以用不了,只有数据库或者redis两种选择。

实在是无法理解为什么要让url失效...

Lv4 码徒
贼***9 CEO 6年前#7

加临时令牌不行??

Lv5 码农
隔***陈 学生 6年前#8

你主要不是纠结数据量的问题吗?
那么,为!什!么! 不用COOKIE, 将数据保存在用户本地终端

Lv4 码徒
贰***兄 页面重构设计 6年前#9

你总是要在后台存储“url是否访问过”这个信息的,这一点跑不了,凭算法手段无法消灭这个问题。

但这个需求的容易之处在于:请求与请求之间是没有联系的,你可以用任意的方法去分表、分库。例如以URL作为分桶依据(注),直接把数据库请求分散到数据库集群中。上千万上亿也是能做到的。

这个需求的真正困难之处在于原子性,即两个请求同时到达服务器时,如何抵抗两个事务同时操作数据库的时间差,造成的数据不一致。

不过这一点的解决也可以靠分表+数据库的锁机制实现。分表分库在这里更是同时承担了(1)分担请求数量压力(2)分担加锁带来的性能压力两个作用。


注1:当然实务上,要先对URL要做一下规范化,避免?v1=1&v2=2?v2=2&v1=1被判定为不同的URL等乌龙情况发生。

注2:实际上根据业务逻辑,用单次有效的索引字符串/token/nonce key(不管叫啥了,随你喜欢)做key才是最好的,省的处理URL的麻烦。

注3:一般而言数据库集群套件,会自动承担平摊分桶的算法,无需手工编写。

Lv6 码匠
bo***18 产品经理 6年前#10

随机串取长一点儿。URL有有效时间,然后存储那些 URL 有效。可以存储在数据库,定时+访问过后清理数据库。
一般的注册用户邮箱验证/修改密码就是这样的。
从概率上来说,未获得合法 随机数和 sign 的恶意攻击者在有效时间内是遍历不出所有可能的。如果再加一些IP尝试次数限制,这样做就很安全了。

如果你不是要验证,一个URL 可以访问最多一次的话 nonce 设为一个递增的数吧。

 文明上网,理性发言!   😉 阿里云幸运券,戳我领取