【发布时间】:2016-04-08 14:00:10
【问题描述】:
我配置了一个使用 AD FS 的 Web 应用,为此我使用 OWIN。
对于登录,一切正常。如果我是域用户并访问该网站,他会自动连接。
但我想要的是登录后自己处理用户和角色。
所以我想检查我的数据库中是否存在使用此 AD 帐户的用户(此过程将在登录另一个应用程序之前进行)
我想使用 Microsoft 的 Identity 来处理声明(角色和权限)。但我不明白如何让我的代码处理来自 AD FS(使用 Ws-Federation)的成功连接并添加验证并填写正确的角色。
我在 ConfigureAuth 中的代码:
public partial class Startup
{
private static string realm = ConfigurationManager.AppSettings["ida:Wtrealm"];
private static string adfsMetadata = ConfigurationManager.AppSettings["ida:ADFSMetadata"];
private NLogLoggingService _loggingService;
public void ConfigureAuth(IAppBuilder app)
{
_loggingService = new NLogLoggingService("Startup");
_loggingService.Debug("ConfigureAuth");
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = adfsMetadata,
//CallbackPath = PathString.FromUriComponent("/Account/TestCallback"),
// https://msdn.microsoft.com/en-us/library/microsoft.owin.security.authenticationmode(v=vs.113).aspx
AuthenticationMode = AuthenticationMode.Passive,
//Notifications = new WsFederationAuthenticationNotifications
//{
//}
});
}
在 Web.config 中,realm 是指向我的 Web 应用 (https://ssoadfs.test) 的链接,adfsMetadata 是指向 AD FS 中 metadata.xml 的链接。
在 AD FS 连接后设置我的角色和登录逻辑的方法是什么?
我在想的架构:
编辑: 经过一些尝试,我无法处理任何成功回调。我不想处理 HomeController 中的角色...
我上次的身份验证配置:
_loggingService = new NLogLoggingService("Startup");
_loggingService.Debug("ConfigureAuth");
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationUser.ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ApplicationCookie);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
Provider = new CookieAuthenticationProvider
{
OnResponseSignIn = ctx =>
{
_loggingService.Debug("OnResponseSignIn");
ctx.Identity = TransformClaims(ctx, app);
},
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = adfsMetadata,
Caption = "Active Directory",
CallbackPath = PathString.FromUriComponent("/Account/TestCallback"),
Notifications = new WsFederationAuthenticationNotifications
{
SecurityTokenValidated = n =>
{
new NLogLoggingService("Startup").Debug("SecurityTokenValidated");
var incomingClaimsFromAdfs = n.AuthenticationTicket.Identity.Claims.ToList();
var incomingClaimsHasNameIdentifier =
incomingClaimsFromAdfs.Any(
c => c.Type == System.Security.Claims.ClaimTypes.NameIdentifier);
_loggingService.Debug("SecurityTokenValidated - incomingClaimsHasNameIdentifier: " +
incomingClaimsHasNameIdentifier);
if (!incomingClaimsHasNameIdentifier)
{
var emailClaim =
incomingClaimsFromAdfs.First(c => c.Type == System.Security.Claims.ClaimTypes.Name);
_loggingService.Debug(emailClaim.Value);
}
//if (!incomingClaimsHasNameIdentifier)
//{
// var emailClaim = incomingClaimsFromAdfs.First(c => c.Type == System.Security.Claims.ClaimTypes.Name);
// incomingClaimsFromAdfs.Add();
// IUser user = await this.UserStore.FindByNameOrEmailAsync(userNameOrEmailAddress);
// if ((Entity<long>)user == (Entity<long>)null)
// LoginResult = new ApplicationUserManager.LoginResult(LoginResultType.InvalidUserNameOrEmailAddress, default(IUser));
// //else if (!loggedInFromExternalSource && new PasswordHasher().VerifyHashedPassword(user.Password, plainPassword) != PasswordVerificationResult.Success)
// // LoginResult = new UserManager<TTenant, TRole, TUser>.LoginResult(LoginResultType.InvalidPassword, user);
// else
// LoginResult = await this.CreateLoginResultAsync(user, tenant);
//}
//else
//{
// throw new ApplicationException("Get ADFS to provide the NameIdentifier claim!");
//}
//var normalizedClaims = incomingClaimsFromAdfs.Distinct(new ClaimComparer());
//var claimsIdentity = new ClaimsIdentity(normalizedClaims, n.AuthenticationTicket.Identity.AuthenticationType);
//n.AuthenticationTicket = new AuthenticationTicket(claimsIdentity, n.AuthenticationTicket.Properties);
return Task.FromResult(0);
}
}
});
在这段代码中,我尝试了 CallbackPath(我的日志中没有出现任何内容)、WsFederationAuthenticationNotifications.SecurityTokenValidated(我的日志中没有出现任何内容)、CookieAuthenticationProvider.OnResponseSignIn(同样没有发生任何事情)
在 HomeController 中,我可以拥有 Identity.Name:
public ActionResult Index()
{
if (HttpContext.GetOwinContext().Authentication.User.Identity.IsAuthenticated)
{
new NLogLoggingService("Home").Debug("User is authenticated");
}
return View();
}
我是否错过了让通知工作或 CookieAuthenticationOptions 中的提供程序的东西???
【问题讨论】:
-
使用 AD 和身份不是开箱即用的选项。您被困在创建该功能中。您将需要 2 个 UserManager 实例配置不同...
-
你能开发“2个UserManager实例”吗?现在,我想创建一个与 AD WS-Federation 一起使用的 Wep API(仍然是 todo),然后使用 cookie 调用另一个方法来检查用户是否作为用户存在于数据库中。
-
@user18620 你好,这不是一个真正的解决方案......但我通过在 App_Start/RouteConfig 中设置默认路由在 AccountController.AuthenticationCallbackAD() 中检查了这一点。在此方法中,我创建用户或检查他是否使用 ASP.NET Identity UserManager 进行了验证。并添加自定义声明。
-
你找到这个问题的最终解决方案了吗?
-
@PreguntonCojoneroCabrón 不,我现在让它在 HomeController 中工作,这不是一个漂亮的实现,但我没有时间寻找更好的解决方案
标签: c# asp.net-mvc owin adfs ws-federation