2016-04-08 57 views
5

AD FS kullanan bir Web Uygulaması yapıyorum, bunun için OWIN kullanıyorum.SSO bir hesabın nasıl oluşturulacağı ve izinlerin nasıl yönetileceği

Giriş için, her şey yolunda. Bir alanın kullanıcısıyım ve web sitesine gidersem otomatik olarak bağlanır.

Ama sahip olmak istediğim kullanıcı ve rolleri giriş yaptıktan sonra kendim halletmek.

Yani bir kullanıcı (ı iddiaları işlemek için Microsoft'tan Kimlik kullanmak istiyorum

(bu süreç olması başka bir uygulamada giriş öncesi yapacaktır) bu AD hesabıyla benim veritabanında olup olmadığını kontrol etmek istiyorum rolleri ve izinler). Ancak, kodumu AD FS'den (Ws-Federation ile) başarılı bir bağlantıya kavuşturmak için nasıl koyacağımı ve doğrulama ekleyip doğru rolleri nasıl dolduracağımı anlamıyorum. ConfigureAuth içinde

Kodum: Web.config içinde

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 
       //{ 

       //} 
      }); 

    } 

, bölge benim Web App (https://ssoadfs.test) link ve adfsMetadata AD FS metadata.xml için bağlantıdır.

AD FS bağlantısından sonra rolümü ve oturum açma mantığımı ayarlamak için ne yapmam gerekiyor? Düşünüyorum da neyi

Şema:

enter image description here

DÜZENLEME: bazı denemeden sonra, herhangi bir başarı geri arama işleyemez. (Bu kodda

  _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); 
        } 
       } 
      }); 

, I, (hiçbir şey benim günlüğünde ortaya çıktı) WsFederationAuthenticationNotifications.SecurityTokenValidated CallbackPath çalıştı: Ben

Benim son Auth yapılandırma ... HomeController rol işlemek zorunda kalmak istemiyoruz hiçbir şey (aynı şey olmadı)

HomeController i Identity.Name olması mümkün değilim CookieAuthenticationProvider.OnResponseSignIn) benim günlüğünde ortaya çıktı:

public ActionResult Index() 
    { 
     if (HttpContext.GetOwinContext().Authentication.User.Identity.IsAuthenticated) 
     { 
      new NLogLoggingService("Home").Debug("User is authenticated"); 
     } 

     return View(); 
    } 

CookieAuthenticationOptions içinde Notifications working veya Provider almak için bir şey mi kaçırdım ???

+0

değil ve kutu seçeneği dışında. Bu işlevselliği yaratabiliyorsun. Ayrı ayrı yapılandırılmış 2 KullanıcıManager örneğine ihtiyacınız olacak ... –

+0

"2 UserManager örneğini" devre dışı bırakabilir misiniz? Şimdilik, AD WS-Federation ile çalışan bir Wep API'si oluşturmayı (hala yapılacak) ve ardından kullanıcının Veritabanı olarak Kullanıcı olarak var olup olmadığını kontrol etmek için tanımlama bilgisiyle anoher yöntemini çağırmayı düşünüyorum. – Jerome2606

+0

@ user18620 Merhaba, gerçekten bir çözüm değil ... ama bunu ControlController'da kontrol ediyorum.App_Start/RouteConfig öğesinde varsayılan yolu ayarlayarak AuthenticationCallbackAD(). Bu yöntemde kullanıcıyı yaratıyorum veya ASP.NET Identity UserManager'ı kullanarak doğrulandığını kontrol ediyorum. Ve özel hak talepleri ekleyin. – Jerome2606

cevap

1

ASP.NET Identity 2.0 veya daha sonraki bir sürümünü kullanırsanız, aşağıdakine benzer bir yaklaşım kullanabilirsiniz. Lütfen bu yaklaşımın, her bir rolün birer birer atanması yerine kullanıcıya GroupRoles değerini atadığını unutmayın. Gereksiniminize göre gerekli parçaları değiştirebilirsiniz. AD ve Kimlik kullanarak bu yardımcı olur

[HttpPost] 
[AllowAnonymous] 
[ValidateAntiForgeryToken] 
public async Task<ActionResult> 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=******", "[email protected]", "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; 
} 


Umut ...

+0

Merhaba Murat, bana yardım etmeye çalıştığınız için teşekkürler. Ama benim problemim, OWIN’in doğru yolunda bir geri bildirimle başedemem. Bir uygulama SSO'su olduğu için bir Giriş sayfasına asla geçmeyeceğim (bu nedenle, Owin'den önce benim Uygulama'ya girmeden önce kullanıcının kimliği doğrulanır). Şimdilik, kullanıcının kimlik doğrulaması yapılıp yapılmadığını kontrol etmek için HomeController'da mantık ekledikten sonra UserManager ... 'da kullanıcı ekleyin ... :( – Jerome2606

+0

Hoşgeldin Jerome. Neden AccountController yerine kullandığınız HomeController'ı anlayamadım? yeterince zamanınız var ve ASP.NET Identity 2.0 ya da daha sonra kullanılmadı, [ASP.NET MVC ve Identity 2.0: Temelleri Anlama] gibi makalelere bakabilirsiniz (http://www.codeproject.com/Articles/762428)/ASP-NET-MVC-ve-Kimlik-Anlayış Temelleri) İyi şanslar :) –

+0

AspNet.Identity.Core, .EntityFramework, .Owin kullanıyorum. Ancak, yapılandırmayı basitleştirmek için AD FS ve Owin'i kullanmak istiyorum (yalnızca AD'den metadata.xml gerekli). Ben UserManager ile kimliğinize benzer bir kod kullanıyorum ve bu mantığı HomeController'a eklemek bir seçenek değil. Varsayılan Rotayı tanımlayarak AccountController'a koyabilirdim. Ama eminim ki Owin, Startup Auth Config'de bunu halletmeme yardımcı olabilir. – Jerome2606