防止 FormsAuthentication 到期时间增加

Preventing FormsAuthentication expiry time from increasing

我有一个使用表单身份验证的相对简单的基于 WebForms 的站点:

<authentication mode="Forms">
  <forms loginUrl="login.aspx" defaultUrl="secure/home.aspx" name=".AdminSite" />
</authentication>

由于没有明确提及,slidingExpiration 默认设置为 true,因此只要用户仍在网站上导航,他们就不会注销。

但是,我希望特定页面增加到期时间。这可能在 web.config 内还是在代码中?我看到的唯一建议是将 slidingExpiration 设置为 false,这将适用于横向。

身份验证 cookie 设置使用:

FormsAuthentication.RedirectFromLoginPage(username, False)

因此更改身份验证 cookie 本身是不切实际的。

您可以将响应 cookie 的到期日期设置为请求 cookie 的到期日期,从而有效地覆盖系统为该特定页面所做的操作。

经过一番思考,我放弃了尝试更改 cookie 或创建第二个 cookie 或通过更改 Session.Timeout 覆盖 cookie。我认为使用计时器实际上可能更容易,使用 System.Timers。如果你愿意,定时器的方法总是可以放在一个单独的 class 中。

using System.Timers;



public partial class MyPage:Page
{

    private System.Timers.Timer timer;

    protected void Page_Load(object sender, EventArgs e)
    {
        SetTimer();
    }
    private void SetTimer()
    {
        // Interval is set in milliseconds- set as you please.
        timer = new System.Timers.Timer(1000 * 60);

        timer.Elapsed += OnTimedEvent;
        timer.AutoReset = true;
        timer.Enabled = true;
    }

    // In this handler, stop the timer and call a method to clear all cookies.
    private void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        timer.Stop();
        ClearAllCookies();
    }

    // Method to clear all cookies. There may be a simpler way to do this, you are vague about your cookies, so I supplied a clear all.

    public void ClearAllCookies()
    {
        HttpCookie cookie;
        string cookieName;
        int cookieCnt = Request.Cookies.Count;
        for(int i = 0; i < cookieCnt; i++)
        {
            cookieName = Request.Cookies[i].Name;
            cookie = new HttpCookie(cookieName);
            // This causes the cookie to expire
            cookie.Expires = DateTime.Now.AddDays(-1); 
            Response.Cookies.Add(cookie);
        }

        Response.Redirect("LogIn.aspx");
    }
}

编辑

使用注销用户的方法。无论哪种方式,您都将结束会话,而无需 fiddle 在网站其余部分的持续时间内通过用户身份验证,除非会话在此特定页面上超时时结束会话。

public void ForceLogOff(){

    Session.Clear();
    Session.Abandon();
    Session.RemoveAll();

    // Do here whatever you need to do. 
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);

    Response.Redirect("LogIn.aspx");
}

如何结束会话由您决定。这为您提供了一种方法来解决滑动过期问题,并仅在一页内设置自定义超时。

FormsAuthentication 模块通过在必要时重新发布 cookie 来实现滑动过期。为了防止滑动,你需要防止cookie更新发生。

这可以通过简单地从响应中删除 FormsAuthentication cookie 来完成。

下面是一个非常简单的 Web 表单的隐藏代码。 aspx 页面有一个 div 显示 Page_Load 事件的输出。

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        testDiv.InnerHtml = "Hi, cookie is: " + HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value;
        testDiv.InnerHtml += "<br />";
        var ticket = FormsAuthentication.Decrypt( HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
        testDiv.InnerHtml += "Expires: " + ticket.Expiration.ToString("yyyy-MM-dd HH:mm:ss");

        if(Response.Cookies.AllKeys.Contains(FormsAuthentication.FormsCookieName))
            testDiv.InnerHtml += "<br />Forms auth is trying to update the cookie in this response";

    }
    protected void Page_Prerender(object sender, EventArgs e)
    {
        if (Response.Cookies.AllKeys.Contains(FormsAuthentication.FormsCookieName))
            Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
    }
}

Page_Prerender 事件从响应中删除 FormsAuthentication cookie(如果存在),从而防止滑动。

我通过将 FormsAuthentication 的超时设置为两分钟来对此进行测试。然后我开始调试并登录。然后我不断刷新有问题的页面。

由于 FormsAuthentication 除非过期时间过半才更新 cookie,因此在第一分钟内,页面将继续显示相同的加密 cookie 和相同的过期时间。一分多钟后,页面将报告 FormsAuthentication 正在尝试更新 cookie。但是 Page_Prerender 删除了 cookie,所以它不会被发送。一分钟后,您将被重定向到登录页面。

测试相同但删除 Page_Prerender 方法显示 cookie 已更改并且过期时间在大约一分钟后更新。