我正在使用存储不同配置的选项模式,包括用于不同环境的API密钥。到目前为止,我一直在使用它并根据需要将我的值注入到类中。
但是,在尝试在控制器中设置授权并针对每个环境唯一的ApiKey运行验证时,我遇到了一些挑战,因为我无法将Iptions注入ApiKeyAuthorizeAttribute类来执行验证。
以下是我的控制器现在的样子:
[ApiKeyAuthorize]
public class NotificationSettingsController : Controller
{
//some endpoints here
}
ApiKeyAuthorize类:
public class ApiKeyAuthorizeAttribute : Attribute, IAuthorizationFilter
{
//////This...
private readonly IOptions<MyConfig> _config;
public ApiKeyAuthorizeAttribute(IOptions<MyConfig> config)
{
_config = config;
}
/////////...is what I am trying to accomplish
public void OnAuthorization(AuthorizationFilterContext context)
{
var request = context.HttpContext.Request;
var foundApiKeys = request.Headers.TryGetValue("ReplaceWithOptionsApiKeyName", out var requestApiKeys);
if (!foundApiKeys || requestApiKeys[0] != "ReplaceWithOptionsApiKeyValue")
{
context.Result = new UnauthorizedResult();
}
}
}
我的问题是这里注入是不可能的,但我需要从IOptions <>获取一个值来运行ApiKey验证。
属性是就地构造的,因此不可能将依赖项注入其中。但是,ASP.NET Core提供了一种解决方法。您可以使用ServiceFilter
属性代替直接应用该属性,并将其传递给您要应用的过滤器类型:
[ServiceFilter(typeof(ApiAuthorizeAttribute))]
这将动态地将过滤器应用于控制器/操作,同时使用它同时需要的任何依赖项对其进行实例化。但是,它确实限制了你的另一个方向。例如,如果您需要执行以下操作:
[ApiAuthorizeAttribute(Roles = "Admin")]
使用ServiceFilter
属性无法实现此目的,因为您无法在此处传递属性值(如Roles
)以及类型。