我可以提供一个建议,OWIN中的WsFederation选项不错,但需要使用cookies。这些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;
}