如何强制注销网站的所有用户?

Posted

技术标签:

【中文标题】如何强制注销网站的所有用户?【英文标题】:How can I force a log out of all users for a website? 【发布时间】:2011-07-26 04:53:18 【问题描述】:

我正在使用 mysql Connector/.NET,它的所有提供程序都带有 FormsAuthentication。

我需要所有用户在某个时刻退出。 FormsAuthentication.SignOut() 方法不像我想要的那样工作。

如何注销所有站点用户?

【问题讨论】:

您是否要使应用程序脱机?然后看看使用“app_offline.htm”文件。 weblogs.asp.net/scottgu/archive/2005/10/06/426755.aspx 我不确定是否有一个简单的方法来完成此任务,但如果您忽略某个日期之前的所有会话 cookie 并将该日期存储在数据库中怎么办? @rcravens:不,我只想重置所有用户的身份验证。 @Joe:好的,这是个好主意。但是如何设置这个 cookie 过滤器来忽略呢?我使用 FormsAuthentication。它是自动运行的。 我已经有将近一年没有编写 ASP .net 应用程序了,但是在身份验证过程中有一些覆盖点,您可以在其中读取 cookie 并确定它是否有效。我自己做过这个,但我一直在寻找一个很好的例子。 【参考方案1】:

正如 Joe 建议的那样,您可以编写一个 HttpModule 来使给定 DateTime 之前存在的任何 cookie 无效。如果你把它放在配置文件中,你可以在必要时添加/删除它。例如,

Web.config:

<appSettings>
  <add key="forcedLogout" value="30-Mar-2011 5:00 pm" />
</appSettings>

<httpModules>
  <add name="LogoutModule" type="MyAssembly.Security.LogoutModule, MyAssembly"/>
</httpModules>

MyAssembly.dll 中的 HttpModule:

public class LogoutModule: IHttpModule

    #region IHttpModule Members
    void IHttpModule.Dispose()  
    void IHttpModule.Init(HttpApplication context)
    
        context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);
    
    #endregion


    /// <summary>
    /// Handle the authentication request and force logouts according to web.config
    /// </summary>
    /// <remarks>See "How To Implement IPrincipal" in MSDN</remarks>
    private void context_AuthenticateRequest(object sender, EventArgs e)
    
        HttpApplication a = (HttpApplication)sender;
        HttpContext context = a.Context;

        // Extract the forms authentication cookie
        string cookieName = FormsAuthentication.FormsCookieName;
        HttpCookie authCookie = context.Request.Cookies[cookieName];
        DateTime? logoutTime = ConfigurationManager.AppSettings["forcedLogout"] as DateTime?;
        if (authCookie != null && logoutTime != null && authCookie.Expires < logoutTime.Value)
        
            // Delete the auth cookie and let them start over.
            authCookie.Expires = DateTime.Now.AddDays(-1);
            context.Response.Cookies.Add(authCookie);
            context.Response.Redirect(FormsAuthentication.LoginUrl);
            context.Response.End();
        
    

【讨论】:

请记住对 web.config 的更改会导致应用重新启动,您应该将强制注销放在其他位置。可能提供一个站点管理页面来设置这个。 同意。这是一个方便的例子。当然有更好的选择:使用管理 UI 将强制注销存储在数据库中;使用时间窗口(forcedLogoutStart、forcedLogoutEnd)来避免多个 web.config 版本;在 app_data 中放置一个文本文件... 为什么 authCookie.Expires 会小于 logoutTime 值?因为我的网站登录可能在接下来的 30 天内有效,在这种情况下如何处理? @Mou 我想你是想告诉我有一个错误,我应该检查 authcookie.Expires 大于 logoutTime? @Brett 基本上 authcookie.Expires 日期和时间可能大于或小于 logoutTime ?所以我读了代码,不确定它在任何情况下都有效。如果可能,请在此处更正代码。不要将 authcookie.Expires 与 logoutTime 进行比较。【参考方案2】:

基于@Bret's 很好的答案。我处理了一些场景,这些场景允许在用户登录(在或之后)配置文件中指定的日期后发生强制注销(无需计算未来的到期日期)。我相信如果 cookie 过期时间在强制注销日期之前,使用他的答案将导致用户不断被注销。此外,我不确定他是如何使用请求中的 cookie 检索 cookie 过期时间的。在我的尝试中,我总是收到 DateTime 默认值,如下所述:ASP.NET cookie expiration time is always 1/1/0001 12:00 AM

所以这里的想法是您需要将 cookie 创建 DateTime 添加到主体(注意:类型应该是可为空的 DateTime。如果已经对站点进行了此更改,这将允许处理正在使用 - 在此之前作为主体不包含此额外字段)。

您像他一样设置 web.config:

<configuration>
  <appSettings>
    <add key="forcedLogout" value="03-Feb-2021 10:46 pm" />
  </appSettings>
</configuration>

要将模块添加到web.config,你需要确定你是否使用application pool integrated mode vs application pool classic mode:

  <system.webServer><!--for integrated mode-->
    <modules>
      <add name="ForceLogoutModule" type="AssemblyName.NameSpace.ForceLogoutModule", AssemblyName />
    </modules>
  </system.webServer>

  <system.web><!--for classic mode-->
     <httpModules>
      <add name="ForceLogoutModule" type="AssemblyName.NameSpace.ForceLogoutModule", AssemblyName />
    </httpModules>
  </system.web>

或者您可以通过编程方式添加模块(在 global.asax 中):

public static IHttpModule Module = new ForceLogoutModule();
public override void Init()

    base.Init();
    Module.Init(this);

然后你的 ForceLogout 模块(可以在同一个项目中):

public class ForceLogoutModule : IHttpModule

    #region IHttpModule Members
    void IHttpModule.Dispose()  
    void IHttpModule.Init(HttpApplication context)
    
        context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);
    
    #endregion


    /// <summary>
    /// Handle the authentication request and force logouts according to web.config
    /// </summary>
    /// <remarks>See "How To Implement IPrincipal" in MSDN</remarks>
    private void context_AuthenticateRequest(object sender, EventArgs e)
    
        HttpContext context = ((HttpApplication)sender as HttpApplication).Context;
        javascriptSerializer serializer = new JavaScriptSerializer();
        string cookieName = FormsAuthentication.FormsCookieName;
        HttpCookie authCookie = context.Request.Cookies[cookieName];
        if (authCookie == null)
            return;
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
        CustomPrincipalSerializeModel principal = serializer.Deserialize<CustomPrincipalSerializeModel>(ticket.UserData);
        DateTime logoutTime;
        DateTime cookieCreation = ticket.IssueDate;

        if (!this.TryParseNullableToDate(ConfigurationManager.AppSettings["forcedLogout"], out logoutTime))
            return;


        if (!principal.Expiration.HasValue
            || (principal.Expiration.Value.ToLocalTime() > logoutTime && cookieCreation < logoutTime
            && DateTime.Now >= logoutTime.Date))
        
            authCookie.Expires = DateTime.Now.AddDays(-1);
            context.Response.Cookies.Add(authCookie);
            context.Response.Redirect(FormsAuthentication.LoginUrl);
            context.Response.End();
        
    

    private bool TryParseNullableToDate(string value, out DateTime dateTime)
    
        DateTime temp;
        if (string.IsNullOrWhiteSpace(value) || !DateTime.TryParse(value, out temp))
        
            dateTime = DateTime.MinValue;
            return false;
        

        dateTime = temp;
        return true;
    

【讨论】:

以上是关于如何强制注销网站的所有用户?的主要内容,如果未能解决你的问题,请参考以下文章

Rails设计gem:强制注销浏览器选项卡关闭

会话到期时网站通常如何自动注销用户?

强制注销所有在线用户中的特定用户

注销后如何保存购物车数据的会话,以便用户在 Django 中再次登录时可以找到它们?

用户不活动注销 PHP

https 客户端证书注销/重新登录