最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

php - How to restrict my app to a single browser tab? - Stack Overflow

programmeradmin4浏览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 plete 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 ments, help or advice?

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 plete 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 ments, help or advice?

Share Improve this question asked Oct 21, 2011 at 2:41 MawgMawg 40.2k108 gold badges327 silver badges574 bronze badges 1
  • If you have this problem, you probably also have problems with the user clicking the browser's Back button and then interacting with a previous page, even without multiple tabs. You can't assume that the $_SESSION is always in sync with the browser. – Wyzard Commented Oct 21, 2011 at 3:44
Add a ment  | 

5 Answers 5

Reset to default 5

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.

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.

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 es in with the correct token.

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

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>

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.

发布评论

评论列表(0)

  1. 暂无评论