如何将我的应用程序限制为单个浏览器选项卡?

发布于 2024-12-11 06:39:22 字数 509 浏览 0 评论 0原文

坦率地说,在 v1.0 中拥有需要三个表单提交的功能,并且 $_SESSION 会话数据保存所有中间内容,只是为了让用户启动一个操作,这会带来太多麻烦,然后打开第二个选项卡并执行第二个操作,该操作会破坏会话数据。

我怀疑这是恶意的(但不能否认)。更有可能的是,用户开始一项操作,被中断,忘记他们已开始或找不到原始选项卡,因此再次开始(然后找到原始选项卡并尝试再次完成操作)。

由于我用 PHP 编码,我可以检测表单提交时会话数据的存在(如果用户打开另一个选项卡,我将如何使用 JS 来做到这一点 - 我想我需要 Ajax - 对吧?)。

因此,每次开始操作时,我都会检查会话数据中的标志,如果设置了,我会重新加载为“对不起,戴夫。恐怕我不能这样做”页面,否则我设置标志并继续(记住在操作结束时清除它)。

我想这会起作用,但是:
1) 将浏览器应用程序限制为单个选项卡/实例是否可以接受?
2) 我应该尝试在 v2.0 中允许多个实例吗?

还有其他意见、帮助或建议吗?

Frankly, it's just causing too much hassle in in v1.0 to have a functionality which requires three form submissions, with $_SESSION session data holding all of the intermediate stuff - only to have a user start an operation, then open a second tab and perform a second operation which tramples over the session data.

I doubt that this is malicious (but can’t discount it). More likely the user starts an operation, gets interrupted, forgets that they started or can’t find the original tab so starts again (then later finds the original tab and tries to complete the operation a second time).

Since I am coding in PHP I can detect the existence of session data on form submission (how would I do that with JS if the user as much as opens another tab – I guess that I would need Ajax – right?).

So, each time I start an operation I check for a flag in session data and if set I reload to a “I’m sorry, Dave. I’m afraid I can’t do that” page, else I set the flag and continue (remembering to clear it at the end of the operation).

I guess that that would work, but:
1) Is it acceptable to restrict browser apps to a single tab/instance?
2) Should I attempt to allow multiple instances in v2.0 ?

Any other comments, help or advice?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

贪恋 2024-12-18 06:39:22

更好的设计是避免在会话中存储用户交互状态。将其放在隐藏的表单字段或其他内容中,以便每个客户端请求都带有其关联的状态。如果您担心用户篡改它,请使用 HMAC 来防止这种情况,并且如果它包含用户不应该看到的内容,则可以对其进行加密。

仅声明应该在选项卡之间共享(例如用户的登录身份或购物车之类的内容)应该存储在会话中。

A better design would be to avoid storing user interaction state in the session. Put it in hidden form fields or something so that each client request carries its associated state with it. If you're concerned about the user tampering with it, use an HMAC to prevent that, and possibly encrypt it if it contains things the user shouldn't be able to see.

Only state that should be shared between tabs — like the user's login identity, or something like a shopping cart — should be stored in the session.

很酷又爱笑 2024-12-18 06:39:22

您最多可以在会话文件中保留“最后请求的页面”列表,并使用标志来指示如果它是这些关键表单标志之一,则不应允许用户离开它。因此,如果您使用 form.php 并且它是一个 no-move-off 页面,那么加载的任何新页面都应该显示“中止或关闭窗口”选项。

您无法阻止用户打开另一个选项卡/窗口,但您可以阻止他们在其他窗口/选项卡中移动到站点中的其他位置。

但是,请考虑这是一个非常糟糕的用户体验。想象一下,如果亚马逊将您困在购物车页面中,并且在您不必实际购买东西的情况下永远不会让您进入另一个页面。考虑更新您的代码以允许多个不同的窗口使用相同的表单。

At most you can is keep a "last requested page" listing in the session file, with flags to indicate that the user shouldn't be allowed to move off it if it's one of these critical form flags. So if you're on form.php and it's a no-move-off one, then any new page loaded should present an "abort or close window" option.

You cannot prevent a user from opening up another tab/window, but you can prevent them from moving elsewhere in your site in those other windows/tabs.

However, consider that this is a very poor user experience. Imagine if Amazon trapped you in the shopping cart page and never let you on to another page without having to actually buy something. Consider updating your code to allow multiple different windows use the same form.

慕烟庭风 2024-12-18 06:39:22

由于每个浏览器都支持选项卡式浏览,因此尝试将浏览限制为单个选项卡将是一种糟糕的用户体验(那么您不妨制作一个桌面应用程序)。

解决此问题的一种方法是在表单中添加 CSRF 令牌(作为隐藏变量),该令牌将随请求一起提交。

CSRF 参考

生成令牌的方法有很多,但本质上是:

  1. 创建令牌
  2. 存储在您的 $_SESSION
  3. 输出带有

然后,当表单提交时,您检查 $_REQUEST['{token name}'] == $_SESSION[{token name}]` 。

如果该令牌不同,您就知道它不是您最初生成的表单,因此可以忽略该请求,直到真正的表单带有正确的令牌。

有一件事:如果攻击者能够弄清楚您如何生成 CSRF 令牌,那么他们就可以伪造请求。

With every browser supporting tabbed browsing it would be a poor user experience to try to restrict browsing to a single tab (you might as well make a desktop app then).

One way you could solve this is by adding a CSRF token to your forms (as a hidden variable), that would be submitted with the request.

CSRF reference

There are many ways to generate the token, but essentially you:

  1. create the token
  2. store in your $_SESSION
  3. output the form with <input type="hidden" name="{token name}"
    value="{token value}" />

Then when the form submits you check $_REQUEST['{token name}'] == $_SESSION[{token name}]`.

If that token is different you know it wasn't the form you originally generated and thus can ignore the request until the real form comes in with the correct token.

One thing: if an attacker can figure out how you generate your CSRF tokens then they can forge requests.

凡间太子 2024-12-18 06:39:22

在我登录后添加了以下脚本(例如dashboard.php)

<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>

在我的其余页面的页眉中添加了以下脚本 - 'random_value' 来自该用户的数据库

<script>
$(document).ready(function()
{       
    $("a").attr("target", "_self");

    if(typeof(Storage)                      !== "undefined") 
    {
        if (sessionStorage.pagecount) 
        {
            if('<?=$random_value?>'         ==  window.name)
            {
                sessionStorage.pagecount    =   Number(sessionStorage.pagecount) + 1;
            }
            else
            {
                var url                     =   "url to remove random_value";           
                $.post(url, function (data, url)
                {
                    sessionStorage.removeItem('pagecount');
                    sessionStorage.clear();
                    window.location         =   'logout.php';
                });

            }               
        } 
        else 
        {           
            var url                         =   "url to remove random_value";           
            $.post(url, function (data, url)
            {
                sessionStorage.removeItem('pagecount');
                sessionStorage.clear();
                window.location             =   'logout.php';
            });
        }
    } 
    else 
    {   
        var url                             =   "url to remove random_value";                   
        $.post(url, function (data, url)
        {
            sessionStorage.removeItem('pagecount');
            sessionStorage.clear();
            window.location                 =   'logout.php';
        });
    }   
});
</script>

Added the below script after I login(say dashboard.php)

<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>

Added the below script in Header in rest of my pages - 'random_value' is from db for that user

<script>
$(document).ready(function()
{       
    $("a").attr("target", "_self");

    if(typeof(Storage)                      !== "undefined") 
    {
        if (sessionStorage.pagecount) 
        {
            if('<?=$random_value?>'         ==  window.name)
            {
                sessionStorage.pagecount    =   Number(sessionStorage.pagecount) + 1;
            }
            else
            {
                var url                     =   "url to remove random_value";           
                $.post(url, function (data, url)
                {
                    sessionStorage.removeItem('pagecount');
                    sessionStorage.clear();
                    window.location         =   'logout.php';
                });

            }               
        } 
        else 
        {           
            var url                         =   "url to remove random_value";           
            $.post(url, function (data, url)
            {
                sessionStorage.removeItem('pagecount');
                sessionStorage.clear();
                window.location             =   'logout.php';
            });
        }
    } 
    else 
    {   
        var url                             =   "url to remove random_value";                   
        $.post(url, function (data, url)
        {
            sessionStorage.removeItem('pagecount');
            sessionStorage.clear();
            window.location                 =   'logout.php';
        });
    }   
});
</script>
鼻尖触碰 2024-12-18 06:39:22

如果我现在这样做,我可能会编写一个单页 AngularJs 应用程序(尽管任何形式的 Js 都可以)。

启动时,在本地存储中查找标志。如果设置,则拒绝启动,并带有适当的消息,否则设置标志和运行应用程序。

当然,恶意用户可以绕过它,因为它不是服务器端检查,但我只是拒绝支持这样的。

If I were doing this now, I would probably code a single page AngularJs app (although any form of Js will do).

On start-up, look in local storage for a flag. If set, refuse to start, with suitable message, else set the flag & run the app.

Sure, a malicious user could get around it, since it's not a server-side check, but I would just refuse to support such.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文