绕过特定路由的全局消息处理程序
Bypassing global message handlers for specific routes
我正在开发一项 Web 服务,该服务具有 API 都需要身份验证。使用在 WebApiConfig
中配置的全局消息处理程序执行身份验证,如下所示:
config.MessageHandlers.Add(new AuthMessageHandler());
现在我们想公开一个不执行身份验证的新 API。我最初的方法是为这个新的 API 配置一个每个路由的处理程序,但是根据我在各个地方(例如 Microsoft docs about HTTP message handlers)阅读的内容,全局消息处理程序在 [=12] 之前被调用=],因此请求在命中任何路由处理程序之前仍将通过全局处理程序。我提出了一些可能的解决方案:
为所有路由配置每个路由的处理程序。我们有很多API,但由于代码的编写方式,我认为 这可以像一行添加和删除一样少。不过我不喜欢它,因为我们必须在未来添加新路由时更加小心,以确保它们得到正确的身份验证。另外,由于我们支持的 API 数量庞大,我不确定我是否有必要涵盖所有这些。我们在全球范围内这样做是有原因的。
修改处理程序,为绕过身份验证的路由设置某种白名单。我想避免这种情况,因为它会使处理程序代码复杂化。另外它在一个完全不同的通用代码库中,我真的不想在那里挖掘......
如您所知,我想尽可能避免使用这两种解决方案。有没有办法从全局消息处理程序中排除某些路由?也许这首先会破坏拥有全局处理程序的目的,但如果这在某种程度上是可能的,那就太好了。
正如对原始问题的评论所建议的那样,解决方案是在具有匿名 API 的控制器上使用 AllowAnonymousAttribute
。仅此一项并没有解决问题,因为我们不使用构建 AllowAnonymousAttribute
的 AuthorizeAttribute
,但是我们的处理程序可以使用此检查来确定是否授权请求:
private bool AllowAnonymousAccess(HttpRequestMessage request)
{
IHttpControllerSelector selector = GlobalConfiguration.Configuration.Services.GetHttpControllerSelector();
HttpControllerDescriptor descriptor = selector.SelectController(request);
Type controllerType = descriptor.ControllerType;
return controllerType.GetCustomAttribute<AllowAnonymousAttribute>(true) != null;
}
请注意,这仅适用于控制器级别。我无法找到一个快速的解决方案来确定将调用哪个控制器方法以及该方法是否具有该属性,因为在请求链的这一点上这显然不太容易做到。
我正在开发一项 Web 服务,该服务具有 API 都需要身份验证。使用在 WebApiConfig
中配置的全局消息处理程序执行身份验证,如下所示:
config.MessageHandlers.Add(new AuthMessageHandler());
现在我们想公开一个不执行身份验证的新 API。我最初的方法是为这个新的 API 配置一个每个路由的处理程序,但是根据我在各个地方(例如 Microsoft docs about HTTP message handlers)阅读的内容,全局消息处理程序在 [=12] 之前被调用=],因此请求在命中任何路由处理程序之前仍将通过全局处理程序。我提出了一些可能的解决方案:
为所有路由配置每个路由的处理程序。我们有很多API,但由于代码的编写方式,我认为 这可以像一行添加和删除一样少。不过我不喜欢它,因为我们必须在未来添加新路由时更加小心,以确保它们得到正确的身份验证。另外,由于我们支持的 API 数量庞大,我不确定我是否有必要涵盖所有这些。我们在全球范围内这样做是有原因的。
修改处理程序,为绕过身份验证的路由设置某种白名单。我想避免这种情况,因为它会使处理程序代码复杂化。另外它在一个完全不同的通用代码库中,我真的不想在那里挖掘......
如您所知,我想尽可能避免使用这两种解决方案。有没有办法从全局消息处理程序中排除某些路由?也许这首先会破坏拥有全局处理程序的目的,但如果这在某种程度上是可能的,那就太好了。
正如对原始问题的评论所建议的那样,解决方案是在具有匿名 API 的控制器上使用 AllowAnonymousAttribute
。仅此一项并没有解决问题,因为我们不使用构建 AllowAnonymousAttribute
的 AuthorizeAttribute
,但是我们的处理程序可以使用此检查来确定是否授权请求:
private bool AllowAnonymousAccess(HttpRequestMessage request)
{
IHttpControllerSelector selector = GlobalConfiguration.Configuration.Services.GetHttpControllerSelector();
HttpControllerDescriptor descriptor = selector.SelectController(request);
Type controllerType = descriptor.ControllerType;
return controllerType.GetCustomAttribute<AllowAnonymousAttribute>(true) != null;
}
请注意,这仅适用于控制器级别。我无法找到一个快速的解决方案来确定将调用哪个控制器方法以及该方法是否具有该属性,因为在请求链的这一点上这显然不太容易做到。