在FormsAuthentication对用户进行身份验证后,撤消身份验证并重定向到登录页面

时间:2022-12-03 20:26:12

I need to revoke an authentication cookie if the user no longer exists (or some other condition), after the forms authentication mechanism already have received the authentication cookie from the browser and have validated it. I.e. here is the use scenario:

在表单身份验证机制已经从浏览器接收到身份验证cookie并验证后,如果用户不再存在(或某些其他条件),我需要撤销身份验证cookie。即这是使用场景:

  1. The user have been authenticated, and granted non-expiring auth cookie.
  2. 用户已经过身份验证,并被授予非过期的身份验证cookie。

  3. In a few days, the user tries to access my web app again, and as the cookie is valid, the forms authentication mechanism will grant access.

    几天后,用户再次尝试访问我的Web应用程序,并且由于cookie有效,表单身份验证机制将授予访问权限。

  4. Now I want to perform a second check (whatever condition I want), and decide if I want to let the user continue, or to revoke the authentication.

    现在我想执行第二次检查(无论我想要什么条件),并决定是否要让用户继续,或者撤销身份验证。

The question is - is there an official automated way for this? So far I have come with some possibilities, but I do not know which one is better. I can capture the Authenticate event in global.asax, check whatever I want, and to revoke I clear the cookie, and then one of these:

问题是 - 这是否有官方的自动化方式?到目前为止,我已经有了一些可能性,但我不知道哪一个更好。我可以捕获global.asax中的Authenticate事件,检查我想要的任何内容,并撤销我清除cookie,然后其中一个:

  1. Redirect again to same url - this should work, as this time the forms authentication will fail, and it will redirect to logon page.

    再次重定向到相同的URL - 这应该工作,因为这次表单身份验证将失败,它将重定向到登录页面。

  2. Throw some exception ??? which one to make the redirect happen w/o me specifying anything?

    抛出一些异常???哪一个使重定向发生而我没有指定任何东西?

  3. Somehow to get the logon page url from the config file (any ideas how/which config handler to use) and redirect directly?

    以某种方式从配置文件(任何想法如何/使用哪个配置处理程序)获取登录页面URL并直接重定向?

  4. Some FormsAuthentication class/method I have overlooked, which is designed for this?

    我忽略了一些FormsAuthentication类/方法,它是为此而设计的?

  5. Any other idea?

    还有其他想法吗?

2 个解决方案

#1


3  

I don't think there is an automated way to achive this. I think the best way would be to add a date to the auth cookie which will be the last time you checked whether the user exists. So when a user logs-in you'll:

我认为没有一种自动化的方式来实现这一目标。我认为最好的方法是在auth cookie中添加一个日期,这是您最后一次检查用户是否存在的时间。因此,当用户登录时,您将:

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                1, // Ticket version
                name, // Username associated with ticket
                DateTime.Now, // Date/time issued
                DateTime.Now.AddMonths(1), // Date/time to expire
                true, // "true" for a persistent user cookie
                DateTime.Now.ToUniversalTime(), // last time the users was checked
                FormsAuthentication.FormsCookiePath);// Path cookie valid for

        // Encrypt the cookie using the machine key for secure transport
        string hash = FormsAuthentication.Encrypt(ticket);
        HttpCookie cookie = new HttpCookie(
            FormsAuthentication.FormsCookieName, // Name of auth cookie
            hash); // Hashed ticket

        cookie.HttpOnly = true;

        // Set the cookie's expiration time to the tickets expiration time
        if (ticket.IsPersistent) cookie.Expires = ticket.Expiration;
        //cookie.Secure = FormsAuthentication.RequireSSL;
        Response.Cookies.Add(cookie);

Then everytime a user is authenicated you can check the additional date you passed to the Authentication ticket and in 10 minute intervals or less double check against the database whether the user exists. The code might look something like this:

然后,每次用户进行身份验证时,您都可以检查传递给身份验证票证的其他日期,并以10分钟或更短的时间间隔对数据库进行双重检查,确定用户是否存在。代码可能如下所示:

public void FormsAuthentication_OnAuthenticate(object sender, 
                           FormsAuthenticationEventArgs args)
    {
        if (FormsAuthentication.CookiesSupported)
        {
            if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
            {
                try
                {
                    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(
                      Request.Cookies[FormsAuthentication.FormsCookieName].Value);

                    DateTime lastCheckedTime = DateTime.TryParse(ticket.UserData);
                    TimeSpan elapsed = DateTime.Now - lastCheckedTime;
                    if (elapsed.TotalMinutes > 10)//Get 10 from the config
                    {
                        //Check if user exists in the database. 
                        if (CheckIfUserIsValid())
                        {
                            //Reset the last checked time
                            // and set the authentication cookie again
                        }
                        else
                        {
                            FormsAuthentication.SignOut();
                            FormsAuthentication.RedirectToLoginPage();
                            return;
                        }
                    }

                }
                catch (Exception e)
                {
                    // Decrypt method failed.
                }
            }
        }
    }

You can even cache the users that have been deleted the last 10 minutes and check against that collection.

您甚至可以缓存最近10分钟内已删除的用户并检查该集合。

Hope that helps.

希望有所帮助。

#2


0  

If you are rejecting the cookie for some other reason than an expired session, then I think you should redirect the user to a page that describes what they need to do in order to gain access. If logging on again is sufficient, then the logon page would suffice. It sounds, however, like there are conditions under which simply logging on again is not possible. In those cases, it would be better to redirect the user to a suitable error page that describes why they are unable to access the site and explains how to gain access again (if possible).

如果由于某个其他原因拒绝cookie而不是过期的会话,那么我认为您应该将用户重定向到描述他们需要做什么才能获得访问权限的页面。如果再次登录就足够了,那么登录页面就足够了。然而,听起来好像有条件再次无法再次登录。在这些情况下,最好将用户重定向到一个合适的错误页面,该页面描述了他们无法访问该站点的原因,并解释了如何再次获取访问权限(如果可能)。

#1


3  

I don't think there is an automated way to achive this. I think the best way would be to add a date to the auth cookie which will be the last time you checked whether the user exists. So when a user logs-in you'll:

我认为没有一种自动化的方式来实现这一目标。我认为最好的方法是在auth cookie中添加一个日期,这是您最后一次检查用户是否存在的时间。因此,当用户登录时,您将:

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                1, // Ticket version
                name, // Username associated with ticket
                DateTime.Now, // Date/time issued
                DateTime.Now.AddMonths(1), // Date/time to expire
                true, // "true" for a persistent user cookie
                DateTime.Now.ToUniversalTime(), // last time the users was checked
                FormsAuthentication.FormsCookiePath);// Path cookie valid for

        // Encrypt the cookie using the machine key for secure transport
        string hash = FormsAuthentication.Encrypt(ticket);
        HttpCookie cookie = new HttpCookie(
            FormsAuthentication.FormsCookieName, // Name of auth cookie
            hash); // Hashed ticket

        cookie.HttpOnly = true;

        // Set the cookie's expiration time to the tickets expiration time
        if (ticket.IsPersistent) cookie.Expires = ticket.Expiration;
        //cookie.Secure = FormsAuthentication.RequireSSL;
        Response.Cookies.Add(cookie);

Then everytime a user is authenicated you can check the additional date you passed to the Authentication ticket and in 10 minute intervals or less double check against the database whether the user exists. The code might look something like this:

然后,每次用户进行身份验证时,您都可以检查传递给身份验证票证的其他日期,并以10分钟或更短的时间间隔对数据库进行双重检查,确定用户是否存在。代码可能如下所示:

public void FormsAuthentication_OnAuthenticate(object sender, 
                           FormsAuthenticationEventArgs args)
    {
        if (FormsAuthentication.CookiesSupported)
        {
            if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
            {
                try
                {
                    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(
                      Request.Cookies[FormsAuthentication.FormsCookieName].Value);

                    DateTime lastCheckedTime = DateTime.TryParse(ticket.UserData);
                    TimeSpan elapsed = DateTime.Now - lastCheckedTime;
                    if (elapsed.TotalMinutes > 10)//Get 10 from the config
                    {
                        //Check if user exists in the database. 
                        if (CheckIfUserIsValid())
                        {
                            //Reset the last checked time
                            // and set the authentication cookie again
                        }
                        else
                        {
                            FormsAuthentication.SignOut();
                            FormsAuthentication.RedirectToLoginPage();
                            return;
                        }
                    }

                }
                catch (Exception e)
                {
                    // Decrypt method failed.
                }
            }
        }
    }

You can even cache the users that have been deleted the last 10 minutes and check against that collection.

您甚至可以缓存最近10分钟内已删除的用户并检查该集合。

Hope that helps.

希望有所帮助。

#2


0  

If you are rejecting the cookie for some other reason than an expired session, then I think you should redirect the user to a page that describes what they need to do in order to gain access. If logging on again is sufficient, then the logon page would suffice. It sounds, however, like there are conditions under which simply logging on again is not possible. In those cases, it would be better to redirect the user to a suitable error page that describes why they are unable to access the site and explains how to gain access again (if possible).

如果由于某个其他原因拒绝cookie而不是过期的会话,那么我认为您应该将用户重定向到描述他们需要做什么才能获得访问权限的页面。如果再次登录就足够了,那么登录页面就足够了。然而,听起来好像有条件再次无法再次登录。在这些情况下,最好将用户重定向到一个合适的错误页面,该页面描述了他们无法访问该站点的原因,并解释了如何再次获取访问权限(如果可能)。