ASP.Net 核心 2.1 注册自定义声明主体



我正在创建一个Windows身份验证应用程序,但角色位于自定义数据库中而不是AD上,因此我创建了一个自定义ClaimPrincipal来覆盖User.IsInRole((函数,该函数通常会在AD中查找角色。

但是,在运行应用程序时,它似乎仍然使用原始代码,而不是我的CustomClaimsPrincipal。 我收到错误"主域和受信任域之间的信任关系失败"。

在 ASP.Net MVC 5中,我使用了自定义角色提供程序,这基本上是我在这里尝试复制的内容。

CustomClaimsPrincipal.cs

public class CustomClaimsPrincipal : ClaimsPrincipal
{
private readonly ApplicationDbContext _context;
public CustomClaimsPrincipal(ApplicationDbContext context)
{
_context = context;
}
public override bool IsInRole(string role)
{
var currentUser = ClaimsPrincipal.Current.Identity.Name;
IdentityUser user = _context.Users.FirstOrDefault(u => u.UserName.Equals(currentUser, StringComparison.CurrentCultureIgnoreCase));
var roles = from ur in _context.UserRoles.Where(p => p.UserId == user.Id)
from r in _context.Roles
where ur.RoleId == r.Id
select r.Name;
if (user != null)
return roles.Any(r => r.Equals(role, StringComparison.CurrentCultureIgnoreCase));
else
return false;
}
}

启动.cs

services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<ApplicationDbContext>();
services.AddScoped<ClaimsPrincipal,CustomClaimsPrincipal>();

不确定 Startup.cs 中的上述代码是否是覆盖 ClaimPrincipal 的正确方法,因为我是 .Net Core 框架的新手。

我想我会以不同的方式解决这个问题:与其尝试让ClaimsPrincipal实例与数据库通信以确定它们是否属于特定角色,不如修改ClaimsPrincipal并在ClaimsPrincipal实例中添加它们所属的角色。

为此,我将使用一个不幸的是没有充分记录的功能。身份验证管道公开一个扩展点,在该扩展点中,身份验证完成后,可以转换已创建的ClaimsPrincipal实例。这可以通过IClaimsTransformation接口完成。

代码可能如下所示:

public class Startup
{
public void ConfigureServices(ServiceCollection services)
{
// Here you'd have your registrations
services.AddTransient<IClaimsTransformation, ClaimsTransformer>();
}
}
public class ClaimsTransformer : IClaimsTransformation
{
private readonly ApplicationDbContext _context;
public ClaimsTransformer(ApplicationDbContext context)
{
_context = context;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
var existingClaimsIdentity = (ClaimsIdentity)principal.Identity;
var currentUserName = existingClaimsIdentity.Name;
// Initialize a new list of claims for the new identity
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, currentUserName),
// Potentially add more from the existing claims here
};
// Find the user in the DB
// Add as many role claims as they have roles in the DB
IdentityUser user = await _context.Users.FirstOrDefaultAsync(u => u.UserName.Equals(currentUserName, StringComparison.CurrentCultureIgnoreCase));
if (user != null)
{
var rolesNames = from ur in _context.UserRoles.Where(p => p.UserId == user.Id)
from r in _context.Roles
where ur.RoleId == r.Id
select r.Name;
claims.AddRange(rolesNames.Select(x => new Claim(ClaimTypes.Role, x)));
}
// Build and return the new principal
var newClaimsIdentity = new ClaimsIdentity(claims, existingClaimsIdentity.AuthenticationType);
return new ClaimsPrincipal(newClaimsIdentity);
}
}

为了完全披露,TransformAsync方法将在每次进行身份验证过程时运行,因此很可能在每个请求上运行,这也意味着它将在每个请求上查询数据库以获取登录用户的角色。

与修改ClaimsPrincipal的实现相比,使用此解决方案的优势在于,ClaimsPrincipal现在是的,并且不绑定到您的数据库。只有身份验证管道知道它,这使得测试之类的事情变得更容易,例如,使用特定角色新建ClaimsPrincipal,以确保他们有权或无权访问特定操作,而不会绑定到数据库。

相关内容

  • 没有找到相关文章

最新更新