如何延长User.Identity的可用属性如何延长User.Identity的可用属性(How t

2019-05-10 10:59发布

我使用MVC5标识2.0用户登录到我的网站,在认证信息存储在SQL数据库中。 Asp.net身份已经以标准的方式被实现为可以在很多在线教程中找到。

在IdentityModels的ApplicationUser类已经扩展到包括一些自定义属性,如整数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,基于用户标识,每一个控制器方法执行时间?

阅读各地我已经看到我需要使用以下方法来获取登录的用户ID等,在网络上

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

然而,OrganizationId不User.Identity可用的属性。 我是否需要延长User.Identity到包括OrganizationId财产? 如果是这样,我怎么去这个问题。

我需要OrganizationId常常出现的原因是,许多表的查询都依赖于OrganizationId检索有关该是关联到登录的用户组织的数据。

Answer 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; }
}

然后,你需要的是创造像这样的扩展方法(我在一个新的扩展文件夹中创建我的):

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;
        }
    }
}

当您创建的ApplicationUser类的身份,只是添加的声明 - > 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 @using. App.Extensions withing一个.cshtml视图文件。

编辑:

你也可以做,以避免在每一个视图中添加using语句是去查看文件夹,找到在那里的Web.config文件。 现在查找<namespaces>标签,有添加扩展名称空间,如下所示:

<add namespace="App.Extensions" />

保存文件,然后你就大功告成了。 现在每个视图会知道你的扩展。

您可以访问的扩展方法:

var orgId = User.Identity.GetOrganizationId();

希望可以帮助任何人:)



Answer 2:

我一直在寻找相同的解决方案和帕维尔给我的回答的99%。 唯一缺少的是我需要的扩展显示被添加以下代码剃刀进入CSHTML(视图)页面的唯一事情:

@using programname.Models.Extensions

我一直在寻找的名字,用户登录后,在我的NavBar的右上角显示。

我以为我会发布此柜面它可以帮助别人,因此,这里是我的代码:

我创建了一个叫做扩展(在我的模型文件夹)一个新的文件夹和帕维尔上述指定创建的新类: 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

然后我加入了变化的代码folling行打算使用用户在砍伐后的名字:

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

也许这可以帮助其他人下了线。



Answer 3:

看看约翰安泰信这个伟大的博客文章: ASP.NET身份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>

然后更新的AccountController的寄存器()方法与新的属性。

    // Add the Address properties:
    user.Address = model.Address;
    user.City = model.City;
    user.State = model.State;
    user.PostalCode = model.PostalCode;


Answer 4:

对于任何人发现这个问题寻找如何在ASP.NET 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>
}


Answer 5:

Dhaust给出了一个很好的方式向属性添加到ApplicationUser类。 纵观OP代码,看来他们可能已经这样做了或正在轨道上做到这一点。 这个问题问

我怎样才能检索到的当前登录用户的OrganizationId财产控制器内? 然而,OrganizationId不User.Identity可用的属性。 我是否需要延长User.Identity到包括OrganizationId财产?

帕维尔提供了一种方式来添加需要使用陈述或添加命名空间的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;


Answer 6:

我还添加了对或扩展其他列到我的AspNetUsers表。 当我想简单地查看这些数据,我发现类似的代码许多例子以上“扩展”等等......这真的让我吃惊的是,你必须编写代码的那些行只是从当前用户获得一对夫妇值。

事实证明,你可以查询AspNetUsers表像任何其他表:

 ApplicationDbContext db = new ApplicationDbContext();
 var user = db.Users.Where(x => x.UserName == User.Identity.Name).FirstOrDefault();


文章来源: How to extend available properties of User.Identity