AuthorizationFilterAttribute 中没有命中断点
Breakpoint not getting hit in AuthorizationFilterAttribute
我有这个属性:
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 。为什么属性没有执行?
这可以使用 policy-based 授权来完成。
这个想法本质上是您有一个需要满足的要求(有效证书),一个要求的处理程序(如何验证证书)和一个强制执行此要求并在授权期间应用的策略。
如果您的代码足够简单,您只需提供一个 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."
};
}
您可以在此处阅读更多相关信息:
我有这个属性:
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 。为什么属性没有执行?
这可以使用 policy-based 授权来完成。
这个想法本质上是您有一个需要满足的要求(有效证书),一个要求的处理程序(如何验证证书)和一个强制执行此要求并在授权期间应用的策略。
如果您的代码足够简单,您只需提供一个 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."
};
}
您可以在此处阅读更多相关信息: