2017-04-10 163 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