Ale*_*exu 6 api-authorization asp.net-core-webapi
根据此 Microsoft 文档,您应该能够将 [RequiredScope("SomeScopeName")] 等属性应用到控制器级别或操作级别以保护 API。但是当我在 API 中尝试它时,它似乎根本没有任何效果 - 无论我使用什么范围名称(我确保令牌中没有该名称的范围),我总是正确的进入我应该失败的 API 操作。但与此同时,我的策略属性,例如 [Authorize(Policy = "PolicyName")],工作得很好。我缺少什么?
[ApiController]
[RequiredScope("AnyRandomName")]
public class MyApiController : ControllerBase
{
Run Code Online (Sandbox Code Playgroud)
更新
这是我的 Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
IdentityModelEventSource.ShowPII = true;
services.AddControllers();
services.AddSwaggerGen(opt =>
{
opt.CustomSchemaIds(type => type.ToString() + type.GetHashCode());
});
services.Configure<HostOptions>(Configuration.GetSection(HostOptions.HOST));
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();
services.AddAuthentication("Bearer").AddJwtBearer(options =>
{
options.Authority = Configuration[HostOptions.IDENTITYGATEWAY];
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});
services.AddTransient<gRPCServiceHelper>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseExceptionHandler("/error-local-development");
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "GroupDemographicEFCore v1"));
}
else
{
app.UseExceptionHandler("/error");
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的 API 控制器
[ApiController]
[Authorize]
[RequiredScope("NoSuchScope")]
public class MyApiController : ControllerBase
{
public MyApiController([NotNull] IConfiguration configuration, [NotNull] ILogger<MyApiController> logger,
[NotNull] gRPCServiceHelper helper) : base(configuration, logger, helper)
{
}
[HttpGet]
[Route("/clients/summary")]
public async Task<IActionResult> ClientsSummaryGet()
{
...
Run Code Online (Sandbox Code Playgroud)
请注意,我在控制器级别应用了此处的属性。但是,如果我将它们移至操作级别,也没有什么区别——RequiredScope 属性总是被忽略。
更新1
我在上次帖子更新中遗漏了 AddAuthorization,因为我认为它与我的问题无关。我现在将其添加回来,其中包含我使用的一些策略。再说一次,这些政策都运行良好,我不明白这与我遇到的问题有什么关系。
services.AddAuthorization(options =>
{
options.AddPolicy("OperatorCode", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireClaim("OperatorCode");
});
options.AddPolicy("OperatorCode:oprtr0", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireClaim("OperatorCode", "oprtr0");
});
options.AddPolicy("Role:User+OperatorCode:oprtr0", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireRole("User");
policy.RequireClaim("OperatorCode", "oprtr0");
});
options.AddPolicy("Role:Admin||Role:User", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireRole("Admin", "User");
});
});
Run Code Online (Sandbox Code Playgroud)
这是 access_token 标头
小智 10
我们需要做的就是添加
services.AddRequiredScopeAuthorization();
为了让 RequireScopeAttrubute 发挥作用,无论如何,这都是AddMicrosoftIdentityWebApiAuthentication在幕后让它发挥作用的。
您需要做的是在 Startup.cs 中添加和配置授权,如下所示:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("ViewReports", policy =>
policy.RequireAuthenticatedUser()
.RequireRole("Finance")
.RequireRole("Management")
);
});
Run Code Online (Sandbox Code Playgroud)
该策略规定用户必须经过身份验证并且具有两种角色。在此示例中,RequireAuthenticatedUser() 是可选的。
然后您可以使用该策略,例如:
[Authorize(Policy = "ViewReports")]
public IActionResult ViewReports()
{
return View();
}
Run Code Online (Sandbox Code Playgroud)
要使角色声明发挥作用,您必须在令牌中定义角色声明的名称,方法如下:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters.NameClaimType = "name";
options.TokenValidationParameters.RoleClaimType = "role";
});
Run Code Online (Sandbox Code Playgroud)
否则可能找不到该角色,因为 OpenIDConnect 和 Microsoft 对于该声明的名称有不同的看法。
从长远来看,使用策略将为您提供更好、更干净的代码,因为如果您将来需要更改范围,则需要更新所有控制器类。通过策略,您可以在一处更改它。
另外,根据 GitHub 上的这个问题,它说:
requiredScopes 仅检查 scp 或 http://schemas.microsoft.com/identity/claims/scope声明。
这意味着您可能需要执行一些声明转换(重命名)才能将RequiredScope 映射到访问令牌中的范围声明。
为了补充这个答案,我写了一篇博客文章,更详细地介绍了这个主题:调试 ASP.NET Core 中的 OpenID Connect 声明问题
| 归档时间: |
|
| 查看次数: |
7706 次 |
| 最近记录: |