database - 当浏览器重新加载/返回时,如何防止再次写入数据库?

标签 database perl cgi idempotent

我正在组装一个写入数据库(Perl CGI 和 MySQL)的小型网络应用程序。 CGI 脚本从表单中获取一些信息并将其写入数据库。但是,我注意到,如果我在网络浏览器上点击“重新加载”或“返回”,它会再次将数据写入数据库。我不想要这个。

在这种情况下,防止数据被重写的最佳方法是什么?

最佳答案

不要使用 GET 请求进行修改!是 RESTful ;使用 POST(或 PUT)代替浏览器应该警告用户不要重新加载请求。在 POST/PUT 请求之后使用普通 GET 请求将 ( using HTTP redirection ) 重定向到收据页面,这样可以在不收到重新提交警告的情况下刷新页面。

编辑:

我假设用户以某种方式登录,因此您已经有了一些跟踪用户的方法,例如 session 或类似 session 。

在显示表单时,您可以制作一个时间戳(或随机哈希等),并将其存储为隐藏字段(除了反跨站点请求 token 外,我相信您已经准备好了),并在一个 session 变量中(安全地存储在您的服务器上),当您收到此表单的 POST/PUT 请求时,您检查时间戳是否与 session 中的时间戳相同。如果是,您将 session 中的时间戳设置为可变且难以猜测的东西(例如时间戳与一些 secret 字符串连接),然后您可以保存表单数据。如果现在有人重复请求,您将不会在 session 变量中找到相同的值并拒绝请求。

这样做的问题是,如果用户单击返回以更改某些内容,则表单无效,而且这可能有点苛刻,除非您要更新的是钱。因此,如果您遇到刷新并单击后退按钮的“愚蠢”用户的问题,因此不小心重新发布了某些内容,只需使用 POST 就会提醒他们不要这样做,而重定向会降低这种可能性。如果你有恶意用户的问题,你也应该使用时间戳,尽管它有时会使用户感到困惑,尽管如果用户故意一遍又一遍地发布相同的消息,你可能需要找到一种方法来禁止他们。使用 POST,有一个时间戳,甚至对整个数据库进行全面比较以检查重复的帖子,如果恶意用户只是编写一个脚本来加载表单并自动提交随机垃圾,则根本无济于事。 (但是跨站点请求保护使这变得更加困难)

关于database - 当浏览器重新加载/返回时,如何防止再次写入数据库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/305684/

相关文章:

java - 无论如何要创建一个没有预身份验证的 Oracle 数据库连接池吗?

javascript - 爬行受密码保护的弹出网站

php - 如何在 Laravel 中同时执行不同的查询

python - 高效的HDF5/PyTables布局,可在大张量上保存和操作

php - PHP中从Mysql结果向Solr V5添加多个文档的方法

perl - 在 perl 中为 hash 分配一个附加值

javascript - 使用javascript从python CGI返回图像

perl - "…/auto/List/Util/Util.so: undefined symbol: PL_stack_sp at …/XSLoader.pm"仅当在 Travis CI 上使用 CGI::Test _and_ 运行测试套件时

linux - AWS beanstalk cgi-bin 权限

java - 无法检索过程的元数据