简体   繁体   English

Windows身份验证Asp.net核心2数据库角色授权

[英]Windows Authentication Asp.net core 2 database role authorization

I am working on an intranet application that will use Asp.Net Core 2.1 and Windows authentication. 我正在使用一个将使用Asp.Net Core 2.1和Windows身份验证的Intranet应用程序。 I am getting the pass through from IIS just fine, but I want to use roles stored in a database for the authorization. 我正好从IIS获得通过,但我想使用存储在数据库中的角色进行授权。

I have an IClaimsTransformeration class that gets the roles from a database based on the LAN Id and adds them to the claims list with the role key. 我有一个IClaimsTransformeration类,它从基于LAN Id的数据库中获取角色,并使用角色键将它们添加到声明列表中。

public class MyClaimsTransformer : IClaimsTransformation
{
    private readonly IUnitOfWorkMtuSecurity _unitOfWork;

    public MyClaimsTransformer(IUnitOfWorkMtuSecurity unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    // Each time HttpContext.AuthenticateAsync() or HttpContext.SignInAsync(...) is called the claims transformer is invoked. So this might be invoked multiple times. 
    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var identity = principal.Identities.FirstOrDefault(x => x.IsAuthenticated);
        if (identity == null) return principal;

        //var user = await _userManager.GetUserAsync(principal);
        var user = identity.Name;
        if (user == null) return principal;

        //Get user with roles from repository.
        var dbUser = _unitOfWork.UserInformations.GetUserWithRoles(user);

        // Inject DbRoles into Claims list
        foreach (var role in dbUser.UserInformationUserRoles.Select((r=>r.UserRole)))
        {
            var claim = new Claim(ClaimTypes.Role, role.Name);
            identity.AddClaim(claim);
        }

        return new ClaimsPrincipal(identity);
    }  
}

I added the IClaimsTransformation to my services in the startup.cs 我在startup.cs中将IClaimsTransformation添加到了我的服务中

services.AddScoped<IClaimsTransformation, MyClaimsTransformer>();

Then I added the attribute to my controller 然后我将属性添加到我的控制器

[Authorize(Roles = "Administrator")]

When I run my application I get the following error: 当我运行我的应用程序时,我收到以下错误:

An unhandled exception occurred while processing the request. 处理请求时发生未处理的异常。 InvalidOperationException: No authenticationScheme was specified, and there was no DefaultForbidScheme found. InvalidOperationException:未指定authenticationScheme,并且未找到DefaultForbidScheme。 Microsoft.AspNetCore.Authentication.AuthenticationService.ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties) Microsoft.AspNetCore.Authentication.AuthenticationService.ForbidAsync(HttpContext context,string scheme,AuthenticationProperties properties)

In the startup.cs I added the following to the services 在startup.cs中,我将以下内容添加到服务中

services.AddAuthentication(IISDefaults.AuthenticationScheme);

This got rid of the error, but no matter what I get a 403 error. 这摆脱了错误,但无论我得到403错误。

You don't have authorization to view this page. 您无权查看此页面。 HTTP ERROR 403 HTTP错误403

When I watch the return value from MyClaimsTransformer, I can see the role of administrator has been added to the list of claims, but no matter what I get a 403 error. 当我从MyClaimsTransformer观察返回值时,我可以看到管理员的角色已添加到声明列表中,但无论我得到403错误。

Does anyone have a suggestion for what I am missing? 有没有人建议我缺少什么?

If I use the following syntax in my view it works at the view level: 如果我在视图中使用以下语法,它在视图级别工作:

 @if (User.HasClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", "Administrator"))
                    {
                <li><a asp-area="" asp-controller="UserInformationAdmin" asp-action="Index">Admin</a></li>
                     } 

I have to specify the entire schema url though. 我必须指定整个架构URL。

The ClaimIdentity had a RoleClaimType of " http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid " ClaimIdentity的RoleClaimType为“ http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid

and it needed to be a RoleClaimType of " http://schemas.microsoft.com/ws/2008/06/identity/claims/role " 它需要是一个RoleClaimType“ http://schemas.microsoft.com/ws/2008/06/identity/claims/role

Since this is a readonly property, I changed the TransformAsync method to create a new ClaimsPrincipal instead of trying to add database roles to the existing claims. 由于这是一个只读属性,因此我更改了TransformAsync方法以创建新的ClaimsPrincipal,而不是尝试将数据库角色添加到现有声明中。 My application doesn't require any of the AD groups, so it only uses windows for Authentication. 我的应用程序不需要任何AD组,因此它仅使用Windows进行身份验证。 The code below seems to work. 下面的代码似乎有效。

public class MyClaimsTransformer : IClaimsTransformation
{
    private readonly IUnitOfWorkSecurity _unitOfWork;

    public MyClaimsTransformer(IUnitOfWorkSecurity unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    // Each time HttpContext.AuthenticateAsync() or HttpContext.SignInAsync(...) is called the claims transformer is invoked. So this might be invoked multiple times. 
    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var identity = principal.Identities.FirstOrDefault(x => x.IsAuthenticated);
        if (identity == null) return principal;

        var user = identity.Name;
        if (user == null) return principal;

        //Get user with roles from repository.
        var dbUser = _unitOfWork.UserInformations.GetUserWithRoles(user);

        var claims = new List<Claim>();

        //The claim identity uses a claim with the claim type below to determine the name property.
        claims.Add(new Claim(@"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", user, "Name"));

        //todo: We should probably create a cache for this
        // Get User Roles from database and add to list of claims.
        foreach (var role in dbUser.UserInformationUserRoles.Select((r=>r.UserRole)))
        {
            claims.Add(new Claim(ClaimTypes.Role, role.Name));
        }

        var newClaimsIdentity = new ClaimsIdentity(claims,"Kerberos","", "http://schemas.microsoft.com/ws/2008/06/identity/claims/role");

        var newClaimsPrincipal = new ClaimsPrincipal(newClaimsIdentity);

        return new ClaimsPrincipal(newClaimsPrincipal);
    }  
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM