坦率地说,它只是在v1.0中引起了太多的麻烦,因为它具有需要三个表单提交的功能,其中$_SESSION
会话数据包含所有中间内容 - 只是让用户启动操作,然后打开第二个选项卡并执行第二个操作,该操作会遍历会话数据。
我怀疑这是恶意的(但不能打折)。用户更有可能启动操作,中断,忘记他们已启动或无法找到原始选项卡,因此再次启动(然后再找到原始选项卡并尝试再次完成操作)。
由于我在PHP编码,我可以检测表单提交时会话数据的存在(如果用户打开另一个选项卡,我将如何使用JS?我想我需要Ajax - 对吧?)。
所以,每次我开始一个操作时,我会在会话数据中检查一个标志,如果设置我重新加载到“对不起,戴夫。我恐怕我不能那样做“页面,否则我设置标志并继续(记住在操作结束时清除它)。
我想那可行,但是:
1)将浏览器应用程序限制为单个选项卡/实例是否可以接受?
2)我应该尝试在v2.0中允许多个实例吗?
还有其他意见,帮助或建议吗?
答案 0 :(得分:5)
更好的设计是避免在会话中存储用户交互状态。将它放在隐藏的表单字段或其他内容中,以便每个客户端请求都带有与之关联的状态。如果您担心用户篡改它,请使用HMAC来防止它,并且如果它包含用户不应该看到的内容,则可能加密它。
仅表明应在标签之间共享 - 例如用户的登录标识或购物车之类的东西 - 应存储在会话中。
答案 1 :(得分:4)
最多可以在会话文件中保留“最后请求的页面”列表,并带有标志,指示如果用户是这些关键表单标志之一,则不应允许用户离开它。因此,如果您在form.php
并且它是no-move-off
,那么加载的任何新页面都应显示“中止或关闭窗口”选项。
您无法阻止用户打开其他标签/窗口,但您可以阻止他们在其他窗口/标签中移动到您网站的其他位置。
但是,请注意这是一个非常糟糕的用户体验。想象一下,如果亚马逊将您困在购物车页面中,并且从未让您进入另一页而无需实际购买。考虑更新代码以允许多个不同的窗口使用相同的表单。
答案 2 :(得分:2)
如果每个浏览器都支持选项卡式浏览,那么尝试将浏览限制为单个选项卡(那么您可能会创建一个桌面应用程序)将是一种糟糕的用户体验。
您可以解决此问题的一种方法是在表单中添加CSRF令牌(作为隐藏变量),并随请求一起提交。
有许多方法可以生成令牌,但基本上是你:
$_SESSION
<input type="hidden" name="{token name}"
value="{token value}" />
然后当表单提交时,请检查$_REQUEST['{token name}'] == $_SESSION[
{token name}]`。
如果该令牌不同,您知道它不是您最初生成的表单,因此可以忽略该请求,直到真实表单带有正确的令牌。
有一件事:如果攻击者能够弄清楚如何生成CSRF令牌,那么他们就可以伪造请求。
答案 3 :(得分:2)
登录后添加以下脚本(例如dashboard.php)
patch
在其余页面的标题中添加了以下脚本 - &#39; random_value&#39;来自该用户的数据库
<script>
$(document).ready(function()
{
$("a").attr("target", "");
if(typeof(Storage) !== "undefined")
{
sessionStorage.pagecount = 1;
var randomVal = Math.floor((Math.random() * 10000000) + 1);
window.name = randomVal;
var url = "url to update the value in db(say random_value)";
$.post(url, function (data, url)
{
});
}
else
{
var url = "url to remove random_value";
$.post(url, function (data, url)
{
sessionStorage.removeItem('pagecount');
sessionStorage.clear();
window.location = 'logout.php';
});
}
});
</script>
答案 4 :(得分:0)
如果我现在这样做,我可能会编写单页AngularJs应用程序(虽然任何形式的J都可以)。
启动时,在本地存储中查找标志。如果设置,拒绝启动,使用适当的消息,否则设置标志&amp;运行应用程序。
当然,恶意用户可以绕过它,因为它不是服务器端检查,但我会拒绝支持。