ASP.NET 核心授权策略:无法进入处理程序?
ASP.NET Core Authorization Policies: Can't step into the handler?
我在我的 .NET Core 应用程序中设置了基于 JWT 的声明身份验证/授权,它按预期进行了身份验证,但我的策略执行并不像我预期的那样。
我有一个需求实现和处理程序设置如下:
public class ImpersonationRequirement : IAuthorizationRequirement
{
}
public class ImpersonationHandler : AuthorizationHandler<ImpersonationRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
ImpersonationRequirement requirement)
{
if (context.User.CanImpersonate()) context.Succeed(requirement);
return Task.CompletedTask;
}
}
我有一个这样设置的助手:
public static bool CanImpersonate(
this ClaimsPrincipal principal)
{
var val = principal?.FindFirst(MyClaimTypes.CAN_IMPERSONATE)?.Value;
return bool.TryParse(val, out var value) && value;
}
public class MyClaimTypes
{
/// <summary>
/// Boolean value indicating this user is authorized to impersonate other customer accounts.
/// </summary>
public const string CAN_IMPERSONATE = "cim";
...
/// <summary>
/// Actual name of the user impersonating the current user.
/// </summary>
public const string IMPERSONATING_USER = "imp";
}
...关闭我的 Startup.cs
,我定义了策略:
services.AddAuthorization(options =>
{
options.AddPolicy("Impersonator", policy => policy.Requirements.Add(new ImpersonationRequirement()));
});
...在我的控制器上,它是这样写的:
[Produces("application/json")]
[Authorize(Policy = "Impersonator")]
public class ImpersonationController : Controller
{
private readonly ILogger _logger;
private readonly ITokenManagementService _tokenManagementService;
private readonly UserManager<MyUser> _userManager;
public ImpersonationController(ITokenManagementService tokenManagementService, ILoggerFactory loggerFactory, UserManager<MyUser> userManager)
{
_tokenManagementService = tokenManagementService;
_userManager = userManager;
_logger = loggerFactory.CreateLogger<ImpersonationController>();
}
[HttpPost]
[Route("~/api/impersonation/token")]
[ProducesResponseType(typeof(AuthenticationResponse), 200)]
[ProducesResponseType(typeof(Exception), 500)]
public async Task<IActionResult> Impersonate([FromBody] string userNameToImpersonate)
{
try
{
var impersonated = await _userManager.FindByNameAsync(userNameToImpersonate);
if (impersonated == null) throw new EntityNotFoundException($"Unable to find user '{userNameToImpersonate}' in the data store.");
var actualUserId = User.UserId();
var token = await _tokenManagementService.GenerateJwt(impersonated.Id, actualUserId);
var refresh = await _tokenManagementService.GenerateRefreshToken(impersonated.Id, actualUserId);
var response = new AuthenticationResponse {AuthenticationToken = token, RefreshToken = refresh};
return Ok(response);
}
catch (Exception ex)
{
return new OopsResult(ex);
}
}
}
如果我 运行 将 AuthorizeAttribute
注释掉,我可以查看用户的声明,并且 "cim: true" 在声明枚举中,但是如果我 运行 它启用了 AuthorizeAttribute
,我收到 403 禁止错误。
我尝试在 ImpersonationHandler
:
的行上放置一个断点
if (context.User.CanImpersonate()) context.Succeed(requirement);
...但是调试器一直停在这里,所以我不知道是什么问题。有人可以告诉我我做错了什么吗?
你好像忘了在DI容器中注册你的ImpersonationHandler
(确实很容易忘记):
services.AddSingleton<IAuthorizationHandler, ImpersonationHandler>();
Asp.net 从容器中解析所有此类处理程序并尝试匹配特定要求。由于没有注册这样的处理程序 - 没有任何设置 context.Succeed
并且整个授权失败。
我在我的 .NET Core 应用程序中设置了基于 JWT 的声明身份验证/授权,它按预期进行了身份验证,但我的策略执行并不像我预期的那样。
我有一个需求实现和处理程序设置如下:
public class ImpersonationRequirement : IAuthorizationRequirement
{
}
public class ImpersonationHandler : AuthorizationHandler<ImpersonationRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
ImpersonationRequirement requirement)
{
if (context.User.CanImpersonate()) context.Succeed(requirement);
return Task.CompletedTask;
}
}
我有一个这样设置的助手:
public static bool CanImpersonate(
this ClaimsPrincipal principal)
{
var val = principal?.FindFirst(MyClaimTypes.CAN_IMPERSONATE)?.Value;
return bool.TryParse(val, out var value) && value;
}
public class MyClaimTypes
{
/// <summary>
/// Boolean value indicating this user is authorized to impersonate other customer accounts.
/// </summary>
public const string CAN_IMPERSONATE = "cim";
...
/// <summary>
/// Actual name of the user impersonating the current user.
/// </summary>
public const string IMPERSONATING_USER = "imp";
}
...关闭我的 Startup.cs
,我定义了策略:
services.AddAuthorization(options =>
{
options.AddPolicy("Impersonator", policy => policy.Requirements.Add(new ImpersonationRequirement()));
});
...在我的控制器上,它是这样写的:
[Produces("application/json")]
[Authorize(Policy = "Impersonator")]
public class ImpersonationController : Controller
{
private readonly ILogger _logger;
private readonly ITokenManagementService _tokenManagementService;
private readonly UserManager<MyUser> _userManager;
public ImpersonationController(ITokenManagementService tokenManagementService, ILoggerFactory loggerFactory, UserManager<MyUser> userManager)
{
_tokenManagementService = tokenManagementService;
_userManager = userManager;
_logger = loggerFactory.CreateLogger<ImpersonationController>();
}
[HttpPost]
[Route("~/api/impersonation/token")]
[ProducesResponseType(typeof(AuthenticationResponse), 200)]
[ProducesResponseType(typeof(Exception), 500)]
public async Task<IActionResult> Impersonate([FromBody] string userNameToImpersonate)
{
try
{
var impersonated = await _userManager.FindByNameAsync(userNameToImpersonate);
if (impersonated == null) throw new EntityNotFoundException($"Unable to find user '{userNameToImpersonate}' in the data store.");
var actualUserId = User.UserId();
var token = await _tokenManagementService.GenerateJwt(impersonated.Id, actualUserId);
var refresh = await _tokenManagementService.GenerateRefreshToken(impersonated.Id, actualUserId);
var response = new AuthenticationResponse {AuthenticationToken = token, RefreshToken = refresh};
return Ok(response);
}
catch (Exception ex)
{
return new OopsResult(ex);
}
}
}
如果我 运行 将 AuthorizeAttribute
注释掉,我可以查看用户的声明,并且 "cim: true" 在声明枚举中,但是如果我 运行 它启用了 AuthorizeAttribute
,我收到 403 禁止错误。
我尝试在 ImpersonationHandler
:
if (context.User.CanImpersonate()) context.Succeed(requirement);
...但是调试器一直停在这里,所以我不知道是什么问题。有人可以告诉我我做错了什么吗?
你好像忘了在DI容器中注册你的ImpersonationHandler
(确实很容易忘记):
services.AddSingleton<IAuthorizationHandler, ImpersonationHandler>();
Asp.net 从容器中解析所有此类处理程序并尝试匹配特定要求。由于没有注册这样的处理程序 - 没有任何设置 context.Succeed
并且整个授权失败。