2017-04-10 106 views
1

我指的是this question。如果服務器啓動時不存在,我嘗試創建一個服務器帳戶。我已覆蓋OnAfterInit來執行此操作。不幸的是沒有創建密鑰,更糟的是,我的ApiKeyAuthProvider似乎是空的!下面是代碼:API密鑰保留爲空

public class AppHost : AppHostHttpListenerBase 
{ 
    private PooledRedisClientManager RedisBusPool { get; set; } 

    public override void Configure(Container container) 
    { 
     RedisBusPool = new PooledRedisClientManager(connStrBus); 

     #region IOC registrations 
     container.Register<IRedisClientsManager>(c => new PooledRedisClientManager(connStrBus)); 
     container.Register(c => new RedisAuthRepository(RedisBusPool)); 
     //... 
     #endregion 


     #region ServiceStack plugins 
     Plugins.Add(new AuthFeature(() => new AuthUserSession(), 
      new IAuthProvider[] { 
       new BediCredentialsAuthProvider(), 
       new ApiKeyAuthProvider(AppSettings) 
       { 
        KeyTypes = new []{"secret", "publishable"}, 
       }, 
      } 
     )); 
     //... 

     #endregion 
     //... 
    } 

    public override void OnAfterInit() 
    { 
     #region Add test users 
     var authRepo = TryResolve<RedisAuthRepository>(); 
     var user = authRepo.GetUserAuthByUserName("JoeTest"); 
     if (user == null) 
     { 
      var newUser = new UserAuth(); 
      newUser.UserName = "JoeTest"; 
      newUser.Email = "[email protected]"; 
      newUser.FirstName = "Joe"; 
      newUser.LastName = "Test"; 
      user = authRepo.CreateUserAuth(newUser, "topSecret!"); 
     } 

     var keys = authRepo.GetUserApiKeys(user.Id.ToString()); 
     foreach (var apiKey in keys) 
     { 
      Debug.WriteLine(apiKey); 
     } 

     //CANT GET THE AUTHPROVIDER IT IS ALWAYS NULL HERE 
     var authProvider = (ApiKeyAuthProvider)AuthenticateService.GetAuthProvider(ApiKeyAuthProvider.Name); 


     #endregion 
     base.OnAfterInit(); 
    } 

} 

用戶可以成功地創建密碼,鹽等。這裏是我的Redis數據庫顯示:

{ 
    "__type": "ServiceStack.Auth.UserAuth, ServiceStack", 
    "Id": 2, 
    "UserName": "JoeTest", 
    "Email": "[email protected]", 
    "FirstName": "Joe", 
    "LastName": "Test", 
    "Salt": "1/696g==", 
    "PasswordHash": "FZNI5cR5TWTpbvvm9PDy/w/JdRZImQYU5m5P6z8j7TY=", 
    "DigestHa1Hash": "e4e0cff88386c6f991d13a3802ce7b53", 
    "Roles": [], 
    "Permissions": [], 
    "CreatedDate": "\/Date(1491811177540)\/", 
    "ModifiedDate": "\/Date(1491811177540)\/", 
    "InvalidLoginAttempts": 0 
} 

問題:

  1. 是如何API密鑰是否已創建?我錯過了什麼或者只有在啓用RegistrationFeature時才起作用?如果是這樣,我該如何保護這一點(在我的方案中不允許自我註冊)以及我的服務初始化後如何使用它?
  2. 我是通過RedisAuthRepository.cs的代碼瀏覽了一下,發現這樣的:

    var saltedHash = HostContext.Resolve<IHashProvider>();

這是否意味着我可以實現和插件在我自己的HashProvider?如果是的話,那是如何工作的?

UPDATE

我想通了,我可以指定鍵,但只有當我把代碼放到AfterInitCallbacks.Add。它似乎被稱爲AFTER OnAfterInit()

所以這個代碼創建ServiceStartup過程中生成的帳號的關鍵是:

AfterInitCallbacks.Add(host => 
{ 

    var authProvider = (ApiKeyAuthProvider)AuthenticateService.GetAuthProvider(ApiKeyAuthProvider.Name); 
    var authRepo = (IManageApiKeys)TryResolve<RedisAuthRepository>(); 
    var userRepo = (IUserAuthRepository)TryResolve<RedisAuthRepository>(); 
    var user = userRepo.GetUserAuthByUserName("JoeTest"); 

    var keys = authRepo.GetUserApiKeys(user.Id.ToString()); 
    if (keys.Count == 0) 
    { 
     try 
     { 
      keys = authProvider.GenerateNewApiKeys(user.Id.ToString()); 
      authRepo.StoreAll(keys); 

     } 
     catch (Exception e) 
     { 
      Debug.WriteLine(e); 
      throw; 
     } 
    } 
}); 

至少我可以看到什麼是對Redis的產生了。但是,我仍然不清楚如何自動創建密鑰

回答

1

首先,你也應該只有一個PooledRedisClientManager單實例所有連接池一起,所以你也應該改變你的Redis客戶端管理器連接到重複使用相同的實例,例如:

container.Register<IRedisClientsManager>(c => RedisBusPool); 

用戶認證信息庫應對IAuthRepository接口註冊,以便它可以解決的,所以你需要將它更改爲:

container.Register<IAuthRepository>(c => new RedisAuthRepository(RedisBusPool)); 

,你現在會與檢索:

var authRepo = (IUserAuthRepository)TryResolve<IAuthRepository>(); 

至於檢索ApiKeyAuthProvider,我確認這按預期工作:

var authProvider = (ApiKeyAuthProvider) 
    AuthenticateService.GetAuthProvider(ApiKeyAuthProvider.Name); 

如果你在AuthFeature如圖所示,應當退還註冊ApiKeyAuthProvider。我會仔細檢查Null引用錯誤是不是由於另一個問題。

+0

謝謝,戴米斯。我剛剛更新了我的原始帖子。我只是在你的答案中進行更正。 – ThommyB

+0

@ThommyB我不知道你是什麼意思**自動創建**?調用'StoreAll()'是創建API密鑰的原因。 – mythz

+0

我的意思是用創建用戶來創建密鑰,所以我不必調用StoreAll()。該文檔說:'雖然API密鑰認證提供程序將自動爲新用戶生成API密鑰,如果......' – ThommyB