关于身份验证:我应该使用用户名还是用户ID来引用ASP.NET中经过身份验证的用户

关于身份验证:我应该使用用户名还是用户ID来引用ASP.NET中经过身份验证的用户

Should I use the username, or the user's ID to reference authenticated users in ASP.NET

因此,在我的简单学习网站中,我使用了内置的ASP.NET身份验证系统。

我现在添加一个用户表来保存诸如zip,DOB等之类的东西。我的问题是:

  • 在新表中,键应为用户名(字符串)或用户ID,即用户ID在asp_ tables中使用的具有GUID外观的数字。
  • 如果最佳实践是使用该丑陋的GUID,那么有人知道如何获得它吗?它似乎不像名称(System.Web.HttpContext.Current.User.Identity.Name)那样容易访问
  • 如果您建议我不使用(不使用ASP.NET身份验证提供的guid或userName字段),那么如何使用ASP.NET身份验证呢?我喜欢的一种选择是使用用户的电子邮件地址作为登录名,但是如何使ASP.NET身份验证系统使用电子邮件地址而不是用户名? (或者没有什么可做的,只是我决定"知道" userName实际上是一个电子邮件地址吗?
  • 请注意:

    • 我不是在问如何在.NET中获得GUID,我只是将asp_ tables中的userID列称为guid。
    • 用户名在ASP.NET身份验证中是唯一的。

    您应该使用一些唯一的ID,即您提到的GUID或其他一些自动生成的密钥。但是,该号码永远对用户不可见。

    这样做的巨大好处是,所有代码都可以在用户ID上使用,但是用户名并没有真正与其绑定。然后,用户可以更改其名称(我发现这些名称在网站上很有用)。如果您使用电子邮件地址作为用户的登录名,这尤其有用……这对用户来说非常方便(这样,如果普通用户ID受欢迎,他们就不必记住20个ID)。


    您应该使用UserID。
    这是MembershipUser的ProviderUserKey属性。

    1
    Guid UserID = new Guid(Membership.GetUser(User.Identity.Name).ProviderUserKey.ToString());


    如果用户名是唯一的,我建议使用用户名作为表中的主键,这样做有几个很好的理由:

  • 主键将是聚集索引,因此通过用户名搜索用户详细信息将非常快。
  • 它将阻止出现重复的用户名
  • 您不必担心使用两种不同的信息(用户名或GUID)
  • 由于不必查找两位信息,这将使编写代码更加容易。

  • 我会使用一个用户ID。如果要使用用户名,将使"更改用户名"功能非常昂贵。


    这已经很老了,但我只希望发现这些的人注意以下几点:

  • 在访问用户记录时,对aspnet成员数据库进行了优化。当使用loweredusername和applicationid搜索记录时,将使用sql服务器中的聚集索引查找(最佳)。这很有意义,因为我们只有在用户首次发送其凭据时才提供所提供的用户名。

  • guid userid将提供比int更大的索引大小,但这并不重要,因为我们通常一次只检索1条记录(用户),而且就碎片而言,读取次数通常远远大于写入和编辑的次数到用户表-人们只是不会经常更新该信息。

  • 可以编辑创建aspnet成员资格表的regsql脚本,以便代替使用NEWID作为用户ID的默认值,它可以使用NEWSEQUENTIALID()来提供更好的性能(我对此进行了介绍)。

  • 个人资料。创建"新学习网站"的人不应尝试重新发明轮子。我工作过的其中一个网站使用的是现成的aspnet成员资格表(不包括可怕的个人资料系统),而users表包含近200万个用户记录。即使记录数量如此之多,选择仍然很快,因为,正如我首先说的那样,数据库索引着重于降低的用户名+应用程序ID,以对这些记录执行聚集索引查找,并且通常来说,如果sql正在执行聚集索引查找要找到1条记录,即使没有大量记录,只要您不向表中添加列并开始拉回太多数据,就不会有任何问题。

  • 根据系统的实际性能和经验,对我来说,担心该系统的指导是过早的优化。如果您的用户ID有int值,但是由于您的自定义索引设计等原因,系统执行了次优查询,那么系统将无法很好地扩展。微软公司的人在aspnet成员数据库方面做得很好,与将userId更改为int相比,还有很多工作要做。


  • 我想说的是使用UserID,以便仍可以更改用户名而不影响主键。我还将用户名列设置为唯一以停止重复的用户名。

    如果您主要是在用户名而不是用户ID上进行搜索,则使用户名成为聚簇索引,并将主键设置为非聚簇。搜索用户名时,这将为您提供最快的访问权限,但是,如果您将主要搜索UserId,则将其保留为聚簇索引。

    编辑:这也将更好地适合当前的ASP.Net成员资格表,因为它们还将UserID用作主键。


    我同意Palmsey,
    尽管他的代码似乎有一点错误:

    1
    Guid UserID = new Guid(Membership.GetUser(User.Identity.Name)).ProviderUserKey.ToString());

    应该

    1
    Guid UserID = new Guid(Membership.GetUser(User.Identity.Name).ProviderUserKey.ToString());

    我会使用一个自动递增的数字,通常是一个整数。

    您想要使密钥的大小尽可能小。这样可以使索引变小,也可以使任何外键受益。另外,您并没有将数据设计与外部用户数据紧密结合(对于aspnet GUID也是如此)。

    通常,GUID的主键很大,因此不好用,并且插入可能发生在表中的任何数据页上,而不是最后一个数据页上。主要的例外是如果您正在运行多用途复制数据库。在这种情况下,GUID对于密钥非常有用,但是我猜您只有一个数据库,所以这不是问题。


    如果您要使用LinqToSql进行开发,我建议您使用Int作为主键。当我使用非Int字段建立关系时,即使nvarchar(x)字段具有使其成为唯一字段的约束,我也会遇到很多问题。

    我不确定这是LinqToSql中的已知错误还是什么,但是我在当前项目中遇到了问题,因此我不得不在几张表上交换PK和FK。


    我将在我的代码中使用guid,并且已经提到过将电子邮件地址用作用户名。毕竟,对于用户而言,它已经是独特且令人难忘的。甚至放弃了Guid(可辩论)。

    如果您的代码中使用了聚集索引,则有人提到在GUID上使用聚集索引。我会避免这种情况,尤其是在INSERT高的情况下;每当您插入一条记录时,索引将被重建。尽管由于仅附加了新记录,所以聚集索引在自动增量ID上也能很好地工作。


    我也同意Mike Stone。我的公司最近为外部客户(与通过LDAP进行身份验证的内部用户相对)实现了一个新的用户表。对于外部用户,我们选择将GUID存储为主键,并将用户名存储为varchar,并且在用户名字段上具有唯一性约束。

    另外,如果您要存储密码字段,我强烈建议您将密码以盐化,哈希散列的形式存储在数据库中。这样,如果有人要入侵您的数据库,则他们将无权访问您客户的密码。


    我同意迈克·斯通。我还建议仅在要跟踪大量数据的情况下使用GUID。否则,一个简单的自动递增整数(Id)列就足够了。

    如果您确实需要GUID,那么.NET足够可爱,您可以通过简单的方法获得它。

    1
    Dim guidProduct As Guid = Guid.NewGuid()

    要么

    1
    Guid guidProduct = Guid.NewGuid();


    推荐阅读