2015-12-15 62 views
2

[編輯:增加了UserService代碼]identityserver3定製usersevice不會被調用

當我IdentityServer內將下面的代碼已經在ADUserService說和.UseInmemory(MemUser.TempUser)代碼不予置評,一切工作正常。

當InMemory被標記並且兩個ADUserService行沒有標記爲下面的代碼時,將顯示相同的登錄屏幕,但是這次失敗。在調試時,沒有顯示日誌,並且在登錄期間沒有輸入ADUserService,但僅在調用啓動代碼期間。

我錯過了什麼嗎?難道我做錯了什麼?

 // identityServer factory 
     var factory = new IdentityServerServiceFactory() 
     //   .UseInMemoryUsers(MemUser.TempUser) // Fix: Remove temp users!! 
        .UseInMemoryClients(CrbAuthClients.Get()) 
        .UseInMemoryScopes(Scopes.AllSupportedScopes); 

     var userService = new ADUserService(); 
     factory.UserService = new Registration<IUserService>(resolver => userService); 



     // identityServer go!! 
     var options = new IdentityServerOptions 
     { 
      SigningCertificate = Certificate.Load(), 
      AuthenticationOptions = new AuthenticationOptions 
        { 
         SignInMessageThreshold = 1 // default is 5, prevents "Header Too Long" error 
        }, 
      Factory = factory 
     }; 

     app.UseIdentityServer(options); 

難道這是由於我使用Visual Studio和IIS快遞在HTTPS是不是無論是IDServ3服務器(南錫)或我的MVC客戶端驗證?

難道我需要添加CORS策略服務嗎?我什麼時候需要這個?我從單獨的MVC項目和網站調用身份驗證。

factory.CorsPolicyService = new Registration<ICorsPolicyService>(new DefaultCorsPolicyService { AllowAll = true }); 

難道是因爲我以前使用inMem用戶的問題,現在有某種緩存的地方還在使用? (我查了鮑勃 - 祕密制止了變更後的工作,並改回時對內存中的用戶返回工作)

----- -----編輯

也許是因爲對我沒有使用ldapConnectionDelegate? 我需要嗎?

下面的代碼:

namespace Crb.Auth.AuthServer.Securing 
{ 
    using System; 
    using System.Configuration; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web; 
    using System.Threading.Tasks; 
    using System.DirectoryServices; 
    using System.Security.Claims; 

    using System.DirectoryServices.AccountManagement; 
    using IdentityServer3.Core; 
    using IdentityServer3.Core.Services; 
    using IdentityServer3.Core.Models; 
    using IdentityServer3.Core.Extensions; 
    using IdentityServer3.Core.Services.Default; 

    using Serilog; 

    // according to gist https://gist.github.com/rmbrunet/6c5c2ba2b8fb03fbc359 
    // from rmbrunet on Stack Exchange here: https://github.com/IdentityServer/IdentityServer3/issues/1366 

    // A slightly cleaner but less explicit approach (not used here) is in https://gist.github.com/tjrobinson/0ad6c790e90d7a385eb1 
    // from rajarameshvarma on Stack Exchange here: https://github.com/IdentityServer/IdentityServer3/issues/995 

    // Startup code is taken from the CustomUserService project in the IdentityServer3 Samples. 

    public class ADUserService : UserServiceBase //UserServiceBase 
    { 
     static class ADAttributes 
     { 
      public static string SamAccountName = "samaccountname"; 
      public static string Mail = "mail"; 
      public static string UserGroup = "usergroup"; 
      public static string DisplayName = "displayname"; 
      public static string Department = "department"; 
      public static string StreetAddress = "streetAddress"; 
      public static string Phone = "telephoneNumber"; 
      public static string State = "st"; 
      public static string City = "l"; 
      public static string Zip = "postalCode"; 
      public static string Surname = "sn"; 
      public static string Givenname = "givenName"; 
     } 

     const string ActiveDirectoryConnectionStringname = "CnnActiveDir"; 

     #region setup and construction 
     //Func<string, string> _ldapConnectionDelegate; //Delegate that receives the domain and returns the LDAP connection string. 

     // default ctor reads from connection string 
     public ADUserService()//Func<string, string> ldapConnectionDelegate) 
     { 
      //_ldapConnectionDelegate = ldapConnectionDelegate; 
      //Log.Debug("ADUserService called"); 
     } 
     //.. region setup and construction 
     #endregion 

     #region authenticate with claims 

     #region authenticate external - not supported 
     public System.Threading.Tasks.Task<IdentityServer3.Core.Models.AuthenticateResult> AuthenticateExternalAsync(IdentityServer3.Core.Models.ExternalIdentity externalUser, IdentityServer3.Core.Models.SignInMessage message) 
     { 
      return Task.FromResult<AuthenticateResult>(null); 
     } 
     #endregion 

     public Task<AuthenticateResult> AuthenticateLocalAsync(
      string userDomainAndName, // sometimes referred to as 'the subject' 
      string password, 
      SignInMessage message) 
     { 

      bool isUserValid = false; 

      if (string.IsNullOrEmpty(userDomainAndName) 
       || userDomainAndName.IndexOf(@"\") < 1) // expected: some domain name given followed by a backslash 
      { 
       Log.Debug("Supplied username missing domain. Authentication denied."); 
       return Task.FromResult<AuthenticateResult>(null); // Failed!! 
      } 
      var split = userDomainAndName.ToLower().Split('\\'); //username assumed to be in the form domain\user 
      string domain = split[0]; 
      string username = split[1]; 


      using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain)) 
      { 
       isUserValid = pc.ValidateCredentials(username, password); 
      } 

      if (!isUserValid) 
      { 
       Log.Debug("Authentication attempt failed for {0}", userDomainAndName); 
       return Task.FromResult<AuthenticateResult>(null); 
      } 

      return Task.FromResult<AuthenticateResult>(
       new AuthenticateResult(subject: username.ToLower(), name: username)); 
     } 

     #region pre-authenticate async - not supported 
     public System.Threading.Tasks.Task<IdentityServer3.Core.Models.AuthenticateResult> PreAuthenticateAsync(IdentityServer3.Core.Models.SignInMessage message) 
     { 
      return Task.FromResult<AuthenticateResult>(null); 
     } 
     #endregion 
     //..region authenticate 
     #endregion 

     #region profile 

     public System.Threading.Tasks.Task<IEnumerable<System.Security.Claims.Claim>> GetProfileDataAsync(
      System.Security.Claims.ClaimsPrincipal principal, 
      IEnumerable<string> requestedClaimTypes = null) 
     { 

      List<System.Security.Claims.Claim> claims = new List<Claim>(); //x null; 


      string subject = principal.GetSubjectId(); 
      if (! string.IsNullOrEmpty(subject)) 
       claims.Add(new Claim(Constants.ClaimTypes.Subject, subject)); // notice: idsrv3 short name convention as opposed to claims with full type 

      SearchResult result = findUser(subject); 
      if (result != null && 
       result.Properties.Contains(ADAttributes.Mail) && 
       result.Properties.Contains(ADAttributes.DisplayName)) 
      { 
       claims.Add(new Claim(ClaimTypes.Email, (String)result.Properties[ADAttributes.Mail][0])); 
       claims.Add(new Claim(ClaimTypes.Name, (String)result.Properties[ADAttributes.DisplayName][0])); 

       if (result.Properties.Contains(ADAttributes.Surname)) 
        claims.Add(new Claim(ClaimTypes.Surname, (String)result.Properties[ADAttributes.Surname][0])); 

       if (result.Properties.Contains(ADAttributes.Givenname)) 
        claims.Add(new Claim(ClaimTypes.GivenName, (String)result.Properties[ADAttributes.Givenname][0])); 

       //Is there an address? 
       if (result.Properties.Contains(ADAttributes.State) 
        && result.Properties.Contains(ADAttributes.StreetAddress) 
        && result.Properties.Contains(ADAttributes.City) 
        && result.Properties.Contains(ADAttributes.Zip)) 
       { 

        string state = (String)result.Properties[ADAttributes.State][0]; 
        string street = (String)result.Properties[ADAttributes.StreetAddress][0]; 
        string city = (String)result.Properties[ADAttributes.City][0]; 
        string zip = (String)result.Properties[ADAttributes.Zip][0]; 

        string address = string.Format("{0}, {1}, {2} {3}", street, city, state, zip); 
        claims.Add(new Claim(ClaimTypes.StreetAddress, address)); 
       } 

       // Get roles from AD user groups 
       var prince = principal.Identity as UserPrincipal; 
       var groups = prince.GetGroups(); 
       foreach (var group in groups) 
        claims.Add(new Claim(ClaimTypes.Role, "dpn:" + group.DisplayName+",dtn:"+group.DistinguishedName)); 

       claims = claims.Where(x => requestedClaimTypes.Contains(x.Type)).ToList(); 
      } 

      return Task.FromResult(claims.AsEnumerable()); 
     } 
     //.. region profile 
     #endregion 

     #region sign-out 

     public System.Threading.Tasks.Task SignOutAsync(System.Security.Claims.ClaimsPrincipal subject) 
     { 
      return Task.FromResult(0); 
     } 
     //..region sign-out 
     #endregion 

     #region internals 

     SearchResult findUser(string subject) 
     { 
      string[] a = subject.Split('\\'); 

      string domain = a[0]; 
      string username = a[1]; 

      string node = ConfigurationManager.ConnectionStrings[ActiveDirectoryConnectionStringname].ConnectionString; 
          //x _ldapConnectionDelegate(domain); 


      using (DirectoryEntry searchRoot = new DirectoryEntry(node)) 
      { 
       using (DirectorySearcher search = new DirectorySearcher(searchRoot)) 
       { 

        search.Filter = string.Format("(&(objectClass=user)(objectCategory=person)(SAMAccountName={0}))", username); 
        //search.PropertiesToLoad.Add(Constants.ADAttributes.SamAccountName); 
        search.PropertiesToLoad.Add(ADAttributes.Mail); 
        search.PropertiesToLoad.Add(ADAttributes.UserGroup); 
        search.PropertiesToLoad.Add(ADAttributes.DisplayName); 
        search.PropertiesToLoad.Add(ADAttributes.Surname); 
        search.PropertiesToLoad.Add(ADAttributes.Givenname); 
        search.PropertiesToLoad.Add(ADAttributes.Department); 
        search.PropertiesToLoad.Add(ADAttributes.StreetAddress); 
        search.PropertiesToLoad.Add(ADAttributes.Phone); 
        search.PropertiesToLoad.Add(ADAttributes.State); 
        search.PropertiesToLoad.Add(ADAttributes.City); 
        search.PropertiesToLoad.Add(ADAttributes.Zip); 

        return search.FindOne(); 
       } 
      } 
     } 

     public System.Threading.Tasks.Task<bool> IsActiveAsync(System.Security.Claims.ClaimsPrincipal principal) 
     { 
      string subject = principal.GetSubjectId(); // this should return the "distinguished name" (sub.maindomain/username) 
      SearchResult result = findUser(subject); 
      return Task.FromResult(result != null); 
     } 
     //.. region internals 
     #endregion 
    } 
} 
+0

也許我在做錯的是,我沒有「上下文功能」。 我將編輯問題並添加userService代碼 – pashute

回答

0

我看不出什麼明顯的毛病,你在做什麼。你檢查過日誌嗎?

我發現它們在實現IdServer時非常有用。你可以很容易地用Serilog寫出來。

下面是一些示例代碼;

public static void Configuration(IAppBuilder appBuilder) 
{ 
    Log.Logger = new LoggerConfiguration() 
     .MinimumLevel.Debug() 
     .WriteTo.Trace() 
     .CreateLogger(); 

    //id server initialisation... 
} 
+0

是的,我使用了serilog。在調用構造函數之後沒有任何反應,構造函數本身被調用(並且什麼都不做)然後在用ID和用戶名登錄IDSrv3登錄頁面之後,它只是迴應用戶沒有被授權 – pashute