表单身份验证 Cookie 在服务器关闭/故障时不会过期

发布于 2024-10-11 02:21:41 字数 3839 浏览 0 评论 0原文

这是我使用 CustomMembershipProvider 登录的用例

  1. 用户登录 MembershipProvider 验证用户帐户
  2. Membership 的用户属性设置为来自数据库的用户详细信息
  3. 创建身份验证票证
  4. 添加表单身份验证 cookie。
  5. 用户已登录

这是我的问题的一个用例

  1. 停止 Web 开发服务器
  2. 启动 Web 开发服务器,并且用户仍然登录(由于 cookie?)
  3. 由于服务器重新启动/故障,用户属性成员资格设置为 null
  4. 应用程序抛出由于空用户值而导致的异常

我能想到的唯一解决方案是清除 Application_Start() 上的所有 cookie,但我不知道这怎么可能,因为请求在应用程序启动期间脱离了上下文。

您对如何解决此类问题有什么想法吗?

这是代码:

CustomMembershipProvider

public class CustomMembershipProvider : MembershipProvider
{
    #region Unimplemented MembershipProvider Methods
    //Other methods here
    #endregion

    //private IUserRepository _userRepository = new UserRepository();

    //Ninject bindings
    private IUserRepository _userRepository;

    [Inject]
    public IUserRepository UserRepository
    {
        set
        {
            _userRepository = value;
        }
    }

    private IProfileRepository _profileRepository;

    [Inject]
    public IProfileRepository ProfileRepository
    {
        set
        {
            _profileRepository = value;
        }
    }


    public User User
    {
        get;
        private set;
    }

    public Profile Profile
    {
        get;
        set;
    }


    public CustomMembershipProvider()
    {
        MvcApplication.Container.Inject(this);
    }

    public override bool ValidateUser(string username, string password)
    {
        if (string.IsNullOrEmpty(password.Trim())) return false;

        User user = _userRepository.GetUserByUsername(username);

        user.UserType = UserHelper.GetUserTypeById(user.UserTypeId);

        if (user == null) return false;

        string hash = PasswordHelper.ComputeHash(password, user.PasswordSalt);

        if (user.Password == hash)
        {
            this.User = user;

            Profile profile = _profileRepository.GetProfileByUserId(user.UserId);

            this.Profile = profile;
            return true;
        }

        return false;
    }
}

这是帐户控制器的登录方法

        [HttpPost]
        public ActionResult Login(string username, string password)
        {

            if (!provider.ValidateUser(username, password))
            {
                TempData["LoginError"] = "Incorrect";
            }
            else
            {
                User user = provider.User;

                if (!user.Verified)
                {
                    TempData["LoginError"] = "Please verify your account";
                    return Redirect(Request.UrlReferrer.LocalPath);
                }

                //FormsAuthentication.SetAuthCookie(user.Username,false);
                FormsAuthenticationTicket authTicket = new
                               FormsAuthenticationTicket(1, //version
                               username,                    //user name
                               DateTime.Now,                //creation
                               DateTime.Now.AddMinutes(30), //Expiration
                               false,                       //Persistent
                               username);                   //since Classic logins don't have a "Friendly Name"

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

                WebsiteObjects.Profile profile = provider.Profile;


                TempData["LoginError"] = String.Empty;
            }


        return Redirect("/");

    }

下面的建议是不可行的,因为每当我重新启动服务器时都会出现这种情况。

  1. Application_BeginRequest 上的 Request.IsAuthenticated 为 FALSE;
  2. Request.IsAuthenticated 在我的“视图”上为 TRUE

为什么会发生这种情况?

Here is a use case of my login using a CustomMembershipProvider

  1. User Logs in MembershipProvider validates user account
  2. User property of Membership is set to user details coming from the database
  3. An authentication ticket is created
  4. Forms authentication cookie is added.
  5. User is logged in

Here is a use case of my problem

  1. Stop whe web development server
  2. Start the web development server, and user is still logged in (due to cookie?)
  3. User property Membership is set to null due to server restart/failure
  4. Application throws exception due to null user value

The only solution I could think off is to clear all cookies on Application_Start() but I don't know how is that even possible as Request is out of context during application start.

Do you have any ideas how to solve this kind of problem?

Here is the code:

CustomMembershipProvider

public class CustomMembershipProvider : MembershipProvider
{
    #region Unimplemented MembershipProvider Methods
    //Other methods here
    #endregion

    //private IUserRepository _userRepository = new UserRepository();

    //Ninject bindings
    private IUserRepository _userRepository;

    [Inject]
    public IUserRepository UserRepository
    {
        set
        {
            _userRepository = value;
        }
    }

    private IProfileRepository _profileRepository;

    [Inject]
    public IProfileRepository ProfileRepository
    {
        set
        {
            _profileRepository = value;
        }
    }


    public User User
    {
        get;
        private set;
    }

    public Profile Profile
    {
        get;
        set;
    }


    public CustomMembershipProvider()
    {
        MvcApplication.Container.Inject(this);
    }

    public override bool ValidateUser(string username, string password)
    {
        if (string.IsNullOrEmpty(password.Trim())) return false;

        User user = _userRepository.GetUserByUsername(username);

        user.UserType = UserHelper.GetUserTypeById(user.UserTypeId);

        if (user == null) return false;

        string hash = PasswordHelper.ComputeHash(password, user.PasswordSalt);

        if (user.Password == hash)
        {
            this.User = user;

            Profile profile = _profileRepository.GetProfileByUserId(user.UserId);

            this.Profile = profile;
            return true;
        }

        return false;
    }
}

Here is the login method of the Account Controller

        [HttpPost]
        public ActionResult Login(string username, string password)
        {

            if (!provider.ValidateUser(username, password))
            {
                TempData["LoginError"] = "Incorrect";
            }
            else
            {
                User user = provider.User;

                if (!user.Verified)
                {
                    TempData["LoginError"] = "Please verify your account";
                    return Redirect(Request.UrlReferrer.LocalPath);
                }

                //FormsAuthentication.SetAuthCookie(user.Username,false);
                FormsAuthenticationTicket authTicket = new
                               FormsAuthenticationTicket(1, //version
                               username,                    //user name
                               DateTime.Now,                //creation
                               DateTime.Now.AddMinutes(30), //Expiration
                               false,                       //Persistent
                               username);                   //since Classic logins don't have a "Friendly Name"

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

                WebsiteObjects.Profile profile = provider.Profile;


                TempData["LoginError"] = String.Empty;
            }


        return Redirect("/");

    }

Suggestions below are not doable because whenever I restart the server here is the case.

  1. Request.IsAuthenticated is FALSE on Application_BeginRequest;
  2. Request.IsAuthenticated is TRUE on my 'View'

why is this happening?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

古镇旧梦 2024-10-18 02:21:41

您应该对每个请求执行步骤 2,或将用户详细信息存储到身份验证 cookie 的 UserData 部分。

You should perform step 2 on each request or store the user details into the UserData part of the authentication cookie.

梨涡 2024-10-18 02:21:41

在 Application_AuthenticateRequest 中检查 Request.IsAuthenticated=true 但 User 对象是否为 null,然后重新填充它。

In the Application_AuthenticateRequest check if Request.IsAuthenticated=true but User object is null then re-populate it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文