【问题标题】:How to logout user in OWIN ASP.NET MVC5如何在 OWIN ASP.NET MVC5 中注销用户
【发布时间】:2014-11-28 17:32:54
【问题描述】:

我有一个 ASP.NET MVC5 项目的标准 AccountController 类。 当我尝试注销用户时,我遇到了一个错误,因为 HttpContextnull。 (我的意思是HttpContext.GetOwinContext().Authentication 为空)

所以我不知道如何在会话结束时注销用户...

global.asax 我有这个

protected void Session_Start(object sender, EventArgs e)
{
     Session.Timeout = 3; 
}

protected void Session_End(object sender, EventArgs e)
{
            try
            {
                 var accountController = new AccountController();
                 accountController.SignOut();
            }
            catch (Exception)
            {
            }
}

帐户控制器

public void SignOut()
{
      // Even if I do It does not help coz HttpContext is NULL
      _authnManager = HttpContext.GetOwinContext().Authentication;    

    AuthenticationManager.SignOut();


}

private IAuthenticationManager _authnManager;  // Add this private variable


public IAuthenticationManager AuthenticationManager // Modified this from private to public and add the setter
{
            get
            {
                if (_authnManager == null)
                    _authnManager = HttpContext.GetOwinContext().Authentication;
                return _authnManager;
            }
            set { _authnManager = value; }
}

Startup.Auth.cs

 public void ConfigureAuth(IAppBuilder app)
        {
            // Enable the application to use a cookie to store information for the signed in user
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                ExpireTimeSpan = TimeSpan.FromMinutes(3),
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login")
            });
}

【问题讨论】:

    标签: c# session asp.net-mvc-5 logout owin


    【解决方案1】:

    这对我有用

    `public void SignOut()
        {
            IOwinContext context = _context.Request.GetOwinContext();
            IAuthenticationManager authenticationManager = context.Authentication;
            authenticationManager.SignOut(AuthenticationType);
        }
    `
    

    我唯一的问题是没有重定向到登录,所以我得到一个未找到视图的错误,因为我注销的视图在 [Authorize] 属性下。我认为当用户没有被这个代码块授权时,自动重定向是内置的......

    `app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "ApplicationCookie",
            LoginPath = new PathString("/Account/Login"),
            ExpireTimeSpan = TimeSpan.FromHours(1),
        });
    `
    

    【讨论】:

      【解决方案2】:
      Session.Abandon();
      var owinContext = System.Web.HttpContext.Current.Request.GetOwinContext();
      var authenticationTypes = owinContext.Authentication.GetAuthenticationTypes();
      owinContext.Authentication.SignOut(authenticationTypes.Select(o => o.AuthenticationType).ToArray());
      

      ```

      【讨论】:

        【解决方案3】:

        我都试过了:

        System.Web.HttpContext.Current.GetOwinContext().Authentication.SignOut(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie);
        FormsAuthentication.SignOut();
        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
        
        Request.GetOwinContext().Authentication.SignOut();
        
        Request.GetOwinContext().Authentication.SignOut(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie);
        

        但这终于解决了我的问题:

        HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty),null);
        

        Check

        【讨论】:

          【解决方案4】:

          假设您使用 ApplicationCookie 来存储您的登录信息。

          AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
          

          【讨论】:

          • 它说AuthManager没有方法SignOut
          • 你可以试试 var ctx = Request.GetOwinContext(); var authenticationManager = ctx.Authentication; authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
          • @phil 它只是删除了 cookie。页面不会重定向到登录页面,除非刷新有没有办法在同一请求注销后使身份无效?
          • @msz 是的,我去年就知道了,哈哈
          【解决方案5】:

          为此,您需要定义一个 ActionFilter 属性,并且您需要将用户重定向到相应的控制器操作。在那里你需要检查会话值,如果它为空,那么你需要重定向用户。下面是代码(Also you can visit my blog for detail step):

          public class CheckSessionOutAttribute : ActionFilterAttribute
              {
                  public override void OnActionExecuting(ActionExecutingContext filterContext)
                  {
                      string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower().Trim();
                      string actionName = filterContext.ActionDescriptor.ActionName.ToLower().Trim();
          
                      if (!actionName.StartsWith("login") && !actionName.StartsWith("sessionlogoff"))
                      {
                          var session = HttpContext.Current.Session["SelectedSiteName"];
                          HttpContext ctx = HttpContext.Current;
                          //Redirects user to login screen if session has timed out
                          if (session == null)
                          {
                              base.OnActionExecuting(filterContext);
          
          
                              filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new
                              {
                                  controller = "Account",
                                  action = "SessionLogOff"
                              }));
          
                          }
                      }
          
                  }
          
              }
          }
          

          【讨论】:

            【解决方案6】:

            Session_End() 的调用导致异常。这是完全可以预料的,因为您不能简单地创建new AccountController(),调用accountController.SignOut() 并期望它能够工作。这个新控制器没有连接到 MVC 管道中 - 它没有 HttpContext 以及能够工作的所有其他要求。

            您应该注销用户以响应他们提出的请求。使用个人帐户身份验证创建一个新的 MVC 项目。打开 AccountController 看看LogOff() 方法:

                [HttpPost]
                [ValidateAntiForgeryToken]
                public ActionResult LogOff()
                {
                    AuthenticationManager.SignOut();
                    return RedirectToAction("Index", "Home");
                }
            

            这里AuthenticationManager.SignOut() 将被执行以响应/Account/LogOff 处的POST 请求。每当此类请求到达时,ASP.NET/MVC 将创建一个 AccountController 实例并正确初始化它。之后将调用 LogOff 方法,您可以在其中实际执行AuthenticationManager.SignOut();

            同样在默认的 ASP.NET/MVC Application with Identity 中,在代码的 Helpers 区域中声明 AuthenticationManager,如下所示:

            private IAuthenticationManager AuthenticationManager { get { return HttpContext.GetOwinContext().Authentication; } }
            

            希望这会有所帮助。

            【讨论】:

            • 是的,我同意。我们默认有这种方法,但我想强制注销用户并将他重定向到登录页面。所以我需要解决方案来用 OWIN 做到这一点。不管怎样,谢谢你的意见!
            • @ClarkKent 该解决方案确实可以使用 OWIN,我已经编辑了答案以解释它是如何做到的。请查看待修改的内容。 Milan 解释了为什么它会在您注销用户之前引发错误。
            • 嗯...我刚刚在Session_End 中评论了代码,我正面临应用程序的奇怪行为。我把 SessionTimeout 1 分钟。当我登录并且什么都不做时,它工作正常。所以 1 分钟后,当我刷新页面时,它会注销并重定向到 LOGIN 页面。但如果在 2-3 分钟内。我在网站内导航它不起作用。 :)
            • @ClarkKent 在这 2-3 分钟内,您是否积极地浏览网站?您是否尝试过转到不同的页面,坐一分钟然后移动?如果是这样,请尝试输出您的会话变量以查看它是否仍然设置或重置。当您导航到其他页面时,不会调用该功能或​​您将用户注销的功能。
            • 您的代码有点混乱,但即使您收到填充上下文的调用,您仍可能面临一个单独的问题,如 codeplex 网站上的一些错误请求中所述。 katanaproject.codeplex.com/workitem/356 .你需要调用AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);不仅仅是 AuthenticationManager.SignOut();
            猜你喜欢
            • 2014-04-29
            • 1970-01-01
            • 1970-01-01
            • 2016-11-21
            • 2014-12-24
            • 2015-02-22
            • 1970-01-01
            • 2017-12-27
            • 1970-01-01
            相关资源
            最近更新 更多