【问题标题】:ASP.NET MVC 3 MembershipProviderASP.NET MVC 3 MembershipProvider
【发布时间】:2012-06-23 04:40:24
【问题描述】:

我目前正在使用 ASP.NET MVC 3 开发一个站点,我正在使用 Nhibernate。我创建了一个自定义 MembershipProvider,如下所述。

我的问题是时间在 ValidateUser 方法中记录会话中的用户身份验证并在 GetUser 中检索它。

据我所知,您不能在 ValidateUser 中使用 Session,但使用 Cache 是不正确的,因为存储不是每个用户会话。

我该怎么做?

class MyMembershipProvider : MembershipProvider
{
    public override MembershipUser GetUser(string username, bool userIsOnline)
    {
        var membershipUser = MyMembershipUser)HttpContext.Current.Cache.Get(username);

        // Is not possible
        // var membershipUser = (MyMembershipUser) HttpContext.Current.Session[username];

        return membershipUser;
    }

    public override bool ValidateUser(string username, string password)
    {
        var usuario = UsuarioRepository.GetUsuarioAuthentication(username, password);

        if (usuario != null)
        {
            HttpContext.Current.Cache.Add(username, new MyMembershipUser(usuario.Id, usuario.Email), null,
                                          Cache.NoAbsoluteExpiration, FormsAuthentication.Timeout,
                                          CacheItemPriority.Default, null);

            // Is not possible 
            // HttpContext.Current.Session.Add(username, new MyMembershipUser(usuario.Id, usuario.Email));

            return true;
        }

        return false;
    }

}

【问题讨论】:

  • 不要在 ValidateUser 方法中添加。如果 ValidateUser 返回 true,则在 web 应用程序中添加它。
  • 但是在 GetUser(string username, bool userIsOnline) 方法中我需要返回一个 MembershipUser。

标签: asp.net asp.net-mvc asp.net-mvc-3 asp.net-membership


【解决方案1】:

当您使用带有表单身份验证的 ASP.NET 成员身份时,根本不涉及会话。

一旦用户成功认证,只需调用

FormsAuthentication.SetAuthCookie() 

并且会自动为您创建一个身份验证 cookie。不要在 ValidateUser() 中调用它,而是从调用 ValidateUser() 的客户端代码中调用。

身份验证 cookie 完全独立于会话 cookie。

有关更多信息,请参阅 MSDN 上的 Forms Authentication

如果您想缓存已验证用户的用户详细信息,这应该在调用 Membership.ValidateUser() 的客户端代码中完成,而不是在成员资格提供程序本身中完成。 成员资格提供者 GetUser() 和 ValidateUser() 应该按照他们的名字所暗示的那样做,并且没有任何其他副作用。

【讨论】:

  • 实际上,我使用的是自定义会员,这就是为什么调用 GetUser
  • @Michel 无论您选择使用哪种会员提供者,相同的模式都适用。你调用 Membership.Validate(),然后如果成功,调用 FormsAuthentication.SetAuthCookie()。
  • 是的。赛耶是对的。会话在自定义成员资格提供程序中没有位置。创建自定义成员资格提供程序后,如果您确实需要,可以将其中一些信息存储在 Session 中。
  • 我正在尝试做类似的事情。例如,在我的身份验证过程中,成功的身份验证将返回一些我想存储在会话中的信息。但是由于尚未创建会话(直到我从该方法返回),所以 Session 为空。有没有办法从 ValidateUser 方法初始化会话??
  • 考虑使用 ASP.NET Profile 而不是 Session 作为用户特定信息的接口。
【解决方案2】:

您不想从会话中获取用户。 GetUser 用于从数据库中检索用户 - 返回填充的 MembershipUser 对象。

【讨论】:

  • 碰巧还有其他方法吗?在一个请求中这个方法被调用了两次或更多次。
  • 在同一个进程中是否被调用了两次或多次?如果是这样,那么您需要重新编写该代码。如果它在您的应用程序中被调用两次或更多次,那很好。这就是您将 Membership 抽象为一个类的原因,因为您在多个地方使用它。
  • 如果您只需要用户名,User.Identity.Name 就可以了。如果您需要 MembershipUser 对象的所有属性,您可以缓存该对象 - 使用用户名作为缓存键。我只能提出建议,因为我不知道您要达到的目标。
【解决方案3】:

这两种方法的实现应该只查询您的数据库并返回 MembershipUser 或验证用户名密码 - 不用担心 HttpContext

我不知道你的 UsuarioRepository 实现的细节,所以我只是编了一些方法,但你应该大致像这样对你的提供者进行编码:

class MyMembershipProvider : MembershipProvider
{
    public override MembershipUser GetUser(string username, bool userIsOnline)
    {
        var usuario = UsuarioRepository.GetUserByUserName(username);
        return new MyMembershipUser(usuario.Id, usuario.Email);
    }

    public override bool ValidateUser(string username, string password)
    {
        return UsuarioRepository.ValidateUser(username, password);              
    }
}

UsuarioRepository.GetUserByUserName(username) 方法只会返回具有给定用户名的用户,而如果给定用户名的密码正确,UsuarioRepository.ValidateUser(username, password) 应该返回 true。存储库将处理获取会话并进行查询。

然后,为了提高提供程序的性能,您可以使用 NHibernate 的一些内置缓存功能,通过修改您的 UsuarioRepository 方法以使用缓存来确保它缓存这些查询的结果。然后对这些方法的多次调用不会对性能造成影响。

【讨论】:

  • Stank,这很完美,但是我的GetUser方法有时在一个请求中被调用4次,这正常吗?
  • 不,这不正常。您是否在任何地方明确调用它? web.config 中的 membershipauthentication 部分是什么样的?
  • 看起来不错。因此,您对~/Login 执行的操作应将用户带到登录屏幕,并且该屏幕的 POST 应使用您的会员资格提供程序验证用户,如果用户通过身份验证,则应调用 FormsAuthentication.SetAuthCookie(userName, createPersistentCookie),然后设置确认用户已获得授权的 cookie。
【解决方案4】:

您是否关心查找有关用户的存储信息?

使用 MVC,您可以随时调用

        User.Identity.Name

这将为您提供用户的当前用户名。

正如上面提到的@Saille,在创建自己的自定义成员资格提供程序时,您只需关注创建MembershipUser 和验证MembershipUser 的基础知识。

完成基础并创建提供程序后,您可以在用户成功登录时将信息存储到Session

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 2011-07-02
    • 2011-09-16
    相关资源
    最近更新 更多