ASP.NET会员资格:当前用户ID存储在哪里?

5
使用ASP.NET成员资格,如果我想获取当前用户的信息,我可以调用MembershipUser.GetUser()
因此,系统必须以某种方式知道当前用户的ID。
如果我的理解是正确的,并且我只需要当前用户的ID,那么有没有一种方法可以在不返回数据库中所有用户信息的情况下获取它?
我知道我可以使用User.Identity.Name来获取当前用户的用户名,但我需要ID。
6个回答

10

简短回答是:当你使用内置成员资格提供程序时,你不能只获取userID而不检索整个用户信息,只有这样。

    MembershipUser user = Membership.GetUser();
    string UserID = user.ProviderUserKey.ToString();

但是如果你想要一个只检索userID的方法或属性,你必须重新实现自己的成员资格提供程序,或者(更简单地)实现IPrincipal接口。


2

1

正如你所猜测的那样,Membership API并不支持你想要的功能。在过去,我使用了一个辅助类来代替创建自己的提供程序。在这种情况下,它非常简单,可能像这样:

public static object GetUserId() {
  return GetUserId(HttpContext.Current.User.Identity.Name, true);
}    
public static object GetUserId(string userName) {
  return GetUserId(userName, true);
}
public static object GetUserId(string userName, bool UpdateLastActivity) {
  using (SqlConnection c = new SqlConnection(CONNECTION_STRING)) {
    string sql = @"
DECLARE @UserId uniqueidentifier
SELECT @UserId=u.UserId
FROM dbo.aspnet_Applications AS a
  ,dbo.aspnet_Users AS u
  ,dbo.aspnet_Membership AS m
WHERE
  a.LoweredApplicationName=LOWER(@ApplicationName)
  AND u.ApplicationId=a.ApplicationId
  AND u.LoweredUserName=LOWER(@UserName)
  AND u.UserId=m.UserId;
IF @UserId IS NOT NULL AND @UpdateLastActivity=1
  UPDATE dbo.aspnet_Users
  SET LastActivityDate=@CurrentTimeUtc
  WHERE UserId=@UserId;
SELECT @UserId  
      ";
    using (SqlCommand cmd = new SqlCommand(sql, c)) {
      cmd.Parameters.AddWithValue("@ApplicationName", Roles.ApplicationName);
      cmd.Parameters.AddWithValue("@UserName", userName);
      cmd.Parameters.AddWithValue("@UpdateLastActivity", UpdateLastActivity);
      cmd.Parameters.AddWithValue("@CurrentTimeUtc", DateTime.UtcNow);
      object id = null;
      c.Open();
      id = cmd.ExecuteScalar();
      return id != DBNull.Value ? id : null;
    }
  }
}

以上内容与在调用GetUser()时,在Membership API中所做的非常相似。

我所寻找的是更轻量级的东西,因为我可以看到ASP.NET正在缓存其中一些信息。我真的看不出使用您的代码与像Membership.GetUser().ProviderUserKey这样简单的东西相比有什么优势。 - Jonathan Wood
如果您查看aspnetdb数据库中的aspnet_Membership_GetUserByName存储过程,其中一个查询字段具有ntext数据类型。您没有详细说明您的设置是什么,因此可能会出现问题。但是,您错过了调用Membership.GetUser().ProviderUserKey的重点。您可以获得用户ID,但是Membership.GetUser()正在执行aspnet_Membership_GetUserByName-通过SQL Server Profiler运行它以进行确认。从未打扰过检查ASP.NET缓存什么。 - kuujinbo
我不确定我是否理解了你的观点。是的,Membership.GetUser()返回整个用户记录——这是我最初想避免的东西。但是看着你发布的代码的复杂性,我并没有真正看到它将会更快。因此,我不确定我真的看到了很大的优势。抱歉,我错过了你提到ntext的观点。为什么它会成为问题?(我正在使用几乎所有的最新版本)。 - Jonathan Wood
aspnet_Membership_GetUserByName查询11个字段,包括SQL Server中性能最差的数据库类型之一aspnet_Membership.dbo.Comment。根据您的问题,一个合理的假设是您想要任何可能的优化。答案可以减少网络流量,特别是如果您在设置中使用了MembershipUser.Comment(问题中未指定)。请不要认为这是“复杂的*”,但如果您认为答案很复杂,最好坚持使用Membership.GetUser().ProviderUserKey(差异对您不重要)。祝你好运。 - kuujinbo
是的,我确实认为这是个人问题。这只是一个权衡的问题 - 而不是对我来说太复杂的问题!除此之外,你为什么不能在数据库中更改“ntext”列类型呢? - Jonathan Wood
显示剩余2条评论

0

你可以使用 MembershipUser.UserName 获取用户 ID,或者尝试调用 Membership.GetUser(User.Identity.Name) 看看是否适用于你。


不,那是用户名,而不是ID。而我的问题是如何在不检索所有用户数据的情况下获取此信息,这正是您所提供建议所做的。 - Jonathan Wood
尝试使用我在编辑后发布的这个 Membership.GetUser(User.Identity.Name) - Xtian Macedo
你已经描述了多种做法,而这恰恰是我不想要的。也许你没有读懂我的问题。 - Jonathan Wood
这个怎么样? MembershipUser myObject = Membership.GetUser(); string UserID = myObject.ProviderUserKey.ToString(); 我相信这就是你要找的。 - Xtian Macedo
当然它可以工作。但是需要读取整个用户记录才能获取ID。这正是我在问题中说过的,我不想这样做。我不清楚为什么你不理解我,感谢你的努力,但我认为我已经结束了这次对话。 - Jonathan Wood

0

进一步研究后发现,ASP.NET Membership API实际上并没有跟踪用户ID。它只跟踪用户名(User.Identity.Name)。因为Membership.GetUser()可以从ID或用户名中查找用户,所以不需要ID。

事实上,Membership.GetUser()只需要转换成Membership.GetUser(User.Identity.Name)即可。由于它可以从用户名获取当前用户,因此不再需要假设当前用户的ID被缓存到任何地方。

因此,似乎ID并没有被加载到内存中,获取ID的唯一方法是从数据库加载数据(这意味着在使用ASP.NET Membership API时必须要加载整个用户记录)。


一个MembershipUser应该有一个ProviderUserKey属性,如果你正在使用SQLMembershipProvider,你可以将其转换为(Guid)。 - PilotBob

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接