48

(使用VS2013 RTW,ASP.NET MVC5)

我看过很多关于如何在使用 ASP.NET 标识时向 ApplicationUser 类(和表)添加属性的文档。但是我还没有看到任何关于如何拥有一个单独的表的文档,该表的内容通过外键映射到 ApplicationUser 表。

我已经成功地派生了我自己的 Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext,现在我自己的“UserPreferences”表与我的 SQL Server 数据库中的各种“AspNet*”表和谐共存。但我不清楚获取当前用户 ID 以便将新行写入“UserPreferences”表的最佳方法。请注意,该项目是 ASP.NET MVC,但我已经添加(并且正在其中工作)一个 Web API 控制器。

我有一个可行的解决方案,即:

            var uman = new Microsoft.AspNet.Identity.UserManager<Microsoft.AspNet.Identity.EntityFramework.IdentityUser>(new Microsoft.AspNet.Identity.EntityFramework.UserStore<Microsoft.AspNet.Identity.EntityFramework.IdentityUser>(new App1.Data.App1DbContext()));

            var uident = User.Identity;

            var userobject = uman.FindByNameAsync(uident.Name);

            var userid = userobject.Result.Id;
            // (Perform new row creation including the userid we just looked up

考虑 AspNetUsers 表(由 Identity 框架定义)由以下字段组成:

-id (PK, nvarchar(128) - seems to contain a GUID, not sure why not an autoincrement integer, but I assume there are reasons for this)
-Username (nvarchar(max))
-PasswordHash (nvarchar(max))
-SecurityStamp (nvarchar(max))

我认为 id 字段(不是用户名)是此表中要引用的正确字段。(我在想一个用户可能会更改他/她的用户名,然后其他人可以假设另一个用户的用户名,这就是为什么两个字段都可能存在的原因。)那么,我需要获取当前用户的 ID 以存储在“UserPreferences”表,这就是上面的代码所做的。但是必须进行此查找似乎效率低下。

重要的一点是,在 System.Web.Mvc.Controller 的上下文中,我可以这样做:

User.Identity.GetUserId()
(Runtime type of User.Identity: System.Security.Principal.GenericIdentity)

但是在 System.Web.Http.ApiController (Web API) 的上下文中,我不能,因为该方法不存在(User.Identity 的运行时类型:System.Security.Claims.ClaimsIdentity),这就是我必须依赖的原因:

User.Identity.Name

并进行额外的查找以将名称转换为 ID。有人对如何改进有任何建议吗?我是否正在以正确的方式将用户数据写入单独的表?

4

5 回答 5

59

您应该能够通过identity 1.0 RTW 包中的相同扩展方法在 MVC 控制器和 Web api 控制器上获取用户 ID 。

这是身份包的扩展:

namespace Microsoft.AspNet.Identity
{
    public static class IdentityExtensions
    {
        public static string FindFirstValue(this ClaimsIdentity identity, string claimType);
        public static string GetUserId(this IIdentity identity);
        public static string GetUserName(this IIdentity identity);
    }
}

IIdentity 是所有身份类型的基本接口。您可能需要添加“使用 Microsoft.AspNet.Identity”才能查看扩展方法。

顺便说一句:关于为用户添加外部表,为什么不使用 ApplicationUser 并将导航属性添加到 UserPreference 以让 EF 处理它们的关系?那会更容易。

于 2013-10-21T22:57:00.337 回答
46
ClaimsIdentity identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, UserID));

ClaimTypes.NameIdentifier是函数的声明User.Identity.GetUserId()

于 2014-10-19T18:11:56.877 回答
15

我正在使用索赔基础方法:

private ApplicationUser GetCurrentUser(ApplicationDbContext context)
{
  var identity = User.Identity as ClaimsIdentity;
  Claim identityClaim = identity.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);

  return context.Users.FirstOrDefault(u => u.Id == identityClaim.Value);
}
于 2015-12-11T13:03:48.067 回答
3

最佳答案的简短描述:

  1. Install-Package Microsoft.AspNet.Identity.Core -Version 2.2.1
  2. var userId = User.Identity.GetUserId();
于 2017-09-03T02:46:59.787 回答
0

尝试了@Mastenka 的答案,但它什么也没给我。我检查了 ClaimsIdentity 并且有声明类型“UserName”,因此,我通过使用“UserName”作为 ClaimsType 来获取用户名。希望有人能提供更多有关它的信息。“ClaimTypes.NameIdentifier”没有效果看起来很奇怪。(ApiController, ASP MVC API)

var userName = ((ClaimsIdentity)RequestContext.Principal.Identity).Claims.FirstOrDefault(cl => cl.Type == "UserName")?.Value;
于 2019-08-06T14:10:01.420 回答