我可以提供 OWIN 中的 WsFederation 选项很好,但需要 cookie……而且它们是与带有 cookie 的本地身份验证不同类型的 cookie。ADFS 2.0/WsFederation 使用 AuthenticationType="Cookies",本地身份验证使用 AuthenticationType="ApplicationCookie"。据我所知,它们显然是不相容的。我认为您必须对 ADFS 使用令牌身份验证,但我认为这需要 2012R2 上的 ADFS 3.0。为此,请使用 OWIN OAuth。
更新:在研究了一段时间后,我想出了如何让这两种身份验证类型在同一个 Web 应用程序中和平共存。使用 OWIN,设置两次调用 UseCookieAuthentication,一次启用新的 WsFederationAuthentication 中间件,再次启用本地 cookie 身份验证。这并不直观,但在幕后,为每个指定不同的身份验证类型将它们设置为不同的身份验证“引擎”。这是它在我的 Startup 中的外观:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnResponseSignIn = ctx =>
{
ctx.Identity = TransformClaims(ctx, app);
}
}
});
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
Provider = new CookieAuthenticationProvider
{
OnResponseSignIn = ctx =>
{
ctx.Identity = TransformClaims(ctx, app);
}
}
});
app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
{
Wtrealm = Realm,
MetadataAddress = Metadata,
Caption = "Active Directory",
SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType
});
这成功地允许用户对本地 SQL 表或 ADFS 2.0 进行身份验证。TransformClaims 标注允许我规范这两个提供者之间的声明,以便它们保持一致。
编辑:这是一个非常基本的 TransformClaims。你可以在其中做很多事情:从你的数据库中获取用户,设置导航声明,自定义权限,角色集合等等。我刚刚从一个更大的实现中构建了这个精简版本,所以我没有运行它,但希望您了解如何利用 OnResponseSignIn 事件。
private static ClaimsIdentity TransformClaims(CookieResponseSignInContext ctx, IAppBuilder app)
{
var ident = ctx.Identity;
var claimEmail = ident.Claims.SingleOrDefault(c => c.Type == ClaimTypes.Email);
var claimName = ident.Claims.SingleOrDefault(c => c.Type == ClaimTypes.Name);
//normalize my string identifier
var loginString = (claimEmail != null) ? claimEmail.Value : (claimName != null) ? claimName.Value : null;
var efctx = ctx.OwinContext.Get<DBEntities>();
var user = UserBL.GetActiveUserByEmailOrName(efctx, loginString);
if (user == null)
{
//user was auth'd by ADFS but hasn't been auth'd by this app
ident.AddClaim(new Claim(ClaimTypesCustom.Unauthorized, "true"));
return ident;
}
if (ident.Claims.First().Issuer == "LOCAL AUTHORITY")
{
//Local
//local already has claim type "Name"
//local didn't have claim type "Email" - adding it
ident.AddClaim(new Claim(ClaimTypes.Email, user.Email));
}
else
{
//ADFS
//ADFS already has claim type "Email"
//ADFS didn't have claim type "Name" - adding it
ident.SetClaim(ClaimTypes.Name, user.UserName);
}
//now ident has "Name" and "Email", regardless of where it came from
return ident;
}