Как расширить доступные свойства 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 текущего пользователя, вошедшего в систему, из контроллера? Доступно ли это через метод после входа пользователя в систему или у меня всегда есть возможность извлекать OrganId из базы данных на основе UserId каждый раз, когда выполняется метод контроллера?

Читая в Интернете, я видел, что мне нужно использовать следующее, чтобы войти в систему под UserId и т. д.

using Microsoft.AspNet.Identity;
...
User.Identity.GetUserId();

Однако OrganizationId не является свойством, доступным в User.Identity. Нужно ли расширять User.Identity, чтобы включить свойство OrganizationId? Если да, то как мне это сделать.

Причина, по которой мне так часто нужен OrganizationId, заключается в том, что многие запросы к таблицам зависят от OrganizationId для получения данных, относящихся к Организации, связанных с вошедшим в систему пользователем.

111 голосов | спросил RobHurd 5 FebruaryEurope/MoscowbThu, 05 Feb 2015 05:48:50 +0300000000amThu, 05 Feb 2015 05:48:50 +030015 2015, 05:48:50

6 ответов


0

Всякий раз, когда вы хотите расширить свойства 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 -> Организация вроде бы так:

    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 App.Extensions; в контроллере и @using. App.Extensions без файла .cshtml View.

РЕДАКТИРОВАТЬ:

Чтобы избежать добавления оператора using в каждое представление, вы также можете перейти в папку Views и найти там файл Web.config. Теперь найдите тег <namespaces> и добавьте туда пространство расширений следующим образом:

<add namespace="App.Extensions" />

Сохраните файл, и все готово. Теперь каждый View будет знать о ваших расширениях.

Вы можете получить доступ к методу расширения:

var orgId = User.Identity.GetOrganizationId();

Надеюсь, это кому-нибудь поможет:)

ответил Pawel 10 J000000Friday15 2015, 14:49:13
0

Я искал такое же решение, и Павел дал мне 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 Папки) Я добавил @using.ProgramName.Models.Extensions

Затем я добавил изменение в следующую строку кода, которая собиралась использовать имя пользователя после входа в систему:

@Html.ActionLink("Hello " + User.Identity.GetUserFirstname() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })

Возможно, это поможет кому-то еще.

ответил AxleWack 12 Maypm16 2016, 13:22:01
0

Посмотрите эту замечательную запись в блоге Джона Аттена: 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;
ответил Dhaust 5 FebruaryEurope/MoscowbThu, 05 Feb 2015 07:21:43 +0300000000amThu, 05 Feb 2015 07:21:43 +030015 2015, 07:21:43
0

Dhaust дает хороший способ добавить свойство в класс ApplicationUser. Глядя на код OP, кажется, что они, возможно, сделали это или собирались сделать это. Вопрос задает

  

Как я могу получить свойство OrganizationId текущего пользователя, вошедшего в систему, из контроллера? Однако OrganizationId не является свойством, доступным в User.Identity. Нужно ли расширять User.Identity, чтобы включить свойство OrganizationId?

Pawel позволяет добавить метод расширения, который требует использования операторов или добавления пространства имен в файл web.config.

Однако возникает вопрос, нужно ли вам "расширять" User.Identity, чтобы включить новое свойство. Существует альтернативный способ доступа к свойству без расширения User.Identity. Если вы использовали метод Dhaust, вы можете использовать следующий код в вашем контроллере для доступа к новому свойству.

ApplicationDbContext db = new ApplicationDbContext();
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
var currentUser = manager.FindById(User.Identity.GetUserId());
var myNewProperty = currentUser.OrganizationId;
ответил codeMethod 15 FriEurope/Moscow2017-12-15T02:11:48+03:00Europe/Moscow12bEurope/MoscowFri, 15 Dec 2017 02:11:48 +0300 2017, 02:11:48
0

Для любого, кто найдет этот вопрос в поисках доступа к пользовательским свойствам в ASP.NET Core 2.1, это гораздо проще: у вас будет UserManager, например, в _LoginPartial.cshtml, а затем вы можете просто сделать это (при условии, что «ScreenName» - это свойство, которое вы добавили в свой собственный AppUser, который наследует от IdentityUser):

@using Microsoft.AspNetCore.Identity

@using <namespaceWhereYouHaveYourAppUser>

@inject SignInManager<AppUser> SignInManager
@inject UserManager<AppUser> UserManager

@if (SignInManager.IsSignedIn(User)) {
    <form asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Action("Index", "Home", new { area = "" })" 
          method="post" id="logoutForm" 
          class="form-inline my-2 my-lg-0">

        <ul class="nav navbar-nav ml-auto">
            <li class="nav-item">
                <a class="nav-link" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">
                    Hello @((await UserManager.GetUserAsync(User)).ScreenName)!
                    <!-- Original code, shows Email-Address: @UserManager.GetUserName(User)! -->
                </a>
            </li>
            <li class="nav-item">
                <button type="submit" class="btn btn-link nav-item navbar-link nav-link">Logout</button>
            </li>
        </ul>

    </form>
} else {
    <ul class="navbar-nav ml-auto">
        <li class="nav-item"><a class="nav-link" asp-area="Identity" asp-page="/Account/Register">Register</a></li>
        <li class="nav-item"><a class="nav-link" asp-area="Identity" asp-page="/Account/Login">Login</a></li>
    </ul>
}
ответил Jashan 23 J000000Monday18 2018, 17:54:15
0

Я также добавил или расширил дополнительные столбцы в моей таблице AspNetUsers. Когда я хотел просто просмотреть эти данные, я нашел много примеров, таких как приведенный выше код с «Расширениями» и т. Д. Это действительно поразило меня, что вам пришлось писать все эти строки кода, чтобы получить пару значений от текущих пользователей.

Оказывается, вы можете запросить таблицу AspNetUsers, как и любую другую таблицу:

 ApplicationDbContext db = new ApplicationDbContext();
 var user = db.Users.Where(x => x.UserName == User.Identity.Name).FirstOrDefault();
ответил Anthony Griggs 25 J0000006Europe/Moscow 2018, 09:38:55

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132