如何 return 来自自定义 AuthorizeAttribute 的自定义消息?
How to return custom message from custom AuthorizeAttribute?
我正在使用 ASP.NET Core 3.1 WebAPI with Auth0。
我想实现一个自定义 AuthorizeAttribute
,它会执行简单的权限检查,如果缺少权限,return 403 会显示一条消息。
代码如下:
Startup.cs
(配置服务)
services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}
)
.AddJwtBearer(options =>
{
var keyResolver = new MultipleIssuerSigningKeyResolver();
options.MetadataAddress = "https://.../.well-known/openid-configuration";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = Auth0Configuration.Audience,
ValidIssuers = Auth0Configuration.Issuers,
IssuerSigningKeyResolver = (token, securityToken, kid, parameters) =>
keyResolver.GetSigningKey(securityToken.Issuer, kid)
};
}
);
自定义 AuthorizeAttribute
:
public class AuthorizeAttribute : Microsoft.AspNetCore.Authorization.AuthorizeAttribute, IAsyncAuthorizationFilter
{
private readonly string[] _permissions;
public AuthorizeAttribute(params string[] permissions)
{
_permissions = permissions;
}
/// <inheritdoc />
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
var user = (IRemoteUser) context.HttpContext.RequestServices.GetService(typeof(IRemoteUser));
await user.Fetch(context.HttpContext);
context.HttpContext.Items["RemoteUser"] = user;
foreach (var permission in _permissions)
{
if (user.HasPermission(permission)) continue;
// Permission not found, return forbidden.
context.Result = new ForbidResult($"Permission '{permission}' is required.");
return;
}
}
}
我这样称呼它:
[Authorize("support:all")]
[HttpPost]
public async Task<ActionResult> Create([FromBody] SupportMessageCreateDto dto)
{...}
如果我不向 new ForbidResult()
提供消息,它会正常工作。如果缺少许可,我会得到 403。但如果我提供此消息,我会得到:
{
"error": "No authentication handler is registered for the scheme 'Permission 'support:all' is required.'. The registered schemes are: Bearer. Did you forget to call AddAuthentication().Add[SomeAuthHandler](\"Permission 'support:all' is required.\",...)?"
}
为什么会这样,我该如何解决?我真的很喜欢这个设置,因为它很简单,但是这条消息是必需的。
我弄错了结果类型。 ForbidResult 实际上期望身份验证方案作为构造函数中的字符串。我替换了
context.Result = new ForbidResult($"Permission '{permission}' is required.");
和
context.Result = new ObjectResult($"Permission '{permission}' is required.")
{
StatusCode = (int) HttpStatusCode.Forbidden
};
现在可以使用了。
我正在使用 ASP.NET Core 3.1 WebAPI with Auth0。
我想实现一个自定义 AuthorizeAttribute
,它会执行简单的权限检查,如果缺少权限,return 403 会显示一条消息。
代码如下:
Startup.cs
(配置服务)
services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}
)
.AddJwtBearer(options =>
{
var keyResolver = new MultipleIssuerSigningKeyResolver();
options.MetadataAddress = "https://.../.well-known/openid-configuration";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = Auth0Configuration.Audience,
ValidIssuers = Auth0Configuration.Issuers,
IssuerSigningKeyResolver = (token, securityToken, kid, parameters) =>
keyResolver.GetSigningKey(securityToken.Issuer, kid)
};
}
);
自定义 AuthorizeAttribute
:
public class AuthorizeAttribute : Microsoft.AspNetCore.Authorization.AuthorizeAttribute, IAsyncAuthorizationFilter
{
private readonly string[] _permissions;
public AuthorizeAttribute(params string[] permissions)
{
_permissions = permissions;
}
/// <inheritdoc />
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
var user = (IRemoteUser) context.HttpContext.RequestServices.GetService(typeof(IRemoteUser));
await user.Fetch(context.HttpContext);
context.HttpContext.Items["RemoteUser"] = user;
foreach (var permission in _permissions)
{
if (user.HasPermission(permission)) continue;
// Permission not found, return forbidden.
context.Result = new ForbidResult($"Permission '{permission}' is required.");
return;
}
}
}
我这样称呼它:
[Authorize("support:all")]
[HttpPost]
public async Task<ActionResult> Create([FromBody] SupportMessageCreateDto dto)
{...}
如果我不向 new ForbidResult()
提供消息,它会正常工作。如果缺少许可,我会得到 403。但如果我提供此消息,我会得到:
{
"error": "No authentication handler is registered for the scheme 'Permission 'support:all' is required.'. The registered schemes are: Bearer. Did you forget to call AddAuthentication().Add[SomeAuthHandler](\"Permission 'support:all' is required.\",...)?"
}
为什么会这样,我该如何解决?我真的很喜欢这个设置,因为它很简单,但是这条消息是必需的。
我弄错了结果类型。 ForbidResult 实际上期望身份验证方案作为构造函数中的字符串。我替换了
context.Result = new ForbidResult($"Permission '{permission}' is required.");
和
context.Result = new ObjectResult($"Permission '{permission}' is required.")
{
StatusCode = (int) HttpStatusCode.Forbidden
};
现在可以使用了。