C# IAsyncationFilter中的OnActionExecutionAsync有时只命中
我制作了一个Api密钥授权属性,它可以工作。。。有时候,这很奇怪 属性代码:C# IAsyncationFilter中的OnActionExecutionAsync有时只命中,c#,.net,api,attributes,authorization,C#,.net,Api,Attributes,Authorization,我制作了一个Api密钥授权属性,它可以工作。。。有时候,这很奇怪 属性代码: [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class ApiKeyAuthAttribute: Attribute, IAsyncActionFilter { private const string ApiKeyHeadername = "ApiKey";
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ApiKeyAuthAttribute: Attribute, IAsyncActionFilter
{
private const string ApiKeyHeadername = "ApiKey";
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
DataAcces dataAcces = context.HttpContext.RequestServices.GetService(typeof(DataAcces)) as DataAcces;
if (!context.HttpContext.Request.Headers.TryGetValue(ApiKeyHeadername, out var apiKey) ||
!dataAcces.TryAuthenticate(apiKey, out NsInvoiceRecognitionCredentials credentials))
{
context.Result = new UnauthorizedResult();
return;
}
((JobController)context.Controller).Credentials = credentials;
await next();
}
}
控制器代码:
[ApiController]
[Route("jobs")]
[ApiKeyAuth]
public class JobController : ControllerBase
{
private readonly DataAcces _dataAcces;
private readonly ILogger<JobController> _logger;
public NsInvoiceRecognitionCredentials Credentials;
public JobController(ILogger<JobController> logger, DataAcces dataAcces)
{
_logger = logger;
_dataAcces = dataAcces;
}
[HttpPost, Route("add")]
public IActionResult Add(IFormFile document)
{
//Do stuff
return Ok();
}
}
[ApiController]
[路线(“工作”)]
[ApiKeyAuth]
公共类作业控制器:ControllerBase
{
专用只读数据访问\u数据访问;
专用只读ILogger\u记录器;
公共NSINVOICERecognition凭证;
公共作业控制器(ILogger记录器、数据访问数据访问)
{
_记录器=记录器;
_数据访问=数据访问;
}
[HttpPost,路线(“添加”)]
公共IActionResult添加(IFormFile文档)
{
//做事
返回Ok();
}
}
数据访问代码:
public bool TryAuthenticate(string apiKeyString, out NsInvoiceRecognitionCredentials credentials)
{
if (Guid.TryParse(apiKeyString, out Guid apiKey))
{
credentials = _dbContext.Set<NsInvoiceRecognitionCredentials>().FirstOrDefault(x => x.ApiKey == apiKey);
return credentials != null;
}
credentials = default;
return false;
}
public bool TryAuthenticate(字符串apiKeyString,out NSINVOICERognitionCredentials)
{
if(Guid.TryParse(apiKeyString,out-Guid-apiKey))
{
凭据=_dbContext.Set().FirstOrDefault(x=>x.ApiKey==ApiKey);
返回凭据!=null;
}
凭证=默认值;
返回false;
}
我发送的每个请求都会在控制器构造函数中结束,这是预期的。之后,它应该转到ApiKeyAut hAttribute
中的OnActionExecutionAsync
,但这种情况不会100%发生,只有大约50%的时间发生。另外50%的时间它什么也不做,最终超时
我不认为问题出在我的过滤器或DataAccess代码中,只是因为它甚至没有击中过滤器中OnActionExecutionAsync第一行的断点,所以这些部分甚至没有执行
如果我在我的控制器构造函数的第一行中放置一个断点,我可以跨过接下来的几行,大约50%的时间它在执行这些行之后停止,没有异常,没有任何异常
编辑:
我知道出了什么问题,但还没有找到合适的解决办法。如果我回答,我会回答我的问题
过滤器中没有出现任何问题,所有问题都是由于我正在处理请求正文中的文件。这些文件显然使请求太重(奇怪,因为它只有100kb)。当我发送没有任何文件的请求时,一切正常
我想问题可能是我发送和接收文件(文件)的方式
如果有人知道原因或如何解决这个问题,我将非常感激尝试在ActionExecutionGasSync上更改它,您必须这样使用它
[ServiceFilter(typeof(ApiKeyAuthAttribute))]
public class JobController : ControllerBase
在使用之前,它应该在启动中注册
services.AddScoped<ApiKeyAuthAttribute>();
或者您可以尝试合并两者
public class ApiKeyAuthAttribute: IActionFilter, IAsyncActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
......
}
public async Task OnActionExecutingAsync(ActionExecutingContext context,
ActionExecutionDelegate next)
{
OnActionExecuting(context);
await next();
}
}
虽然这确实改善了它,但它现在在75%的时间里都能工作……我正在用它来做动作。尝试将其移动到action当将其用于操作时,同样的事情也会发生。邮递员告诉我,当它发生时,它无法得到响应。然后,如果你的过滤器仍然不能正常工作,那么错误就在过滤器代码中。你的算法没有进行适当的过滤。您必须清楚地解释此筛选器的用途和工作方式。该筛选器应检查api密钥的传入请求,并检查其是否有效以及是否存在于数据库中。如果不是,它应该在请求到达控制器方法之前返回401 unauthorized。我认为错误不在过滤代码中,因为当错误发生时,过滤代码甚至没有执行。它在构造控制器后停止。您的代码需要更多详细信息。请为您的DataAccess服务发布一些解释和代码。例如TryAuthenticate方法。我添加了DataAccess代码,我认为这不是问题,因为它根本没有执行,如果您需要更多解释,请让我知道。
public class ApiKeyAuthAttribute: IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
public class ApiKeyAuthAttribute: IActionFilter, IAsyncActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
......
}
public async Task OnActionExecutingAsync(ActionExecutingContext context,
ActionExecutionDelegate next)
{
OnActionExecuting(context);
await next();
}
}