[英]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.