多次提交禁止重复提交Redis篡改不可取(redis禁止同一个id)
多次提交禁止重复提交:Redis篡改不可取
随着互联网时代的到来,Web 应用程序的开发成为越来越普及的技能之一。在开发这些应用程序时,有时需要通过表单提交数据。在使用表单提交数据时,重复提交是一个必须要谨慎处理的问题。
一些开发人员可能会使用 Redis 等缓存工具来解决这个问题。然而,当涉及到多次提交禁止重复提交时,Redis 被篡改的风险非常高。为了防止 Redis 篡改,开发人员需要采用其他解决方案。
多次提交禁止重复提交的原因
多次提交禁止重复提交的主要原因是避免重复提交。例如,考虑一个在线购物应用程序。用户点击“提交”按钮来确认他们的订单。如果用户在等待页面加入购物车后多次单击“提交”按钮,则可能会出现多个相同的订单。这将导致用户不必要的麻烦,并严重影响客户体验。在这种情况下,多次提交禁止重复提交是必要的。
解决方法
在处理多次提交禁止重复提交问题时,一些开发人员可能会考虑使用 Redis 等缓存工具来存储数据。这种方法会在第一次提交后将数据存储在缓存中。如果同一用户再次提交相同的数据,则该数据将被 Redis 拒绝。虽然这种方法可以防止重复提交,但存在重大隐患。Redis 篡改是一个相对容易的攻击方法,因为 Redis 数据既可以在内存中,也可以在磁盘上。读者可以参考以下代码:
String orderNo = getOrderNo();
if(redisService.set(orderNo,1,"nx","ex",60L)){//设置成功,标识15s内未重复提交 return ResponseEntity.ok(orderNo);//返回订单号
}else{ return ResponseEntity.ok("重复提交");//重复提交
}
上述代码操作流程为,使用 Redis 的 set 方法设置订单号 orderNo ,每张订单的标识唯一,有效时间 60 秒。设置成功则表示未重复提交过,即用户提交的订单未存在于 Redis 中,否则表示重复提交。
如此一来,攻击者可以轻松地修改 Redis 数据(这很容易在某些无屏幕服务器上实现),并导致应用程序接受错误数据。破坏文件权限、修改配置文件、授予权限等攻击行为都可以实现 Redis 的篡改。
替代方案
由于 Redis 不是一个有效的解决方案,开发人员需要采用其他方法来解决多次提交禁止重复提交问题。以下是一些推荐的解决方案。
1.令牌桶限流器
令牌桶限流器是一种流控技术。它适用于控制访问速度和强制实现最大并发数量。
public class RateLimiter {
private long lastTime = System.currentTimeMillis(); private long gapMs;
private long leftCount;
public RateLimiter(long gapMs, long countPerGap) { this.gapMs = gapMs;
this.leftCount = countPerGap; }
public synchronized boolean tryAcquire() { long now = System.currentTimeMillis();
if (now - lastTime > gapMs) { lastTime = now;
leftCount = gapMs; }
if (leftCount > 0) { // 获得令牌
leftCount--; return true;
} else { // 没有获得令牌
return false; }
}}
上述代码中的 RateLimiter 类采用令牌桶限流,以在特定时间段内对请求进行限制。在该实现中,每个用户都只能在特定时间段内提交一定数量的请求,从而防止重复提交。
2.加密常量隐藏字段
常量隐藏字段式一种 Web 安全技术,可以将表单数据与预定义的常量配对。通过这种方法,您可以在 Web 应用程序中进行数据验证,以确保表单数据的一致性。
例如:
上述代码中,表单包含一个隐藏的值为 token 的字段。此token通常由应用程序生成,用于防止重复提交。如果将此token与每个提交的表单数据一起使用,则您可以从攻击者那里保护自己的 Web 应用程序。
结论
在开发 Web 应用程序时,多次提交禁止重复提交是一个必须仔细处理的问题。可惜的是,Redis 等缓存工具不是一个可行的解决方案。替代方案可能包括令牌桶限流器和常量隐藏字段,以防止重复提交和保护 Web 应用程序的安全。