Automatically sign out from Forms Authentication i

2019-04-17 00:10发布

问题:

Is there a way to force ASP.NET to sign out from it's authentication when the browser is closed or the user types in a new address?

If the browser is left open then I need to keep the user authenticated, so a long timeout on the authentication ticket is preferable.

回答1:

Not sure if this is still an issue but this resolved the issue for me. Just add the following to the Page_Load event of your Start Page:

protected void Page_Load(object sender, EventArgs e)
{
    if (Request.UrlReferrer == null || string.IsNullOrEmpty(Request.UrlReferrer.AbsolutePath))
    {
        Session.Abandon();
        FormsAuthentication.SignOut();
        FormsAuthentication.RedirectToLoginPage();
    }
}


回答2:

I've been working on this for some time, reading around and seeing various posts and answers, conjecture and speculation.

This solution does have a significant caveat - Popup windows ("BURN HIM!!!" I hear you cry) are required, as is JavaScript. However, given that you have a need to implement this so securely, I'd hazard a guess that the users would accept this to maintain security, and you could code for JavaScript being enabled.

STEP 1 - Verify that popups are enabled - If not, redirect to instructions on how to enable

in the Global.asax

Setup a session variable to verify if popups have been checked:

void Session_Start(object sender, EventArgs e)
{
    // Code that runs when a new session is started
    Session["popupsChecked"] = false;
}

in Page.aspx / masterPage.master

Check the session variable, if false (first visit to the site this session), inject the JavaScript to check for popup availability:

if (!IsPostBack)
{
    if (!(bool)Session["popupsChecked"])
    {
        Page.Header.Controls.Add(new LiteralControl("<script src=\"/js/popupCheck.js\" type=\"text/javascript\"></script>"));
    }
}

The popupCheck.js file (The file "enablePopups.aspx" is instructions on how to enable popups for the site in question)

$(function () {
    result = window.open("/static/popupCheck.aspx", "popped", "width=10, height=10, location=no, menubar=no, status=no, toolbar=no, scrollbars=no, resizable=no");
    if (result != null) {
        // Not blocking
        if (window.location.pathname != "/static/enablePopups.aspx") {
            window.location = "/";
        };
    }
    else {
        //blocking
        if (window.location.pathname != "/static/enablePopups.aspx") {
            window.location = "/static/enablePopups.aspx";
        };
    }
});

And finally, the popupCheck.aspx

<head runat="server">
    <title>Popup Checker</title>
    <script language="javascript" type="text/javascript">
        window.close();
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        Popup windows are enabled, please close this window.
    </div>
    </form>
</body>
</html>

With the following in the codebehind - This will stop any further checks to see if popup windows are enabled:

protected void Page_Load(object sender, EventArgs e)
{
    Session["popupsChecked"] = true;
}

So at this point we now have "forced" the user to enable popups for this site - As said, the site content should justify this annoyance in my opinion

STEP 2 - Check for where they're going, if they're off, popup the logoff

In your main javascript block, file, data, or however you're doing it now days

var siteLinkClicked = false;
var isAuthenticated = false;
$(function() {

   // Check if user is authenticated
   if ($("#someElementThatOnlyAppearsWhenLoggedIn").length) { isAuthenticated = true; };

   // Check if any of the links clicked are in the site 
    $("a, input").click(function () { // -- You may need more then "a" and "input" tags, or exceptions
        siteLinkClicked = true;
    });

    $(window).bind("beforeunload", function (event) {
        if (siteLinkClicked == false && isAuthenticated == true) {
        // popup the logout page
        window.open("/popupLogout.aspx", "popupLogout", "status=0,location=0,directories=0,menubar=0,scrollbar=0,resizable=0,width=400,height=200")
        };
    });
});

And the popupLogout.aspx

We have some javascript to check for the parent (opener) location, if it's the same as this popup (i.e. the user has clicked refresh - Or you've missed an element for siteLinkClicked) then just close the window without doing anything:

$(function () {
    setTimeout(checkParent, 5000); // Give some time for the new window to load if they've navigated away - A counter could be added, logging off in 5... 4... 3... You get the idea.
    window.blur(); // And stick this to the back
});

function checkParent() {
    var openerLocation = null;
    try {
        openerLocation = window.opener.location.hostname
    } catch (e) {
        openerLocation = null;
    }

    if (openerLocation == window.location.hostname) {
        window.close();
    } else {
        $("#<%= cmdLogout.ClientID %>").click();
        // setTimeout(window.close(), 1000); // Removed and add a redirect to static "loggedOut.html page
    };        
};

If the location is different / undefined then fire off a button click, then close the window:

<asp:Button Text="logout..." runat="server" ID="cmdLogout" OnClick="cmdLogout_click" />

And the button then triggers the following code:

protected void cmdLogout_click(object sender, EventArgs e)
{
    System.Web.Security.FormsAuthentication.SignOut();
    Session.Abandon();

    Response.Redirect("~/static/loggedOut.htm"); // Added, can self close if needed in the HTML
}

Final limitation reiteration

Without JavaScript or popups this method will not work, and for me at least, I'll be working in a controlled environment where security is paramount so this solution is worth the annoyance of the end users.

If you have to go to these extreme ends, then I can only assume that the data and application are sensitive enough to force the users to have to enable javascript and have to enable popups.



回答3:

It seems like you could set a long expiration time and also set it not to persist to get the exact behavior you seem to be looking for. For example:

FormsAuthentication.SetAuthCookie("username", true); 

This sets it to persist so that when you close your browser, it will preserve the cookie so that even if they close their browser and load your site again, it will make it so that they don't have to login so long as the expiration time hasn't occurred.

On the other hand:

FormsAuthentication.SetAuthCookie("username", false); 

This sets the cookie to not persist. When you close your browser, the cookie is deleted thereby forcing a login the next time you load it whether the expiration time happened or not. For more info here, see FormsAuthentication.SetAuthCookie