Идентификация ASP.NET(OWIN): как получить UserID с контроллера веб-API?
(Использование VS2013 RTW, ASP.NET MVC5)
Я видел много документации о том, как добавлять свойства в класс ApplicationUser (и таблицу) при использовании идентификатора ASP.NET. Но я не видел никакой документации о том, как иметь отдельную таблицу с контентом, который сопоставляется с таблицей ApplicationUser через внешний ключ.
Я успешно получил свой собственный файл Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext, и теперь моя собственная таблица "UserPreferences" сосуществует в гармонии с различными таблицами "AspNet *" в моей базе данных SQL Server. Но я не знаю, как наилучшим образом получить текущий идентификатор пользователя, чтобы написать новую строку в таблице "UserPreferences". Обратите внимание, что проект ASP.NET MVC, но я добавил (и работаю внутри) контроллер веб-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 (как определено Framework 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 (а не имя пользователя) является правильным полем для ссылки в этой таблице. (Я думал, что пользователь может изменить свое имя пользователя, а кто-то другой может затем принять другое имя пользователя пользователя, поэтому оба поля там вероятны.) Итак, мне нужно получить текущий идентификатор пользователя для хранения в Таблица 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. Есть ли у кого-нибудь предложения по улучшению этого? Подхожу ли я к задаче записи пользовательских данных для правильного разделения таблиц?
Ответы
Ответ 1
Вы должны иметь возможность получить идентификатор пользователя как на контроллере MVC, так и на веб-api-контроллере одним и тем же методом расширения в identity 1.0 RTW-пакете.
Вот расширения из пакета удостоверений:
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 - это базовый интерфейс для всех типов удостоверений. Вам может потребоваться добавить "using Microsoft.AspNet.Identity", чтобы увидеть метод расширения.
BTW: относительно добавления внешней таблицы для пользователя, почему бы не использовать ApplicationUser и добавить свойство навигации в UserPreference, чтобы позволить EF обрабатывать их отношения? Это будет проще.
Ответ 2
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()
Ответ 3
Я использую подход с основанием претензии:
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);
}
Ответ 4
Краткое описание наилучшего ответа:
-
Install-Package Microsoft.AspNet.Identity.Core -Version 2.2.1
-
var userId = User.Identity.GetUserId();
Ответ 5
Простое решение:
var user = await UserManager.FindAsync(model.UserName, model.Password);
и свойство user.id будет содержать то, что вам нужно.