我想创建一个自定义 Authorize 属性,以便能够在失败时发送个性化响应。有很多例子,但我找不到我要找的东西。注册保单时,我添加了“索赔”。是否可以在自定义属性中访问该注册声明而无需通过参数传递声明?或者是否有可能知道索赔检查是否发生,如果没有,返回个性化回复?谢谢!
public static void AddCustomAuthorization(this IServiceCollection serviceCollection)
{
serviceCollection.AddAuthorization(x =>
{
x.AddPolicy(UserPolicy.Read,
currentPolicy => currentPolicy.RequireClaim(UserClaims.Read));
});
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext authorizationFilterContext)
{
if (authorizationFilterContext.HttpContext.User.Identity.IsAuthenticated)
{
if (!authorizationFilterContext.HttpContext.User.HasClaim(x => x.Value == "CLAIM_NAME")) // ACCESS TO REGISTER CLAIM => currentPolicy => currentPolicy.RequireClaim(UserClaims.Read)
{
authorizationFilterContext.Result = new ObjectResult(new ApiResponse(HttpStatusCode.Unauthorized));
}
}
}
}
[HttpGet]
[CustomAuthorizeAttribute(Policy = UserPolicy.Read)]
public async Task<IEnumerable<UserDTO>> Get()
{
return ...
}
Run Code Online (Sandbox Code Playgroud)
Alb*_*rtK 10
您可以使用IAuthorizationPolicyProvider获取策略,然后使用ClaimsAuthorizationRequirement.ClaimType获取声明名称。而且,由于它具有异步API,它是更好地使用IAsyncAuthorizationFilter替代IAuthorizationFilter。尝试这个:
public class CustomAuthorizeAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter
{
public async Task OnAuthorizationAsync(AuthorizationFilterContext authorizationFilterContext)
{
var policyProvider = authorizationFilterContext.HttpContext
.RequestServices.GetService<IAuthorizationPolicyProvider>();
var policy = await policyProvider.GetPolicyAsync(UserPolicy.Read);
var requirement = (ClaimsAuthorizationRequirement)policy.Requirements
.First(r => r.GetType() == typeof(ClaimsAuthorizationRequirement));
if (authorizationFilterContext.HttpContext.User.Identity.IsAuthenticated)
{
if (!authorizationFilterContext.HttpContext
.User.HasClaim(x => x.Value == requirement.ClaimType))
{
authorizationFilterContext.Result =
new ObjectResult(new ApiResponse(HttpStatusCode.Unauthorized));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个属性需要一个字符串数组,这在我的例子中是需要的。我需要将不同的用户角色传递给这个属性,并根据一些自定义逻辑返回结果。
public class CustomAuthFilter : AuthorizeAttribute, IAuthorizationFilter
{
public CustomAuthFilter(params string[] args)
{
Args = args;
}
public string[] Args { get; }
public void OnAuthorization(AuthorizationFilterContext context)
{
//Custom code ...
//Resolving a custom Services from the container
var service = context.HttpContext.RequestServices.GetRequiredService<ISample>();
string name = service.GetName(); // returns "anish"
//Return based on logic
context.Result = new UnauthorizedResult();
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用此属性装饰您的控制器,如下所示
[CustomAuthFilter("Anish","jiya","sample")]
public async Task<IActionResult> Index()
Run Code Online (Sandbox Code Playgroud)
Sample 是一个返回硬编码字符串的类
public class Sample : ISample
{
public string GetName() => "anish";
}
Run Code Online (Sandbox Code Playgroud)
services.AddScoped(); //注册ISample,Sample作为作用域。
对于异步支持,请使用 IAsyncAuthorizationFilter
public class CustomAuthFilter : AuthorizeAttribute, IAsyncAuthorizationFilter
{
public CustomAuthFilter(params string[] args)
{
Args = args;
}
public string[] Args { get; }
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
//DO Whatever...
//Resolve Services from the container
var service = context.HttpContext.RequestServices.GetRequiredService<ISample>();
var httpClientFactory = context.HttpContext.RequestServices.GetRequiredService<IHttpClientFactory>();
string name = service.GetName();
using var httpClient = httpClientFactory.CreateClient();
var resp = await httpClient.GetAsync("https://jsonplaceholder.typicode.com/todos/1");
var data = await resp.Content.ReadAsStringAsync();
//Return based on logic
context.Result = new UnauthorizedResult();
}
}
Run Code Online (Sandbox Code Playgroud)
希望有帮助..
| 归档时间: |
|
| 查看次数: |
11553 次 |
| 最近记录: |