2017-07-19 59 views
0

我正在編寫一個Angular4應用程序,並且我想使用一個RestFul API和IdentityServer4進行認證/授權。爲了讓這個過程開始,我下載了GitHub IdentityServer4Demo項目。我做了演示工作並決定添加一個ResourceOwnerPasswordValidatorProfileService服務來驗證應該有權訪問應用程序的用戶。我的問題是,現在所有的用戶ID /密碼組合觸發IdentityServer 的有效令牌,無論用戶是否有效。我在這裏錯過了什麼? the userid and password should be alice to get an access token Startup.csIdentityServer4返回一個有效的令牌,無論用戶標識和密碼組合是否有效

public void ConfigureServices(IServiceCollection services) 
    { 
     services.AddMvc(); 

     var builder = services.AddIdentityServer() 
      .AddInMemoryApiResources(Config.GetApis()) 
      .AddInMemoryIdentityResources(Config.GetIdentityResources()) 
      .AddInMemoryClients(Config.GetClients()); 
     //    .AddTestUsers(TestUsers.Users); 
     services.AddTransient<IProfileService, Configuration.ProfileService>(); 
     services.AddTransient<IResourceOwnerPasswordValidator, Configuration.ResourceOwnerPasswordValidator>(); 


     // demo versions 
     services.AddTransient<IRedirectUriValidator, DemoRedirectValidator>(); 
     services.AddTransient<ICorsPolicyService, DemoCorsPolicy>(); 

     if (_env.IsDevelopment()) 
     { 
      builder.AddTemporarySigningCredential(); 
     } 
     else 
     { 
      builder.AddTemporarySigningCredential(); 
      //builder.AddSigningCredential("6B7ACC520305BFDB4F7252DAEB2177CC091FAAE1", StoreLocation.CurrentUser, nameType: NameType.Thumbprint); 
     } 
    } 

ResourceOwnerPasswordValidator.cs

 public Task ValidateAsync(ResourceOwnerPasswordValidationContext context) 
    { 
     using (IDbConnection db = new SqlConnection("Data Source=server1;Initial Catalog=myDB;Integrated Security=SSPI;")) 
     { 
      var user = db.Query<User>("select * from Users where [email protected] and [email protected]", 
       new { UserName = context.UserName, Password = context.Password }).SingleOrDefault<User>(); 
      if (user == null) 
      { 
       context.Result = new GrantValidationResult(IdentityModel.OidcConstants.TokenErrors.UnauthorizedClient, "Invalid User of Password."); 
       return Task.FromResult<ResourceOwnerPasswordValidationContext>(context); 
      } 
      else 
      { 
       context.Result = new GrantValidationResult(user.Id.ToString(), "password"); 
       return Task.FromResult<ResourceOwnerPasswordValidationContext>(context); 
      } 

     } 
    } 

ProfileService.cs

 public class ProfileService : IProfileService 
{ 

    public Task GetProfileDataAsync(ProfileDataRequestContext context) 
    { 
     context.IssuedClaims = context.Subject.Claims.ToList(); 
     //context.IssuedClaims.Add(new Claim("test-claim", "test-value")); 
     return Task.FromResult(0); 
    } 

    public Task IsActiveAsync(IsActiveContext context) 
    { 
     return Task.FromResult(0); 
    } 
} 

Config.cs

 public static IEnumerable<Client> GetClients() 
    { 
     return new List<Client> 
     { 
      new Client 
      { 
       ClientId = "client1", 
       RequireClientSecret = false, 
       //ClientSecrets = { new Secret("secret".Sha256()) }, 
       //AccessTokenLifetime = 3600, 
       //AlwaysSendClientClaims=false, 
       AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, 
       AllowedScopes = { "openid", "profile", "email", "api","api1" }, 
            AllowOfflineAccess = true 
      }, 

回答

1

當您在線路var user = db.Query<User>("select * from Users where [email protected] and [email protected]"上設置斷點時,User在您使用無效的用戶名/密碼對其進行調用時有什麼價值?它是否爲空?如果沒有,那麼問題出在您的select/tables,因爲它找到一個用戶。

如果不爲空,那麼問題是你如何返回Task.

在我們的實現,我們正在做的事情像失敗以下:

context.Result = new GrantValidationResult(TokenRequestErrors.UnauthorizedClient); 
return Task.FromResult(false); 

和像這樣的成功...

context.Result = new GrantValidationResult(user.UserName, "password", claims); 
return Task.FromResult(0); 
0

不確定爲什麼您需要ResourceOwnerPassword流角度應用程序。您應該使用隱式或混合解決方案。

規範建議僅對 「受信任」(或傳統)應用程序使用資源所有者密碼授權。一般來說,當您要驗證用戶身份並請求訪問令牌時,您通常使用交互式OpenID Connect流程中的一個來更好。

反正,here是一個很好的示例應用程序,你可以看看,可能有助於解決您的問題。

相關問題