我应该使用用户名还是用户 ID 来引用 ASP.NET 中经过身份验证的用户
Posted
技术标签:
【中文标题】我应该使用用户名还是用户 ID 来引用 ASP.NET 中经过身份验证的用户【英文标题】:Should I use the username, or the user's ID to reference authenticated users in ASP.NET 【发布时间】:2010-09-05 12:24:14 【问题描述】:所以在我的简单学习网站中,我使用了内置的 ASP.NET 身份验证系统。
我现在正在添加一个用户表来保存他的 zip、DOB 等内容。我的问题是:
-
在新表中,键应该是用户名(字符串)还是用户 ID,即他们在
asp_ tables
中使用的具有 GUID 外观的数字。
如果最好的做法是使用那个丑陋的指南,有谁知道如何获得它?它似乎不像名称那样容易访问 (System.Web.HttpContext.Current.User.Identity.Name
)
如果您建议我既不使用(不是 guid 也不是 ASP.NET 身份验证提供的 userName 字段),那么我该如何使用 ASP.NET 身份验证呢?我喜欢的一种选择是使用用户的电子邮件地址作为登录名,但是如何让 ASP.NET 身份验证系统使用电子邮件地址而不是用户名? (或者没有什么可做的,只是我决定我“知道” userName 实际上是一个电子邮件地址?
请注意:
我不是问如何在 .NET 中获取 GUID,我只是将asp_ tables
中的 userID 列称为 guid。
用户名在 ASP.NET 身份验证中是唯一的。
【问题讨论】:
【参考方案1】:这是旧的,但我只想让发现它的人注意几点:
aspnet 成员数据库在访问用户记录时进行了优化。当使用 loweredusername 和 applicationid 搜索记录时,使用 sql server 中的聚集索引搜索(最佳)。这很有意义,因为当用户第一次发送他们的凭据时,我们只有提供的用户名才能继续。
guid 用户 ID 将提供比 int 更大的索引大小,但这并不重要,因为我们通常一次只检索 1 条记录(用户),并且就碎片而言,读取次数通常大大超过对用户表的写入和编辑次数 - 人们根本不会经常更新该信息。
可以编辑创建 aspnet 成员资格表的 regsql 脚本,这样它就可以使用 NEWSEQUENTIALID() 来提供更好的性能(我已经对此进行了分析),而不是使用 NEWID 作为用户 ID 的默认值。
个人资料。创建“新学习网站”的人不应该尝试重新发明***。我工作过的一个网站使用了开箱即用的 aspnet 成员表(不包括可怕的配置文件系统),用户表包含近 200 万条用户记录。即使有这么多的记录,选择仍然很快,因为正如我开始所说,数据库索引专注于降低用户名+应用程序ID来对这些记录执行聚集索引查找,一般来说,如果 sql 正在执行聚集索引查找找到 1 条记录,即使有大量记录,只要您不向表中添加列并开始拉回太多数据,您也不会有任何问题。
在我看来,根据系统的实际性能和经验,担心这个系统中的引导是过早的优化。如果您的用户 ID 有一个 int,但由于您的自定义索引设计等原因系统执行次优查询,则系统将无法很好地扩展。微软的人在 aspnet 会员数据库方面做得很好,除了将 userId 更改为 int 之外,还有许多更有成效的事情需要关注。
【讨论】:
【参考方案2】:您应该使用用户 ID。 它是 MembershipUser 的 ProviderUserKey 属性。
Guid UserID = new Guid(Membership.GetUser(User.Identity.Name).ProviderUserKey.ToString());
【讨论】:
.Identity.Name 后面多了一个右括号【参考方案3】:我会在我的代码中使用 guid,并且如前所述,使用电子邮件地址作为用户名。毕竟,对于用户来说,它已经是独一无二且令人难忘的。甚至可能放弃 guid(v. 有争议的)。
有人提到在您的代码中使用 GUID 上的聚集索引。我会避免这种情况,尤其是在 INSERT 很高的情况下;每次插入记录时都会重建索引。聚簇索引在自动增量 ID 上运行良好,因为仅追加新记录。
【讨论】:
【参考方案4】:我会说使用 UserID,这样用户名仍然可以更改而不会影响主键。我还将用户名列设置为唯一以停止重复的用户名。
如果您主要搜索用户名而不是用户 ID,则将用户名设为聚集索引并将主键设置为非聚集索引。这将在搜索用户名时为您提供最快的访问,但是如果您主要搜索 UserId,则将其保留为聚集索引。
编辑:这也将更适合当前的 ASP.Net 成员表,因为它们也使用 UserID 作为主键。
【讨论】:
【参考方案5】:我同意 Palmsey 的观点, 虽然他的代码似乎有一点错误:
Guid UserID = new Guid(Membership.GetUser(User.Identity.Name)).ProviderUserKey.ToString());
应该是
Guid UserID = new Guid(Membership.GetUser(User.Identity.Name).ProviderUserKey.ToString());
【讨论】:
【参考方案6】:我会使用一个自动递增的数字,通常是一个 int。
您希望密钥的大小尽可能小。这使您的索引保持较小,并且也有利于任何外键。此外,您没有将数据设计与外部用户数据紧密耦合(这也适用于 aspnet GUID)。
通常,GUID 不能作为良好的主键,因为它们很大,并且插入可能发生在表中的任何数据页而不是最后一个数据页。主要的例外是如果您正在运行多个复制数据库。 GUID 在这种情况下对于键非常有用,但我猜您只有一个数据库,所以这不是问题。
【讨论】:
【参考方案7】:我也同意 Mike Stone 的观点。我的公司最近为外部客户端(而不是通过 LDAP 进行身份验证的内部用户)实施了一个新的用户表。对于外部用户,我们选择将 GUID 存储为主键,并将用户名存储为 varchar,并在用户名字段上具有唯一约束。
另外,如果您要存储密码字段,我强烈建议您将密码作为加盐的哈希二进制文件存储在数据库中。这样,如果有人入侵了您的数据库,他们将无法访问您客户的密码。
【讨论】:
【参考方案8】:如果您打算使用 LinqToSql 进行开发,我建议您使用 Int 作为主键。当我在非 Int 字段的基础上建立关系时,我遇到了很多问题,即使 nvarchar(x) 字段具有使其成为唯一字段的约束。
我不确定这是 LinqToSql 中的一个已知错误还是什么,但我在当前项目中遇到了问题,我不得不换掉几个表上的 PK 和 FK。
【讨论】:
【参考方案9】:我会使用用户 ID。如果你想使用用户名,你会让“更改用户名”功能变得非常昂贵。
【讨论】:
【参考方案10】:如果用户名是唯一的,我建议使用用户名作为表中的主键,这样做有几个很好的理由:
-
主键将是一个聚集索引,因此通过用户名搜索用户详细信息将非常快速。
它将阻止重复的用户名出现
您不必担心使用两种不同的信息(用户名或 guid)
这将使编写代码变得更加容易,因为不必查找两位信息。
【讨论】:
使用用户名的关键问题是如果用户出于某种原因想要更改他们的用户名。如果您使用用户名,您将不得不更改多个表,而不仅仅是一个。注意:发表此评论然后阅读以下内容并看到其他人提到了这一点。 随着时间的推移可以重复使用用户名时会出现其他潜在问题。例如,假设您在自定义授权模型中使用用户名。用户 ASmith 被指定为管理员。然后他离开公司,他的用户记录被删除。一个新用户加入公司并被分配了用户名 ASmith。您可能只是在没有意识到的情况下授予该用户管理员访问权限。【参考方案11】:我同意迈克·斯通的观点。如果您要跟踪大量数据,我还建议仅使用 GUID。否则,一个简单的自动递增整数 (Id) 列就足够了。
如果您确实需要 GUID,.NET 非常可爱,您可以通过简单的方式获得...
Dim guidProduct As Guid = Guid.NewGuid()
或
Guid guidProduct = Guid.NewGuid();
【讨论】:
【参考方案12】:您应该使用一些唯一的 ID,无论是您提到的 GUID 还是其他一些自动生成的密钥。然而,这个数字不应该对用户可见。
这样做的一个巨大好处是,您的所有代码都可以在用户 ID 上运行,但用户名并没有真正与它绑定。然后,用户可以更改他们的名字(我发现这在网站上很有用)。如果您使用电子邮件地址作为用户的登录名,这尤其有用……这对用户来说非常方便(这样他们就不必记住 20 个 ID,以防他们的常用用户 ID 很受欢迎)。
【讨论】:
以上是关于我应该使用用户名还是用户 ID 来引用 ASP.NET 中经过身份验证的用户的主要内容,如果未能解决你的问题,请参考以下文章
一旦用户登录,我应该使用类实例(序列化)还是 Singleton 来存储 userInfo
在 C# 中,我应该按值传递参数并返回相同的变量,还是按引用传递?
我应该合并事实表的列以使其更窄,还是应该通过大量列使其对用户更友好?