我具有此属性:
public class ValidateCertAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext context)
{
// Read certificate from the HTTP Request and
// check its various attributes against known
// values from a config file.
if (true) // certificate is invalid
{
context.Response = new HttpResponseMessage(HttpStatusCode.Forbidden)
{
ReasonPhrase = "Invalid certificate"
};
}
else
{
base.OnAuthorization(context);
}
}
}
此操作:
[HttpGet]
[Route("TestAuth")]
[ValidateCert]
public HttpResponseMessage TestAuth()
{
return new HttpResponseMessage(HttpStatusCode.OK)
{
ReasonPhrase = "In Test method without any authorization."
};
}
此操作在.NET Core Web Api控制器中:
[ApiController]
public class TestAuthController : ControllerBase
另一方面,Startup.cs包含:
app.UseMvc();
这似乎很奇怪,因为这应该只是一个Web Api控件,而不是MVC Web应用程序。显然,这只是用于路由,但我认为值得一提。
我已经在属性代码的第一行设置了一个断点,但是没有遇到问题。我相信它应该在动作执行之前被击中,并且该动作永远不会执行,因为我在属性内设置了Response。为什么不执行该属性?
答案 0 :(得分:1)
这可以使用基于策略的授权来完成。
从本质上讲,这个想法是您有一个需要满足的要求(有效证书),该要求的处理程序(如何验证证书)以及强制执行此要求并在授权期间应用的策略。
如果您的代码足够简单,则只需向用于评估的策略提供Func<AuthorizationHandlerContext, bool>
。以下是设置策略的方法(在Startup.cs中,ConfigureServices()
):
services.AddAuthorization(options =>
{
options.AddPolicy("ValidateCertificate", policy =>
policy.RequireAssertion(context =>
{
var filterContext = (AuthorizationFilterContext)context.Resource;
var Response = filterContext.HttpContext.Response;
var message = Encoding.UTF8.GetBytes("Invalid certificate");
Response.OnStarting(async () =>
{
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
await Response.Body.WriteAsync(message, 0, message.Length);
});
return false;
}));
});
这会做你想要的。
现在,如果您想走更有条理的路线,则可以实施每一项:
首先,创建您的需求(实际上更像是供参考的标记):
public class ValidCertificateRequirement : IAuthorizationRequirement
{
}
然后设置需要应用的策略(Startup.cs,ConfigureServices()
):
services.AddAuthorization(options =>
{
options.AddPolicy("ValidateCertificate", policy =>
{
policy.Requirements.Add(new ValidCertificateRequirement());
});
});
现在您需要创建需求处理程序:
public class ValidCertificateHandler : AuthorizationHandler<ValidCertificateRequirement>
{
public ValidCertificateHandler()
{
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidCertificateRequirement requirement)
{
var filterContext = (AuthorizationFilterContext)context.Resource;
var Response = filterContext.HttpContext.Response;
var message = Encoding.UTF8.GetBytes("Invalid certificate");
Response.OnStarting(async () =>
{
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
await Response.Body.WriteAsync(message, 0, message.Length);
});
context.Fail();
return Task.CompletedTask;
}
}
然后需要在启动时注册处理程序(在ConfigureServices()
中):
//Register handler
services.AddSingleton<IAuthorizationHandler, ValidCertificateHandler>();
最后,对于两种方法(断言或实施),将Authorize
属性应用于您的操作,指示要应用的策略:
[Authorize(Policy = "ValidateCertificate")]
public HttpResponseMessage TestAuth()
{
return new HttpResponseMessage(HttpStatusCode.OK)
{
ReasonPhrase = "In Test method without any authorization."
};
}
您可以在此处了解更多信息: