C# OWIN认证管道,以及如何正确使用Katana中间件?
我最近开始研究新的ASP.Net Identity framework和Katana中间件,那里有大量令人惊讶的代码和文档,但我看到了很多相互冲突的信息,我想这是代码更新频率不断增加的结果 我希望对内部ADFS 2服务使用WsFederation身份验证,但OWIN身份验证管道的工作方式让我有点困惑,我希望有人能提供一些明确的信息 具体来说,我感兴趣的是中间件连接的顺序,以及在各种场景中需要哪些模块,我想去掉不需要的任何东西,同时确保流程尽可能安全 例如,C# OWIN认证管道,以及如何正确使用Katana中间件?,c#,owin,adfs,katana,ws-federation,C#,Owin,Adfs,Katana,Ws Federation,我最近开始研究新的ASP.Net Identity framework和Katana中间件,那里有大量令人惊讶的代码和文档,但我看到了很多相互冲突的信息,我想这是代码更新频率不断增加的结果 我希望对内部ADFS 2服务使用WsFederation身份验证,但OWIN身份验证管道的工作方式让我有点困惑,我希望有人能提供一些明确的信息 具体来说,我感兴趣的是中间件连接的顺序,以及在各种场景中需要哪些模块,我想去掉不需要的任何东西,同时确保流程尽可能安全 例如,UseWsFederationAuthe
UseWsFederationAuthentication
似乎应该与UseCookieAuthentication
结合使用,但我不确定正确的AuthenticationType
是什么(post表明它只是一个标识符字符串,但它的值是否重要?)或者即使我们仍然需要使用SetDefaultSignInAsAuthenticationType
我还注意到Katana项目讨论板上的线程,其中Tratcher提到了一个常见错误,但对于代码的哪一部分出错并不是很具体
就我个人而言,我现在使用以下方法(使用自定义SAML令牌处理程序将令牌字符串读入有效的XML文档),这对我来说是可行的,但它是最优的吗
var appURI = ConfigurationManager.AppSettings["app:URI"];
var fedPassiveTokenEndpoint = ConfigurationManager.AppSettings["wsFederation:PassiveTokenEndpoint"];
var fedIssuerURI = ConfigurationManager.AppSettings["wsFederation:IssuerURI"];
var fedCertificateThumbprint = ConfigurationManager.AppSettings["wsFederation:CertificateThumbprint"];
var audienceRestriction = new AudienceRestriction(AudienceUriMode.Always);
audienceRestriction.AllowedAudienceUris.Add(new Uri(appURI));
var issuerRegistry = new ConfigurationBasedIssuerNameRegistry();
issuerRegistry.AddTrustedIssuer(fedCertificateThumbprint, fedIssuerURI);
app.UseCookieAuthentication(
new CookieAuthenticationOptions
{
AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType // "Federation"
}
);
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = appURI,
SignOutWreply = appURI,
Configuration = new WsFederationConfiguration
{
TokenEndpoint = fedPassiveTokenEndpoint
},
TokenValidationParameters = new TokenValidationParameters
{
AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
},
SecurityTokenHandlers = new SecurityTokenHandlerCollection
{
new SamlSecurityTokenHandlerEx
{
CertificateValidator = X509CertificateValidator.None,
Configuration = new SecurityTokenHandlerConfiguration
{
AudienceRestriction = audienceRestriction,
IssuerNameRegistry = issuerRegistry
}
}
}
}
);
非常感谢您能为我提供任何帮助来澄清这一困惑。正如@Tratcher所说,
AuthenticationType
参数被Microsoft.Owin.Security
用作查找身份验证中间件实例的密钥
下面的代码将使用以下简单的helper方法来要求对所有请求进行身份验证。实际上,您更可能在敏感控制器上使用[Authorize]
属性,但我想要一个不依赖任何框架的示例:
private static void AuthenticateAllRequests(IAppBuilder app, params string[] authenticationTypes)
{
app.Use((context, continuation) =>
{
if (context.Authentication.User != null &&
context.Authentication.User.Identity != null &&
context.Authentication.User.Identity.IsAuthenticated)
{
return continuation();
}
else
{
context.Authentication.Challenge(authenticationTypes);
return Task.Delay(0);
}
});
}
context.Authentication.Challenge(authenticationTypes)
调用将从提供的每个身份验证类型发出身份验证质询。我们将只提供一个,我们的WS-Federation身份验证类型
正确代码
首先,这里是一个简单使用WS-Federation的站点的“最佳”Owin启动配置示例,如下所示:
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
{
AuthenticationType = "WS-Fed Auth (Primary)",
Wtrealm = ConfigurationManager.AppSettings["app:URI"],
MetadataAddress = ConfigurationManager.AppSettings["wsFederation:MetadataEndpoint"]
});
AuthenticateAllRequests(app, "WS-Fed Auth (Primary)");
app.UseWelcomePage();
}
注意使用“WS-Fed-Auth(Primary)”
AuthenticationType
来唯一标识我们配置的WS-Federation中间件实例。这意味着,例如,如果您有此要求,您可以将一个带有单独WS-Federation服务器的“WS-Feded Auth(Secondary)”
用作后备方案
此配置将执行以下操作:
CookieAuthenticationDefaults
类上的一个常量字符串,它是CookieAuthenticationOptions.AuthenticationType
属性使用的默认值。)AuthenticationType
密钥Microsoft.Owin.Security
方法,用于对任何未经身份验证的请求发出质询)public void Configuration(IAppBuilder app)
{
var x = app.GetDefaultSignInAsAuthenticationType();
app.SetDefaultSignInAsAuthenticationType(x);
}
第一个电话将为您提供您在第一条评论中提到的例外情况:
在IAppBuilder属性中找不到SignanAuthenticationType的默认值。如果身份验证中间件的添加顺序错误,或者缺少一个,则可能会发生这种情况
右-因为默认情况下,Microsoft.Owin.Security
管道不会假定您将要使用的中间件的任何内容(即,Microsoft.Owin.Security.Cookies
甚至不知道是否存在),所以它不知道默认设置应该是什么
使用错误的默认身份验证类型
今天我花了很多时间,因为我真的不知道自己在做什么:
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType("WS-Fed AAD Auth");
// ... remainder of configuration
}
因此,在每次调用时,它将继续尝试使用WS-Federation对调用方进行身份验证。这并不是说它非常昂贵,而是WS-Federation中间件实际上会对每个请求发出一个挑战。所以你永远无法进入,你会看到大量的登录URL从你身边飞过P
可能性
因此,在管道中具有所有这些灵活性的好处在于,您可以做一些非常酷的事情。例如,我有一个域,其中包含两个不同的web应用程序,运行在不同的子路径下,如:
example.com/foo
和example.com/bar
。您可以使用Owin的映射功能(如app.Map(…)
)为每个应用程序设置完全不同的身份验证管道。在我的例子中,一个使用WS-Federation,而另一个使用客户端证书。在单片系统.Web
框架中尝试这样做将是可怕的:P另外,如果我替换WsFederationAuthentica