c# - .NET Core 3.0 声明转换

标签 c# .net-core authorization windows-authentication

以前在 .NET Framework 中,我使用了自定义 RoleProvider与 Windows 身份验证一起提供针对当前主体的自定义角色,而不是使用 Active Directory 组。

所以,目标是能够使用装饰[Authorize(Roles="")]角色来自数据库而不是事件目录的属性(或两者的组合都可以)。

为了在核心中实现这一点,我相信我需要使用 IClaimsTransformation分配所讨论的角色声明here .

在这里,我只是想添加一个角色“管理员”,但是当我使用 [Authorize(Roles = "Admin")] 时我收到 403 Unauthorized 响应。

启动.cs

services.AddRazorPages();
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddSingleton<IClaimsTransformation, ClaimsTransformer>();
-------
app.UseAuthorization();

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

当我调用 User.IsInRole() 时,这很烦人当我检查声明时我可以看到该组,因此它正在被添加,但是它不适用于 Authorize 属性。任何意见,将不胜感激。

最佳答案

设法使用 ClaimsTransformer 解决此问题旁边有一个自定义 TypeFilterAttribute
ClaimsTransformer.cs

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var identity = (WindowsIdentity)principal.Identity;

        Guid userGuid;

        SecurityIdentifier sid = identity.User;

        using (DirectoryEntry userDirectoryEntry = new DirectoryEntry("LDAP://<SID=" + sid.Value + ">"))
        {
            userGuid = userDirectoryEntry.Guid;
        }

        UserAccount user = null;

        if (userGuid != Guid.Empty)
            user = await db.UserAccounts.Where(x => x.GUID == userGuid).SingleOrDefaultAsync();

        if (user == null)
            return principal;

        if (user.Historic)
            return principal;


        var claims = new List<Claim>();
        foreach (var role in user?.UserAccountGroups)
        {
            claims.Add(new Claim(ClaimTypes.GroupSid, role.Group.Name));
        };

        identity.AddClaims(claims);

        return principal;
    }

GroupsAttribute.cs
    [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
public class GroupsAttribute : TypeFilterAttribute
{
    public GroupsAttribute(string groups) : base(typeof(ClaimRequirementFilter))
    {
        Arguments = new object[] { groups };
    }
}

public class ClaimRequirementFilter : IAuthorizationFilter
{
    readonly string _groups;

    public ClaimRequirementFilter(string groups)
    {
        _groups = groups;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {


        var groups = _groups.Split(',');
        bool hasClaim = false;
        foreach (var group in groups)
        {
            if (context.HttpContext.User.Claims.Any(c => c.Type == ClaimTypes.GroupSid && c.Value.Equals(group.Trim(), StringComparison.OrdinalIgnoreCase)))
                hasClaim = true;
        }

        if (!hasClaim)
        {
            context.Result = new ForbidResult();
        }
    }
}

关于c# - .NET Core 3.0 声明转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58483620/

相关文章:

.net-core - WebRTC 和 Asp.Net Core

azure - 来自 .Net SDK 的数据湖分析调用(用户未授权)

c# - 我们可以将自定义对象从 Excel 传递到 C# ExcelDNA 吗?

c# - 为什么 foreach 会跳过接口(interface)类型的编译时类型检查?

azure - 无法将新的 Dotnet Core 项目发布到 Azure 502.5 错误

c# - 无法在 .NET Core 中加载文件或程序集 'System.Runtime, Version=4.1.0.0'

c# - 如何释放 MediaElement 使用的内存

c# - 按索引获取 C# 字典的项目?

jquery - Google Apps 脚本中 $.ajax() 的服务器端等效项是什么?

authorization - FB.login 返回无效的 OAuth 访问 token