【问题标题】:Role authorization throws "The trust relationship between this workstation and the primary domain failed"角色授权抛出“此工作站与主域之间的信任关系失败”
【发布时间】:2020-12-05 10:20:40
【问题描述】:

我正在使用带有 Windows 身份验证的 ASP.NET Core 3.1。如果我单独使用[Authorize],一切都很好,但是,如果我用[Authorize(Roles = "GlobalAdmin")] 装饰我的控制器,则授权失败。

这发生在我本地的开发人员中,以及在 Intranet 上部署之后。

我绝对分配了正确的角色,因为以下工作正常:

if(await _userManager.IsInRoleAsync(await _userManager.FindByNameAsync(User.Identity.Name), "GlobalAdmin"))
{
    return View();
}

但我不想对控制器中的每个方法都执行此操作,并且我不能在基本控制器的构造函数中使用它,因为User.Identity 在构造函数中返回 null。

使用以下内容,var y 向我展示了我的正确角色

var x = await _userManager.FindByNameAsync(User.Identity.Name);
var y = await _userManager.GetRolesAsync(x);

过去,我能够在 Authorize 属性上创建自定义覆盖,并在其中进行了自己的角色验证,但核心 3.1 似乎已经更改了方法,因此它们无法覆盖。

但为什么 [Authorize] 属性首先不适用于我的角色?

在我的创业公司中

public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentity<IdentityUser, IdentityRole>()
        .AddRoleManager<RoleManager<IdentityRole>>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.Configure<IdentityOptions>(options =>
    {
        options.User.AllowedUserNameCharacters =
            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.\\";
        options.User.RequireUniqueEmail = true;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("MyConnString")));

    services.AddControllersWithViews();
 }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
        if (env.IsDevelopment())
        {
            //app.UseMiddleware<Helpers.ErrorHandlingMiddleware>();
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseMiddleware<Helpers.ErrorHandlingMiddleware>();
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();

        app.UseStaticFiles();

        app.UseAuthentication();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

整个堆栈跟踪如下所示:

Win32Exception: 此工作站与主域之间的信任关系失败。

System.Security.Principal.NTAccount.TranslateToSids(IdentityReferenceCollection sourceAccounts, out bool someFailed)
System.Security.Principal.NTAccount.Translate(IdentityReferenceCollection sourceAccounts, Type targetType, out bool someFailed)
System.Security.Principal.NTAccount.Translate(IdentityReferenceCollection sourceAccounts, Type targetType, bool forceSuccess)
System.Security.Principal.WindowsPrincipal.IsInRole(字符串角色)
Microsoft.AspNetCore.Authorization.Infrastructure.RolesAuthorizationRequirement+c__DisplayClass4_0.b__0(string r)
System.Linq.Enumerable.Any(IEnumerable source, Func 谓词)
Microsoft.AspNetCore.Authorization.Infrastructure.RolesAuthorizationRequirement.HandleRequirementAsync(AuthorizationHandlerContext 上下文,RolesAuthorizationRequirement 要求)
Microsoft.AspNetCore.Authorization.AuthorizationHandler.HandleAsync(AuthorizationHandlerContext 上下文)
Microsoft.AspNetCore.Authorization.Infrastructure.PassThroughAuthorizationHandler.HandleAsync(AuthorizationHandlerContext 上下文)
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService.AuthorizeAsync(ClaimsPrincipal 用户、对象资源、IEnumerable 要求)
Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator.AuthorizeAsync(AuthorizationPolicy 策略、AuthenticateResult authenticationResult、HttpContext 上下文、对象资源)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext 上下文)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

【问题讨论】:

  • @CamiloTerevinto 完成!我在网上能找到的所有主要错误都是人们无法使用IsInRole,但IsInRole 对我来说很好用,我只是不明白为什么Authorize 属性不起作用。
  • 如果您没有得到答案,我会在当天晚些时候查看源代码以尝试找出差异
  • 您的代码的属性为[Authorization(Roles = "GlobalAdmin")],但文档显示为[Authorize(Roles = "GlobalAdmin")],您尝试过吗? Role-based authorization in ASP.NET Core
  • @queue 抱歉,这是一个手动输入的错误,它实际上应该是用 [Authorize] 装饰的,我只是输入了“Authorization”,因为那是命名空间。今天早上我在谷歌上输入了大约 20 次,所以我很困惑!
  • @CamiloTerevinto 如果您能发现错误,我将不胜感激!我确定我之前已经创建并使用了这个确切的项目设置没有问题,但这可能是登录而不是 windows auth

标签: c# asp.net-core windows-authentication asp.net-core-3.1


【解决方案1】:

TL:DR;

错误

此工作站与主域之间的信任关系失败。

System.Security.Principal.NTAccount.TranslateToSids(IdentityReferenceCollection sourceAccounts, out bool someFailed)

只是本地系统上不存在的组。在在正确的位置创建组后,即使它没有成员,我也不会再收到此特定错误了。

为了开发,我必须在我的本地系统上创建我的组,正如 cmets 中的 @queue 所暗示的那样。但这并没有解决我的长期问题 - 我想使用数据库中定义的角色!

长解释:

我不明白AspNetIdentityAuthorization / Authentication 之间的区别

我创建了一个默认的 Windows 身份验证应用程序,并最终创建了 AspNetIdentity 表作为我最初的代码优先迁移的一部分,这样我就可以看到我的用户的数据库,并可以创建一些与他们相关的额外表。我认为这些是内在联系的,但 IdentityAuthorisation 可以完全独立存在。

我使用AspNetIdentityUserManagerRoleManager 在数据库中创建用户和角色,userManager.IsInRoleAsync(&lt;username&gt;) 将显示所有正确的角色条目。

我想使用 [Authorize] 属性,但我希望它忽略 Active Directory - 在 dev 和我的 iis 服务器上设置似乎是一件小事,我需要依靠更高的权力和麻烦其他人。我只是想让它查看数据库角色。

我尝试使用带有[Authorize(Roles = "")]IClaimsTransformation 类,它将角色从数据库转换为适当的声明以供Windows 身份验证使用。 StackOverflow 上有一些这样的例子,但我一直收到同样的错误;如果您正在检查的组在系统中不存在,Windows [Authorization] 将在触发 ClaimsTransformation 之前立即失败 - 即使您继续忽略它们。

Startup 中没有可以规避此问题的服务的顺序组合。

我最终使用了与以前的 asp.net 核心应用程序相同的解决方案,但在 3.1 中略有不同:

创建了我自己的属性来替换我的控制器顶部的 [Authorize]

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

并创建了一个简单的类,幸运的是,它允许我注入我的ApplicationDbContext,我有一个方法可以获取给定用户名的角色名称列表。

public class ClaimRequirementFilter : IAuthorizationFilter
{

    private readonly string _roles;
    private readonly ApplicationDbContext _context;

    public ClaimRequirementFilter(string roles, ApplicationDbContext context)
    {
        _context = context;
        _roles = roles;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {

        List<string> matchingRoles = _context.CheckRoles(context.HttpContext.User.Identity.Name, roles);
        if(matchingRoles.Count == 0) context.Result = new ForbidResult();

    }
}

注入UserManager 也可能有效,但使用异步方法会弄乱OnAuthorization 方法,所以我坚持使用我的应用程序上下文,无论如何都可以轻松访问 AspNetIdentity 表。

【讨论】:

    猜你喜欢
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-11
    • 2014-04-26
    • 1970-01-01
    相关资源
    最近更新 更多