带有 Windows 身份验证的 ASP.NET Core 2.1 自定义 RoleProvider

Posted

技术标签:

【中文标题】带有 Windows 身份验证的 ASP.NET Core 2.1 自定义 RoleProvider【英文标题】:ASP.NET Core 2.1 Custom RoleProvider with Windows Authentication 【发布时间】:2019-01-23 04:34:40 【问题描述】:

我正在将应用程序从 ASP.Net MVC 5 框架迁移到新的 .Net Core 2.1。

我在 MVC 5 项目中使用了带有自定义 RoleProvider 的 Windows 身份验证,如下面的链接所示。

ASP.NET MVC How to create a custom role provider

我如何在 Core 2.1 中完成同样的任务,因为它似乎不包含 RoleProvider 功能?

我遇到的每个示例都使用带有 IdentityUser 和 IdentityRole 的个人帐户。

我的用户和角色自定义表:

public class User

    public User()  UserRoles = new HashSet<UserRole>(); 

    [Key]
    public string Id  get; set; 

    [StringLength(50)]
    [Required]
    public string Logon  get; set;  //The users Active Directory Username

    public bool Active  get; set; 

    public ICollection<UserRole> UserRoles  get; set; 




public class Role

    public Role()  UserRoles = new HashSet<UserRole>(); 

    [Key]
    public string Id  get; set; 

    public string Name  get; set; 

    public ICollection<UserRole> UserRoles  get; set; 

编辑:

我添加了一个 CustomClaimsPrincipal ,如下所示:

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));
            //(ApplicationUser)_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;
    

并添加到 Startup.cs

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

services.AddScoped<ClaimsPrincipal, CustomClaimsPrincipal>();

但它似乎仍然采用原始的 ClaimsPrincipal IsInRole 函数而不是覆盖,我相信这就是我收到错误消息“主域和受信任域之间的信任关系失败”的原因。

【问题讨论】:

您提到的副本是针对使用 Windows 身份验证中未使用的 IdentityUser 的个人帐户 【参考方案1】:

我遇到了同样的问题 - 帖子中给出的解决方案没有帮助,但 cmets 为我指明了正确的方向。您需要向您的 ClaimsPrincipal 添加声明。

第 1 步:创建 ClaimsTransformer - 替换“Admin”并为您从数据库中获取的每个角色添加单独的声明

using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;

public class ClaimsTransformer : IClaimsTransformation
 
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    
        var ci = (ClaimsIdentity) principal.Identity;
        var c = new Claim(ci.RoleClaimType, "Admin");
        ci.AddClaim(c);
        return Task.FromResult(principal);
    

第 2 步:将您的 ClaimsTransformer 添加到 Startup.cs 的 ConfigureServices 方法中

services.AddAuthentication(Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme);
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSpaStaticFiles(configuration =>

    configuration.RootPath = "ClientApp/dist";
);

services.AddSingleton<IClaimsTransformation, ClaimsTransformer>();

第 3 步:您现在可以在控制器中添加基于角色的授权属性

[Authorize(Roles = "Admin")]
[HttpGet("[action]/id")]        
public User GetUser([FromRoute] int id)

    UserLogic ul = new UserLogic();
    return ul.GetUser(id);

【讨论】:

你是如何让它工作的?我做了同样的事情,我得到“主域和受信任域之间的信任关系失败”? @CoderSteve 你有想过这个吗?我遇到了同样的问题。【参考方案2】:

在 net core 中管理自定义权限通常是通过声明来完成的。您可以通过 aspnet 身份 (How to add claims in ASP.NET Identity) 执行此操作,也可以编写自己的中间件。

收到声明后,您需要创建政策。这是通过ConfigureServices 方法中的Startup.cs 类完成的。

services.AddAuthorization(options =>
        
            options.AddPolicy("HR", policy => policy.RequireClaim("HRTeam"));
            options.AddPolicy("Helpdesk", policy => policy.RequireClaim("HelpdeskTeam"));
        );

然后用Authorize 属性装饰你的控制器/动作

[Authorize(Policy="Helpdesk")]
public class HelpDeskController : Controller

【讨论】:

我已添加声明,但仍无法按预期工作。你能看到上面的编辑吗? 我认为您不需要覆盖 ClaimsPrincipal,您需要在身份验证时向其添加 Claims 声明和角色(无论是否有策略)都是管理授权的有效方案。 @ste-fu 你能扩展一下吗?我遇到了同样的问题,我不确定您所说的“在您进行身份验证时添加声明”是什么意思?目前我使用此行启用 Windows 身份验证: services.AddAuthentication(Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme); 我们可以像这样添加多个策略 [Authorize(Policy="Helpdesk,Supervisor")] 吗?

以上是关于带有 Windows 身份验证的 ASP.NET Core 2.1 自定义 RoleProvider的主要内容,如果未能解决你的问题,请参考以下文章

应用级别内联网用户的 Windows 身份验证(带有 VB 的 ASP.NET)

ASP.NET Core:带有 OPTIONS 异常的 Windows 身份验证(CORS 预检)

带有 Angular 6 的 Asp.Net Core 2.1 中的 Windows 身份验证 - Chrome 连续登录提示

如何在 ASP.NET Core 中将角色添加到 Windows 身份验证

无法使用 Windows 身份验证发布到 asp.net core web api

在 HTTPS 上使用 Windows 身份验证首次调用 ASP.NET Core 2.0 Web API 在 Chrome 中总是失败