Webapi 委托处理程序返回 401 响应被 Owin Auth 覆盖
Webapi Delegating Handler Returning 401 Response Gets Overridden by Owin Auth
我查看过类似的帖子,其中的解决方案对我不起作用。
我在 IIS 7.x 中托管了一个 MVC 5 站点,该站点为 Web ui - https://www.example.com. Callers can also access api (Webapi 2.2) endpoints to perform certain functions - https://www.example.com/api/x 提供服务。一些 pages/apis 是安全的,而另一些则不是。 mvc/web ui 安全性由配置有 UseCookieAuthentication 和 UseWsFederationAuthentication.
的 owin 中间件管理
当用户还没有有效的 SAML 令牌时,网络中的安全页面ui 会自动重定向到 ADFS 登录屏幕 - 根据需要。
安全网络 api 需要 ui 在 Auth header 中传递一个单独的 JWT 令牌。
Webapi 托管在与 MVC 相同的应用程序池中。 Webapi 没有控制器,相反,webapiconfig 具有利用 DelegatingHandler 通过 api 到 route/pass 的路由电话。委托处理程序负责检查 JWT 是否包含在 Auth header 中,如果包含则允许它继续到另一个验证 JWT 的内部 Webapi。如果 JWT 不存在,那么 DelegatingHandler returns a 401.
401 return 曾经在短路时工作 ui 继续请求,因此绕过了任何 owin 管道内容。但是,现在当 shortcircuit 触发时,401 不是 returned。相反,请求继续并传递到 Owin 身份验证,然后重定向 (302) 到 ADFS 登录。我不知道为什么。 如果我将响应状态代码更改为 401 以外的内容,Owin Auth 将忽略它。
请看下面的代码:
Global.asax.cs
public class Global : HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "Apis",
routeTemplate: "api/{*path}",
handler: HttpClientFactory.CreatePipeline
(
innerHandler: new HttpClientHandler(),
handlers: new DelegatingHandler[] { new ApiHandler() }
),
defaults: new { path = RouteParameter.Optional },
constraints: null
);
}
}
ApiHandler.cs
internal class ApiHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
try
{
// get jwt from header
var jwt = GetJWTFromHeader(request.Headers);
if (jwt == null)
{
response.ReasonPhrase = "Token required";
return await Task.FromResult<HttpResponseMessage>(response);
}
else if (!IsValidJWT(jwt))
{
response.ReasonPhrase = "Invalid token";
return await Task.FromResult<HttpResponseMessage>(response);
}
response = await base.SendAsync(request, cancellationToken);
}
catch (Exception ex)
{
// log error
response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
// return result
return response;
}
}
Startup.Auth.cs
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
ServicePointManager.ServerCertificateValidationCallback += ValidateServerCertificate;
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(
new CookieAuthenticationOptions()
{
SlidingExpiration = false
}
);
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = ADFS_REALM,
MetadataAddress = ADFS_METADATA,
UseTokenLifetime = true,
TokenValidationParameters = new TokenValidationParameters
{
SaveSigninToken = true
},
Notifications = new WsFederationAuthenticationNotifications
{
RedirectToIdentityProvider = async r =>
{
// do stuff
},
SecurityTokenValidated = async s =>
{
// if we get here, then UI user has valid saml token
// do stuff
}
}
}
});
}
感谢您的帮助。如果需要更多详细信息,请告诉我!
看起来你可以使用:
https://msdn.microsoft.com/en-us/library/system.web.http.owinhttpconfigurationextensions.suppressdefaulthostauthentication(v=vs.118).aspx
config.SuppressDefaultHostAuthentication();
感谢Finallz I was able to refine my search and come across an answer - found here。在我的例子中,我不需要任何特殊的身份验证配置,因为我在 api 处理程序中手动检查了 JWT。但是,通过简单地包含一个映射到我的 api 路径,它自然会覆盖 Owin 安全性:
app.Map("/api", inner =>
{
// nothing to do here since we don't have any concrete controllers to manage special authorization for
// we're using apihandlers to pass api traffic through to next stop
});
我查看过类似的帖子,其中的解决方案对我不起作用。
我在 IIS 7.x 中托管了一个 MVC 5 站点,该站点为 Web ui - https://www.example.com. Callers can also access api (Webapi 2.2) endpoints to perform certain functions - https://www.example.com/api/x 提供服务。一些 pages/apis 是安全的,而另一些则不是。 mvc/web ui 安全性由配置有 UseCookieAuthentication 和 UseWsFederationAuthentication.
的 owin 中间件管理当用户还没有有效的 SAML 令牌时,网络中的安全页面ui 会自动重定向到 ADFS 登录屏幕 - 根据需要。
安全网络 api 需要 ui 在 Auth header 中传递一个单独的 JWT 令牌。
Webapi 托管在与 MVC 相同的应用程序池中。 Webapi 没有控制器,相反,webapiconfig 具有利用 DelegatingHandler 通过 api 到 route/pass 的路由电话。委托处理程序负责检查 JWT 是否包含在 Auth header 中,如果包含则允许它继续到另一个验证 JWT 的内部 Webapi。如果 JWT 不存在,那么 DelegatingHandler returns a 401.
401 return 曾经在短路时工作 ui 继续请求,因此绕过了任何 owin 管道内容。但是,现在当 shortcircuit 触发时,401 不是 returned。相反,请求继续并传递到 Owin 身份验证,然后重定向 (302) 到 ADFS 登录。我不知道为什么。 如果我将响应状态代码更改为 401 以外的内容,Owin Auth 将忽略它。
请看下面的代码:
Global.asax.cs
public class Global : HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "Apis",
routeTemplate: "api/{*path}",
handler: HttpClientFactory.CreatePipeline
(
innerHandler: new HttpClientHandler(),
handlers: new DelegatingHandler[] { new ApiHandler() }
),
defaults: new { path = RouteParameter.Optional },
constraints: null
);
}
}
ApiHandler.cs
internal class ApiHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
try
{
// get jwt from header
var jwt = GetJWTFromHeader(request.Headers);
if (jwt == null)
{
response.ReasonPhrase = "Token required";
return await Task.FromResult<HttpResponseMessage>(response);
}
else if (!IsValidJWT(jwt))
{
response.ReasonPhrase = "Invalid token";
return await Task.FromResult<HttpResponseMessage>(response);
}
response = await base.SendAsync(request, cancellationToken);
}
catch (Exception ex)
{
// log error
response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
// return result
return response;
}
}
Startup.Auth.cs
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
ServicePointManager.ServerCertificateValidationCallback += ValidateServerCertificate;
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(
new CookieAuthenticationOptions()
{
SlidingExpiration = false
}
);
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = ADFS_REALM,
MetadataAddress = ADFS_METADATA,
UseTokenLifetime = true,
TokenValidationParameters = new TokenValidationParameters
{
SaveSigninToken = true
},
Notifications = new WsFederationAuthenticationNotifications
{
RedirectToIdentityProvider = async r =>
{
// do stuff
},
SecurityTokenValidated = async s =>
{
// if we get here, then UI user has valid saml token
// do stuff
}
}
}
});
}
感谢您的帮助。如果需要更多详细信息,请告诉我!
看起来你可以使用: https://msdn.microsoft.com/en-us/library/system.web.http.owinhttpconfigurationextensions.suppressdefaulthostauthentication(v=vs.118).aspx config.SuppressDefaultHostAuthentication();
感谢Finallz I was able to refine my search and come across an answer - found here。在我的例子中,我不需要任何特殊的身份验证配置,因为我在 api 处理程序中手动检查了 JWT。但是,通过简单地包含一个映射到我的 api 路径,它自然会覆盖 Owin 安全性:
app.Map("/api", inner =>
{
// nothing to do here since we don't have any concrete controllers to manage special authorization for
// we're using apihandlers to pass api traffic through to next stop
});