从 MVC 迁移到 ASP.NET Core 3.1 中的端点路由时,具有角色的 AuthorizeAttribute 不起作用

Posted

技术标签:

【中文标题】从 MVC 迁移到 ASP.NET Core 3.1 中的端点路由时,具有角色的 AuthorizeAttribute 不起作用【英文标题】:AuthorizeAttribute with Roles not working when migrating from MVC to Endpoint Routing in ASP.NET Core 3.1 【发布时间】:2021-03-09 17:50:52 【问题描述】:

我正在尝试将我的项目从 .UseMVC(asp.net 核心 2.2 兼容样式)升级到 .UseEndpoint Routing,并且对于我的所有请求,我都被重定向到我的身份验证失败页面。它与声明有关 - 如果我删除 [Authorize(Roles = "Admin")] 的角色部分以简单地 [Authorize] 则它可以工作。它似乎没有提取分配给用户的声明。

这似乎是一个与AuthorizeAttribute not working with Endpoint Routing in ASP.NET Core 3.1非常相似的问题

以下段落摘自链接帖子但经过修改以反映我的问题版本

在 2.2 中一切正常,但在迁移到 3.1 并启用后 端点路由,这个控制器开始拒绝任何请求 [Authorize(Roles = "Admin")] 属性存在时的端点。 当我删除 “Roles =”部分并查看User.Claims,我可以看到它确实有 所需的声明/角色。有时候是这样的 仅在启用端点路由时,在使用 UseMvc 的情况下 一切正常。 Endpoint 中的授权有什么问题 路由模式?

摘自 Startup.cs

 app.UseSession();
    
 app.UseRouting();
    
 app.UseAuthentication();
 app.UseAuthorization();
 app.UseResponseCompression();
 //Add the users Roles as claims to his identity so that it is picked up for authentication purposes
 app.Use((context, next) =>
 
     var userId = context.User.Identity.Name;
     if (userId == null)
     
         return next();
     
    
     ...
        
     var roles = resourceDataAccess.GetRolesForUser(userId);
     if (roles != null)
     
         var claims = roles.Select(role => new Claim(ClaimTypes.Role, role.RoleEnum.ToString())).ToList();
    
         var appIdentity = new ClaimsIdentity(claims);
         context.User.AddIdentity(appIdentity);
     
    
     return next();
 );
 app.UseEndpoints(endpoints =>
 
     endpoints.MapHub<AppHub>("api/apphub");
     endpoints.MapControllerRoute("default", "api/controller=Account/action=SignIn/id?");
     endpoints.MapControllerRoute("catch-all", "api/*url",
             new controller = "Utility", action = "NotFoundPage");
 );

【问题讨论】:

这是一个很长的镜头,但您可以尝试将UseAuthorization 放在您的角色映射器中间件之后吗? 你可以按照这个说明使用中间件***.com/questions/56320523/… 该链接是关于创建策略的。我们要做的是使用内置的基于角色的身份验证。出于某种原因,它不尊重我们提供和分配给用户的角色。 @CamiloTerevinto - 你的回答解决了这个问题。 UseAuthentication 需要在映射代码之前,UseAuthorization 需要在之后。 【参考方案1】:

事实证明,由于我们使用 app.Use() 中间件从数据库中填充用户角色,因此需要在 UseAuthorisation 之前调用它,以便在执行授权之前加载角色。 (喜欢@CamiloTerevinto 的评论)

 app.UseSession();
    
 app.UseRouting();
    
 app.UseAuthentication();
 //Add the users Roles as claims to his identity so that it is picked up for authentication purposes
 app.Use((context, next) =>
 
   ...
 
 //Setup the authorisation middleware to run only after we have loaded the users roles.
 app.UseAuthorization();
 app.UseResponseCompression();
 

【讨论】:

很高兴听到您可以解决问题。鉴于 UseXXX 的顺序是调用代码的顺序,这对我来说似乎不正确

以上是关于从 MVC 迁移到 ASP.NET Core 3.1 中的端点路由时,具有角色的 AuthorizeAttribute 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

从 ASP.NET Core 1.1 MVC 迁移到 2.0 后,自定义 cookie 身份验证不起作用

如何先用asp.net身份框架数据库将asp.net mvc迁移到asp.net core

从 2.2 迁移到 3.1 的 ASP.Net Core 解决方案在发布时不会运行

在 ASP.NET Core MVC6 中将文件和模型发布到控制器

如何使用 EF Core 代码优先迁移为 ASP.NET Core MVC 配置 N 层架构

从 ASP.NET WebForms 迁移到 ASP.NET MVC 的建议?