注销 Web 表单身份验证不会删除服务器上的身份验证

Posted

技术标签:

【中文标题】注销 Web 表单身份验证不会删除服务器上的身份验证【英文标题】:Logging out of Webforms Authentication dos not remove the authentication on the server 【发布时间】:2015-01-07 20:23:39 【问题描述】:

我使用开箱即用的网络表单身份验证。

请求“注销”并使用:

 FormsAuthentication.SignOut();

通过从客户端浏览器中删除 cookie“.aspxauth”来注销用户。

这按预期工作。

我们的网站已经过安全审核,审核员声称当用户注销时身份验证令牌不会从服务器中删除。

我可以使用 Fiddler 重现此行为。

我登录网站并复制cookie“.aspxauth” 我退出:客户端上的 cookie 已删除,我无法再访问受保护的页面 我使用以前复制的 cookie“aspxauth”使用提琴手作曲家向站点发送请求。我可以使用该 cookie 访问受保护的页面。

预期的结果是,如果我退出,我将无法通过提供旧的 aspxauth cookie 访问受保护的页面。

有没有办法使服务器上旧的 aspxauth cookie 失效?

【问题讨论】:

不确定,但您是否尝试过将 cookie 的过期日期设置为 FormsAuthentication.SignOut(); 之前的旧日期? 是的,它只删除客户端上的 cookie。但是那个 cookie 还是被删除了。 我认为不会,因为服务器不保存任何有关用户的信息。服务器将用户信息解密为 cookie,并在每次请求时对其进行加密。欲了解更多信息,请查看here 这是默认 Cookie 的性质,它本质上包含一个(机器密钥)加密值,你是谁。如果你想让它更安全,你必须创建一个自己的 Cookie,其中包含一个会话密钥,引用你服务器上的某些内容,也可以在注销时删除。 【参考方案1】:

我通过在 Auth-cookie 中存储一个盐值来解决这个问题,该值在用户登录时也会保存在数据库中。

在每个请求中,都会检查 auth cookie 中的 salt 是否与数据库中的 salt 相同。如果不是,用户将被注销。

如果用户注销,salt 将从数据库中删除,并且旧的 auth - cookie 不能再使用。

登录时存储盐

    // Generate a new 6 -character password with 2 non-alphanumeric character.
string formsAuthSalt = Membership.GeneratePassword(6, 2);

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
    orderAuthToken.EMail,
    DateTime.Now,
    DateTime.Now.AddMinutes(20),
    ApplicationConfiguration.CreatePersistentCookie,
    formsAuthSalt,
    FormsAuthentication.FormsCookiePath);

// Encrypt the ticket.
string encTicket = FormsAuthentication.Encrypt(ticket);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));


UserInfo user = UserService.GetUser(orderAuthToken.EMail);
user.FormsAuthenticationCookieSalt = formsAuthSalt;
UserService.UpdateUser(user);

检查过滤器中的盐分,你用它来装饰所有动作

public class CheckFormsAuthenticationCookieSalt : ActionFilterAttribute

    private readonly IUserService UserService = ObjectFactory.GetInstance<IUserService>();

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    
        if ( filterContext.HttpContext.Request.IsAuthenticated)
        
            // Encrypt the ticket.
            if (HttpContext.Current.Request.Cookies.AllKeys.Contains(FormsAuthentication.FormsCookieName))
            
             var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
                if (cookie != null)
                
                    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
                    if (ticket != null)
                    
                        string salt = ticket.UserData;
                        int userID = UserService.GetUniqueID(filterContext.HttpContext.User.Identity.Name, true, false, "MyAppName");
                        UserInfo user = UserService.GetUser(userID);
                        //for deployment: dont logg out existing users with no cookie
                        if (user.FormsAuthenticationCookieSalt != salt && user.FormsAuthenticationCookieSalt != "seed")
                        
                            FormsAuthentication.SignOut();
                            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary   "action", "Index" ,  "controller", "Home"  );
                        
                    
                
            
        

        base.OnActionExecuting(filterContext);
    

【讨论】:

感谢 Mathias,尝试了您的解决方案并且效果很好。不注销当前登录用户的检查也让我们免去了成千上万用户因突然注销而感到沮丧的头痛。

以上是关于注销 Web 表单身份验证不会删除服务器上的身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Cookie 与基本身份验证

IIS7 表单身份验证不会拒绝图像访问

ASP.NET MVC 真正使用表单身份验证注销

IBM Worklight 6.0 - 如果客户端注销/登录,具有基本身份验证的适配器不会更新身份验证标头

注销Firebase经过身份验证的用户后写入Firestore

Web API 2,OWIN 身份验证,SignOut 不注销