使用AD FS和OWIN的SSO如何创建帐户和处理权限

我配置了一个使用AD FS的Web App,为此我使用了OWIN。

对于登录,一切都好。 如果我是域名的用户并访问该网站,则会自动连接。

但我想要的是在登录后自己处理用户和角色。

所以我想用这个AD帐户检查我的数据库中是否存在用户(此过程将在另一个应用程序登录之前生成)

我想使用Microsoft的Identity来处理声明(角色和权限)。 但我不明白如何将我的代码用于处理来自AD FS(使用Ws-Federation)的成功连接,并添加validation并填写正确的角色。

我在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 App的链接( https://ssoadfs.test ),adfsMetadata是AD FS的metadata.xml链接。

AD FS连接后设置角色和登录逻辑的方法是什么?

架构,我在想什么:

在此处输入图像描述

编辑:经过一些尝试,我无法处理任何成功的回调。 我不想在HomeController中处理角色……

我上次的Auth配置:

  _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.Create); app.CreatePerOwinContext(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( 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)user == (Entity)null) // LoginResult = new ApplicationUserManager.LoginResult(LoginResultType.InvalidUserNameOrEmailAddress, default(IUser)); // //else if (!loggedInFromExternalSource && new PasswordHasher().VerifyHashedPassword(user.Password, plainPassword) != PasswordVerificationResult.Success) // // LoginResult = new UserManager.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中获取通知工作或提供商的内容?

如果使用ASP.NET Identity 2.0或更高版本,则可以使用与下面所示类似的方法。 请注意,此方法将GroupRoles分配给用户,而不是GroupRoles分配每个角色。 您可以根据需要更换必要的零件。

 [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task Login(LoginViewModel model, string returnUrl) { if (!ModelState.IsValid) { return View(model); } ApplicationGroupManager groupManager = new ApplicationGroupManager(); if (Membership.ValidateUser(model.UserName, model.Password)) { FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); //Assign Roles to the current User ApplicationUser user = UserManager.FindByName(model.UserName); //If the user is registered in the system (ASP.NET Identity) add record to AspNetUsers table if (user != null) { //Returns Group Id and Role Id by using User Id parameter var userGroupRoles = groupManager.GetUserGroupRoles("bfd9730e-2093-4fa0-89a2-226e301d831b"); foreach (var role in userGroupRoles) { string roleName = RoleManager.FindById(role.ApplicationRoleId).Name; UserManager.AddToRole(user.Id, roleName); } } else { //crate new user //first retrieve user info from LDAP: // Create an array of properties that we would like and add them to the search object string[] requiredProperties = new string[] { "samaccountname", "givenname", "sn", "mail", "physicalDeliveryOfficeName", "title" }; var userInfo = CreateDirectoryEntry(model.UserName, requiredProperties); var newUser = new ApplicationUser(); newUser.UserName = userInfo.GetDirectoryEntry().Properties["samaccountname"].Value.ToString(); newUser.Name = userInfo.GetDirectoryEntry().Properties["givenname"].Value.ToString(); newUser.Surname = userInfo.GetDirectoryEntry().Properties["sn"].Value.ToString(); newUser.Email = userInfo.GetDirectoryEntry().Properties["mail"].Value.ToString(); newUser.EmailConfirmed = true; newUser.PasswordHash = null; var result = await UserManager.CreateAsync(newUser); if (result.Succeeded) { //If the user is created ... } //Assign user group (and roles) var defaultGroup = "751b30d7-80be-4b3e-bfdb-3ff8c13be05e"; groupManager.SetUserGroups(newUser.Id, new string[] { defaultGroup }); } return this.RedirectToAction("Index", "Issue"); } this.ModelState.AddModelError(string.Empty, "Wrong username or password!"); return this.View(model); } static SearchResult CreateDirectoryEntry(string sAMAccountName, string[] requiredProperties) { DirectoryEntry ldapConnection = null; try { ldapConnection = new DirectoryEntry("LDAP://OU=******, DC=******, DC=******", "acb@xyz.com", "YourPassword"); ldapConnection.AuthenticationType = AuthenticationTypes.Secure; DirectorySearcher search = new DirectorySearcher(ldapConnection); search.Filter = String.Format("(sAMAccountName={0})", sAMAccountName); foreach (String property in requiredProperties) search.PropertiesToLoad.Add(property); SearchResult result = search.FindOne(); //SearchResultCollection searchResultCollection = search.FindAll(); //You can also retrieve all information if (result != null) { return result; } else { return null; //Console.WriteLine("User not found!"); } } catch (Exception e) { Console.WriteLine("Exception caught:\n\n" + e.ToString()); } return null; } 

希望这可以帮助…