Как расширить доступные свойства User.Identity
Я использую MVC5 Identity 2.0 для входа на мой сайт, где данные аутентификации хранятся в базе данных SQL. Идентификация Asp.net была реализована стандартным способом, как это можно найти во многих онлайн-учебниках.
Класс ApplicationUser в IdentityModels был расширен, чтобы включить некоторые настраиваемые свойства, такие как целое OrganizationId. Идея заключается в том, что многие пользователи могут быть созданы и назначены для общей организации отношений с базой данных.
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
//Extended Properties
public DateTime? BirthDate { get; set; }
public long? OrganizationId { get; set; }
//Key Mappings
[ForeignKey("OrganizationId")]
public virtual Organization Organization { get; set; }
}
Как я могу получить свойство OrganizationId текущего зарегистрированного пользователя из контроллера?
Доступно ли это через метод, когда пользователь вошел в систему или всегда ли я получаю OrganizationId из базы данных на основе UserId, каждый раз, когда выполняется метод контроллера?
Чтение в Интернете, которое я видел, мне нужно использовать следующее, чтобы получить вход в UserId и т.д.
using Microsoft.AspNet.Identity;
...
User.Identity.GetUserId();
Однако OrganizationId не является свойством, доступным в User.Identity. Нужно ли расширять User.Identity, чтобы включить свойство OrganizationId? Если да, то как это сделать.
Причина, по которой мне нужна организацияId так часто, заключается в том, что многие запросы в таблице зависят от OrganizationId для извлечения данных, относящихся к Организации, связанных с зарегистрированным пользователем.
Ответы
Ответ 1
Всякий раз, когда вы хотите расширить свойства User.Identity с любыми дополнительными свойствами, такими как вопрос выше, сначала добавьте эти свойства в класс ApplicationUser следующим образом:
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
// Your Extended Properties
public long? OrganizationId { get; set; }
}
Тогда вам нужно создать такой метод расширения (создаю мой в новой папке Extensions):
namespace App.Extensions
{
public static class IdentityExtensions
{
public static string GetOrganizationId(this IIdentity identity)
{
var claim = ((ClaimsIdentity)identity).FindFirst("OrganizationId");
// Test for null to avoid issues during local testing
return (claim != null) ? claim.Value : string.Empty;
}
}
}
Когда вы создаете Identity в классе ApplicationUser, просто добавьте Claim → OrganizationId так:
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here => this.OrganizationId is a value stored in database against the user
userIdentity.AddClaim(new Claim("OrganizationId", this.OrganizationId.ToString()));
return userIdentity;
}
После того, как вы добавили претензию и используете свой метод расширения, чтобы сделать его доступным как свойство в вашем User.Identity, добавить оператор using на странице/файле, к которому вы хотите получить доступ
в моем случае: using App.Extensions;
внутри контроллера и @using. App.Extensions
с файлом View.cshtml View.
ИЗМЕНИТЬ:
Что вы также можете сделать, чтобы избежать добавления оператора using в каждом представлении, это перейти в папку "Представления" и найти там файл Web.config.
Теперь найдите тег и добавьте пространство имен расширения так:
<add namespace="App.Extensions">
Сохраните файл, и все готово. Теперь каждый вид будет знать ваши расширения.
Вы можете получить доступ к методу расширения:
var orgId = User.Identity.GetOrganizationId();
Надеюсь, что кто-нибудь поможет:)
Ответ 2
Я искал то же решение, и Павел дал мне 99% ответа. Единственное, чего не хватало для расширения для отображения, было добавление следующего кода Razor на страницу cshtml (view):
@using programname.Models.Extensions
Я искал FirstName, чтобы отобразить его в правом верхнем углу моего NavBar после входа пользователя.
Я думал, что я опубликую это сообщение, это поможет кому-то другому. Итак, вот мой код:
Я создал новую папку под названием Extensions (под моей моделью) и создал новый класс как Pawel, указанный выше: IdentityExtensions.cs
using System.Security.Claims;
using System.Security.Principal;
namespace ProgramName.Models.Extensions
{
public static class IdentityExtensions
{
public static string GetUserFirstname(this IIdentity identity)
{
var claim = ((ClaimsIdentity)identity).FindFirst("FirstName");
// Test for null to avoid issues during local testing
return (claim != null) ? claim.Value : string.Empty;
}
}
}
IdentityModels.cs
:
public class ApplicationUser : IdentityUser
{
//Extended Properties
public string FirstName { get; internal set; }
public string Surname { get; internal set; }
public bool isAuthorized { get; set; }
public bool isActive { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
userIdentity.AddClaim(new Claim("FirstName", this.FirstName));
return userIdentity;
}
}
Затем в моем _LoginPartial.cshtml
(в Views/Shared
Folders) я добавил @using.ProgramName.Models.Extensions
Затем я добавил изменение в строку вывода кода, которая будет использовать имя пользователя First после входа в систему:
@Html.ActionLink("Hello " + User.Identity.GetUserFirstname() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
Возможно, это помогает кому-то еще по очереди.
Ответ 3
Посмотрите это замечательное сообщение в блоге от John Atten:
ASP.NET Identity 2.0: настройка пользователей и ролей
Он имеет отличную пошаговую информацию по всему процессу. Пойдите, прочитайте это:)
Вот некоторые из основ.
Расширить класс ApplicationUser по умолчанию, добавив новые свойства (например, адрес, город, штат и т.д.):
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity>
GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
// Use a sensible display name for views:
[Display(Name = "Postal Code")]
public string PostalCode { get; set; }
// Concatenate the address info for display in tables and such:
public string DisplayAddress
{
get
{
string dspAddress = string.IsNullOrWhiteSpace(this.Address) ? "" : this.Address;
string dspCity = string.IsNullOrWhiteSpace(this.City) ? "" : this.City;
string dspState = string.IsNullOrWhiteSpace(this.State) ? "" : this.State;
string dspPostalCode = string.IsNullOrWhiteSpace(this.PostalCode) ? "" : this.PostalCode;
return string.Format("{0} {1} {2} {3}", dspAddress, dspCity, dspState, dspPostalCode);
}
}
Затем вы добавляете свои новые свойства в свой RegisterViewModel.
// Add the new address properties:
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
Затем обновите представление реестра, чтобы включить новые свойства.
<div class="form-group">
@Html.LabelFor(m => m.Address, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.Address, new { @class = "form-control" })
</div>
</div>
Затем обновите метод Register() на AccountController с новыми свойствами.
// Add the Address properties:
user.Address = model.Address;
user.City = model.City;
user.State = model.State;
user.PostalCode = model.PostalCode;
Ответ 4
DULT дает хороший способ добавить свойство в класс ApplicationUser. Глядя на код OP, похоже, они, возможно, сделали это или были на пути к этому. Вопрос задает
Как я могу получить свойство OrganizationId текущего зарегистрированного пользователя из контроллера? Однако OrganizationId не является свойством, доступным в User.Identity. Мне нужно расширить User.Identity, чтобы включить свойство OrganizationId?
Pawel дает возможность добавить метод расширения, который требует использования операторов или добавления пространства имен в файл web.config.
Однако вопрос задает вопрос, нужно ли вам "расширить" User.Identity, чтобы включить новое свойство. Существует альтернативный способ доступа к объекту без расширения User.Identity. Если вы воспользовались методом DULT, вы можете использовать следующий код в своем контроллере для доступа к новому свойству.
ApplicationDbContext db = new ApplicationDbContext();
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
var currentUser = manager.FindById(User.Identity.GetUserId());
var myNewProperty = currentUser.OrganizationId;