簡體   English   中英

使用Windows身份驗證聲明轉換

[英]Using Claims Transformation with Windows Authentication

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

我的問題是,一旦注冊了這個服務,在管道中其他地方訪問的IPrincipal現在是一個ClaimsPrincipal而不是WindowsPrincipal 例如,在MyDbContext我通過DI注入IPrincipal

public MyDbContext(DbContextOptions<MyDbContext> options, IPrincipal principal) : base(options)
{
    _principal = principal;
}

以前,這是一個WindowsPrincipal ,我可以從_principal.Identity.Name獲取用戶_principal.Identity.Name ,但在注冊我的Claims Transformer后,它是一個ClaimsPrincipal_principal.Identity.Name為null。 在使用聲明轉換后,有沒有辦法通過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,而是使用repository,這是存儲庫接口:

    public interface IUserrolesRepository
{
    IQueryable<Userrole> Userroles { get; }

}

和EFUserRepository類:

public class EFUserrolesRepository : IUserrolesRepository
{
    private ApplicationDbContext context;

    public EFUserrolesRepository(ApplicationDbContext ctx)
    {
        context = ctx;
    }

    public IQueryable<Userrole> Userroles => context.Userrole;

}

這是我的Userrole類(以防萬一有人需要它):

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
}

在ApplicationDbContext中我也做了一些更改:

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

和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();
}

而已。 它應該工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM