C# 如何在ASP.NET Core中向Windows身份验证添加角色

C# 如何在ASP.NET Core中向Windows身份验证添加角色,c#,asp.net-core,asp.net-core-mvc,windows-authentication,roles,C#,Asp.net Core,Asp.net Core Mvc,Windows Authentication,Roles,我在visual studio 2015中使用windows身份验证创建了一个asp.net核心项目。我不知道如何将角色添加到标识中 我有一个包含windows帐户用户名的表。当用户打开网站时,用户将被添加到标识中(我假设会发生这种情况,因为我可以按user.Identity.Name显示用户名),我想从另一个表中拉出角色并将它们分配给用户,这可能吗?或者有没有更好的方法?(为什么?如何?) 我找不到任何与windows身份验证相关的示例,但我已经阅读了文档并浏览了一遍。这是我用来检查用户是否在

我在visual studio 2015中使用windows身份验证创建了一个asp.net核心项目。我不知道如何将角色添加到标识中

我有一个包含windows帐户用户名的表。当用户打开网站时,用户将被添加到标识中(我假设会发生这种情况,因为我可以按user.Identity.Name显示用户名),我想从另一个表中拉出角色并将它们分配给用户,这可能吗?或者有没有更好的方法?(为什么?如何?)


我找不到任何与windows身份验证相关的示例,但我已经阅读了文档并浏览了一遍。这是我用来检查用户是否在角色\组中的工作代码,请在空闲时使用

using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Security.Principal;

namespace Santander.IsUserInGroupOrRole_cs
{

public class IsUserInRole
{
    public static bool IsInGroup(string groupName)
    {
        var myIdentity = GetUserIdWithDomain();
        var myPrincipal = new WindowsPrincipal(myIdentity);
        return myPrincipal.IsInRole(groupName);
    }

    public bool IsInGroup(List<string> groupNames)
    {
        var myIdentity = GetUserIdWithDomain();
        var myPrincipal = new WindowsPrincipal(myIdentity);

        return groupNames.Any(group => myPrincipal.IsInRole(group));
    }

    public static WindowsIdentity GetUserIdWithDomain()
    {
        var myIdentity = WindowsIdentity.GetCurrent();
        return myIdentity;
    }

    public static string GetUserId()
    {
        var id = GetUserIdWithDomain().Name.Split('\\');
        return id[1];
    }

    public static string GetUserDisplayName()
    {
        var id = GetUserIdWithDomain().Name.Split('\\');

        var dc = new PrincipalContext(ContextType.Domain, id[0]);
        var adUser = UserPrincipal.FindByIdentity(dc, id[1]);
        return adUser.DisplayName;

    }
}
}
使用System.Collections.Generic;
使用System.DirectoryServices.AccountManagement;
使用System.Linq;
使用System.Security.Principal;
命名空间Santander.IsUserInGroupOrRole_cs
{
公共类IsUserInRole
{
公共静态bool IsInGroup(字符串groupName)
{
var myIdentity=GetUserIdWithDomain();
var myPrincipal=新的WindowsPrincipal(myIdentity);
返回myPrincipal.IsInRole(groupName);
}
公共布尔ISingGroup(列出组名)
{
var myIdentity=GetUserIdWithDomain();
var myPrincipal=新的WindowsPrincipal(myIdentity);
返回groupNames.Any(group=>myPrincipal.IsInRole(group));
}
公共静态WindowsIdentity GetUserIdWithDomain()
{
var myIdentity=WindowsIdentity.GetCurrent();
返回我的身份;
}
公共静态字符串GetUserId()
{
var id=GetUserIdWithDomain().Name.Split('\\');
返回id[1];
}
公共静态字符串GetUserDisplayName()
{
var id=GetUserIdWithDomain().Name.Split('\\');
var dc=新的PrincipalContext(ContextType.Domain,id[0]);
var adUser=UserPrincipal.FindByIdentity(dc,id[1]);
返回adUser.DisplayName;
}
}
}

使用Windows身份验证,角色来自Active Directory,而不是数据库

您可以使用声明转换更改每个请求的入站标识,以从数据库中提取额外的角色

public class ClaimsTransformer : IClaimsTransformer
{
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        ((ClaimsIdentity)principal.Identity).AddClaim(
            new Claim("ExampleClaim", "true"));
        return Task.FromResult(principal);
    }
}

请注意,在当前版本中,没有DI支持,因此如果数据库信息在DI中,您必须手动从DI中取出它。

对于任何感兴趣的人,下面是一个简单的示例,说明如何将EF DBContext注入自定义ClaimsTransformer并添加一些自定义角色声明

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
  services.AddScoped<IClaimsTransformer, MyClaimsTransformer>();

  services.AddMvc();

  services.AddDbContext<MyDbContext>(options => options.UseSqlServer(
      Configuration.GetConnectionString("MyConnStringSetting")
    ));

  (...)
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
  app.UseClaimsTransformation(context =>
  {
    var transformer = context.Context.RequestServices.GetRequiredService<IClaimsTransformer>();
    return transformer.TransformAsync(context);
  });

  (...)
}
public void配置服务(IServiceCollection服务)
{
services.addScope();
services.AddMvc();
services.AddDbContext(options=>options.UseSqlServer(
Configuration.GetConnectionString(“MyConnStringSetting”)
));
(...)
}
公共void配置(IApplicationBuilder应用程序、IHostingEnvironment环境、iLogger工厂)
{
app.UseClaimsTransformation(上下文=>
{
var transformer=context.context.RequestServices.GetRequiredService();
返回transformer.TransformAsync(上下文);
});
(...)
}
MyClaimsTransformer.cs

public class MyClaimsTransformer : IClaimsTransformer
{
  private readonly MyDbContext _context;

  public MyClaimsTransformer(MyDbContext context)
  {
    _context = context;
  }

  public Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
  {
    var identity = (ClaimsIdentity)context.Principal.Identity;
    var userName = identity.Name;
    var roles = _context.Role.Where(r => r.UserRole.Any(u => u.User.Username == userName)).Select(r => r.Name);
    foreach (var role in roles)
    {
      var claim = new Claim(ClaimTypes.Role, role);
      identity.AddClaim(claim);
    }
    return Task.FromResult(context.Principal);
  }
}
公共类MyClaimsTransformer:IClaimsTransformer
{
私有只读MyDbContext\u context;
公共MyClaimsTransformer(MyDbContext上下文)
{
_上下文=上下文;
}
公共任务TransformAsync(ClaimTransformationContext)
{
var identity=(ClaimsIdentity)context.Principal.identity;
var userName=identity.Name;
var roles=_context.Role.Where(r=>r.UserRole.Any(u=>u.User.Username==Username))。选择(r=>r.Name);
foreach(角色中的var角色)
{
var索赔=新索赔(ClaimTypes.Role,Role);
标识。添加索赔(索赔);
}
返回Task.FromResult(context.Principal);
}
}

您能否显示您的代码,包括您的using语句。我猜在这个阶段,你现在还没有参考过
System.DirectoryServices
。当您这样做时,您可以通过相对ease@SimonPrice我没有代码来表示抱歉,我放弃了我的每一次尝试,因为它不起作用。但给你一个想法,这只是一个启用了windows身份验证的新项目,从那以后,只有我痛苦和失败。我一定会查“System.DirectoryServices”,还有什么是AD?AD是Active Directory。你想要实现的项目的想法是什么?@SimonPrice如果一家公司雇佣了大约100名员工,他们负责管理他们的windows帐户(状态/信息/等等)。为内部使用的网站/应用程序建立一个单独的帐户对他们来说是一个糟糕的解决方案。因此,我正在研究是否可以只使用windows帐户,并将角色应用于它们。以及我能从他们联系的账户中获取的实际信息。我是网络开发新手,所以一切都很混乱。来这里和我聊天,你能展示/解释如何在连接之前或之后向windows帐户添加角色吗?如果你能在我昨天晚上20:00发送的聊天链接中找到,那么是的,我可以告诉你上面的代码针对用户所属的组(而不是角色)执行检查。github上的相关问题-@blowdart在.netcore 2.0中是否起作用?我没有找到UseClaimsTransformation。看起来这在2.0中被彻底修改了一点。请参阅。该类型现在已更改为ICLAIMS转换。
public class MyClaimsTransformer : IClaimsTransformer
{
  private readonly MyDbContext _context;

  public MyClaimsTransformer(MyDbContext context)
  {
    _context = context;
  }

  public Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
  {
    var identity = (ClaimsIdentity)context.Principal.Identity;
    var userName = identity.Name;
    var roles = _context.Role.Where(r => r.UserRole.Any(u => u.User.Username == userName)).Select(r => r.Name);
    foreach (var role in roles)
    {
      var claim = new Claim(ClaimTypes.Role, role);
      identity.AddClaim(claim);
    }
    return Task.FromResult(context.Principal);
  }
}