C# 在Windows身份验证中使用声明转换

C# 在Windows身份验证中使用声明转换,c#,asp.net-core,windows-authentication,claims-based-identity,C#,Asp.net Core,Windows Authentication,Claims Based Identity,在ASP.NET Core 2.1应用程序中使用Windows身份验证。在数据库中,我们有一个User表,该表存储用户及其Sid。它与UserProfile有1-1关系,其中包含我想用于索赔的信息 我添加了一个用于索赔转换的服务: public class UserStatusClaimsTransformation : IClaimsTransformation { private readonly MyDbContext _context; public UserStatu

在ASP.NET Core 2.1应用程序中使用Windows身份验证。在数据库中,我们有一个
User
表,该表存储用户及其Sid。它与
UserProfile
有1-1关系,其中包含我想用于索赔的信息

我添加了一个用于索赔转换的服务:

public class UserStatusClaimsTransformation : IClaimsTransformation
{
    private readonly MyDbContext _context;

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

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        if (principal.Identity is WindowsIdentity identity)
        {
            User user = await _context.User
                .Include(u => u.UserProfile)
                .Where(u => new SecurityIdentifier(u.WindowsSid, 0) == identity.User)
                .SingleOrDefaultAsync();

            if (user != null)
            {
                identity.AddClaim(new Claim("Status", user.UserProfile));
            }
        }

        return principal;
    }
}

以前,这是一个
WindowsPrincipal
,我可以从
\u principal.Identity.Name
获取用户名,但在注册我的索赔转换器后,它是一个
ClaimsPrincipal
,并且
\u principal.Identity.Name
为空。在使用声明转换后,有没有办法将通过DI提供的
IPrincipal
作为
WindowsPrincipal
保存?

我使用ASP.NET MVC Core 2.2,对您来说可能太晚了,但可能对其他人有帮助。然后我开始我的应用程序,我没有找到有用的信息,这是我的自定义建议。它可以工作,您可以使用它:

 public class ClaimsLoader : IClaimsTransformation
{        
    private IUserrolesRepository repository;
    public ClaimsLoader(IUserrolesRepository repo)
    {
        repository = repo;
    }
    public bool ifRoleExist(ClaimsPrincipal principal, string value)
    {
        var ci = (ClaimsIdentity)principal.Identity;
        var claim = principal.FindAll(ci.RoleClaimType);
        foreach (var c in claim)
        {
            if (c.Value == value)
                return true;
        }
        return false;
    }

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
   {            
        var ci = (ClaimsIdentity)principal.Identity;
        List<Userrole> userroles = await repository.Userroles.Include(u => u.R).Include(u => u.U).Where(u => u.U.Uid==principal.Identity.Name.Substring(10)).ToListAsync();

        if (userroles!=null)                {

            foreach (Userrole ur in userroles)
            {
                Claim claim = new Claim(ci.RoleClaimType, ur.Rid); 
                if (!ifRoleExist(principal, ur.Rid))                  
                ci.AddClaim(claim);
            }
        }                     
        return await Task.FromResult(principal);   
    }
}
在ApplicationDbContext中,我也做了一些更改:

public class ApplicationDbContextFactory
       : IDesignTimeDbContextFactory<ApplicationDbContext>
{

    public ApplicationDbContext CreateDbContext(string[] args) =>
        Program.BuildWebHost(args).Services
            .GetRequiredService<ApplicationDbContext>();
}
公共类ApplicationDbContextFactory
:IDesignTimeDbContextFactory
{
公共应用程序DBContext CreateDbContext(字符串[]args)=>
Program.BuildWebHost(args.Services)
.GetRequiredService();
}
最后在启动阶段:

        services.AddSingleton<IClaimsTransformation, ClaimsLoader>();
        services.AddTransient<IUserrolesRepository, EFUserrolesRepository>();
        services.AddMvc();
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);



services.AddAuthentication(Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme);
services.AddSingleton();
services.AddTransient();
services.AddMvc();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddAuthentication(Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme);
Program.cs文件也已更改:

public class Program
{
    public static void Main(string[] args)
    {
        //CreateWebHostBuilder(args).Build().Run();
        BuildWebHost(args).Run();
    }

    /*public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();*/

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseDefaultServiceProvider(options =>
                options.ValidateScopes = false)
            .Build();
}
公共类程序
{
公共静态void Main(字符串[]args)
{
//CreateWebHostBuilder(args.Build().Run();
BuildWebHost(args.Run();
}
/*公共静态IWebHostBuilder CreateWebHostBuilder(字符串[]args)=>
WebHost.CreateDefaultBuilder(args)
.UseStartup()*/
公共静态IWebHost BuildWebHost(字符串[]args)=>
WebHost.CreateDefaultBuilder(args)
.UseStartup()
.UseDefaultServiceProvider(选项=>
options.ValidateScopes=false)
.Build();
}

就这样。它应该会起作用

向上投票。回答得很好,很详细!嘿@evaluator这应该是答案:)。
public partial class Userrole
{
    public string Rid { get; set; }//pk
    public string Uid { get; set; }//pk

    public virtual Role R { get; set; }//fk
    public virtual User U { get; set; }//fk
}
public class ApplicationDbContextFactory
       : IDesignTimeDbContextFactory<ApplicationDbContext>
{

    public ApplicationDbContext CreateDbContext(string[] args) =>
        Program.BuildWebHost(args).Services
            .GetRequiredService<ApplicationDbContext>();
}
        services.AddSingleton<IClaimsTransformation, ClaimsLoader>();
        services.AddTransient<IUserrolesRepository, EFUserrolesRepository>();
        services.AddMvc();
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);



services.AddAuthentication(Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme);
public class Program
{
    public static void Main(string[] args)
    {
        //CreateWebHostBuilder(args).Build().Run();
        BuildWebHost(args).Run();
    }

    /*public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();*/

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseDefaultServiceProvider(options =>
                options.ValidateScopes = false)
            .Build();
}