如何从Redis中的值填充UserAuth?

时间:2014-07-17 08:22:36

标签: redis servicestack authentication

这是我的global.asax文件中的自定义用户身份验证设置,但我目前正在Configure方法中手动提供用户;是否可以从Redis服务器获取值?

例如,如果用户存在且密码正常,可以自动填写这些详细信息吗?

Plugins.Add(new AuthFeature(()=> 
    new AuthUserSession(), 
    new IAuthProvider[]{ new BasicAuthProvider() }
));

container.Register<ICacheClient>(new MemoryCacheClient());
var userRepo = new InMemoryAuthRepository();
container.Register<IUserAuthRepository>(userRepo);

string hash, salt;
new SaltedHash().GetHashAndSaltString("password", out hash, out salt);

userRepo.CreateUserAuth(new UserAuth
{
    Id = 1,
    DisplayName = "Haluk",
    Email = "hal",
    UserName = "haluk",
    FirstName = "haluk",
    LastName = "yılmaz",
    PasswordHash = hash,
    Salt = salt
}, "password");

1 个答案:

答案 0 :(得分:2)

是的,您可以针对Redis数据源进行身份验证。您可以使用内置的RedisAuthRepository代替InMemoryAuthRepository,或者如果您要使用现有的Redis数据集而不是内置的IAuthRepository模式,我已经包含了一个解决方案,您可以扩展BasicAuthProvider。第一种方法最直接:

使用RedisAuthRepository

  1. 因此您需要建立与Redis的连接。
  2. 然后注册您的身份验证提供程序。
  3. 注册RedisAuthRepository,身份验证提供商将检查凭据,并与RegistrationFeature
  4. 兼容
    private IRedisClientsManager redisClientsManager;
    
    public override void Configure(Funq.Container container)
    {
        // Configure ServiceStack to connect to Redis
        // Replace with your connection details
        redisClientsManager = new PooledRedisClientManager("127.0.0.1:6379");
        container.Register<IRedisClientsManager>(c => redisClientsManager);
        container.Register<ICacheClient>(c => c.Resolve<IRedisClientsManager>().GetCacheClient()).ReusedWithin(Funq.ReuseScope.None);
    
        // Setup the authorisation feature
        Plugins.Add(new AuthFeature(()=> 
            new AuthUserSession(),
            new IAuthProvider[]{ new BasicAuthProvider() }
        ));
    
        // Use a RedisAuthRepository
        var userRepo = new RedisAuthRepository(redisClientsManager);
        container.Register<IUserAuthRepository>(userRepo);
    
        // You can then register users as required using the RegistrationFeature
    }
    

    或者(如果您在Redis中有现有的用户身份验证数据集)

    您可以通过创建extends the existing BasicAuthProvider的自定义身份验证提供程序来执行此操作。

    对于此代码,您还应确保熟悉the ServiceStack.Redis client

    扩展BasicAuthProvider

    MyRedisBasicAuthProvider扩展了现有的BasicAuthProvider,而不是像示例代码中给出的IUserAuthRepository执行凭据查找,而是进行Redis连接并将用户名与条目匹配在Redis。

    代码已完全注释,但如果有任何内容需要进一步解释,请告诉我。

    public class MyRedisBasicAuthProvider : BasicAuthProvider
    {
        // The key at which we will store the user profile. i.e user:john.smith or user:homer.simpson
        // Replace this key with your format as required
        public const string UserKeyFormat = "user:{0}";
    
        MyUser CurrentUser;
    
        // Gets an instance of a redis client
        static IRedisClient GetRedisClient()
        {
            // Get the RedisClientsManager from the Container
            var redisClientManager = HostContext.TryResolve<IRedisClientsManager>();
            if(redisClientManager == null)
                throw new Exception("Redis is not configured");
    
            // Return a client
            return redisClientManager.GetClient();
        }
    
        // This method is used to verify the credentials provided
        public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
        {
            // Get a Redis client connection
            using(var redisClient = GetRedisClient())
            {
                // Get a typed Redis Client
                var userClient = redisClient.As<MyUser>();
    
                // Try to find a matching user in Redis
                CurrentUser = userClient.GetValue(string.Format(UserKeyFormat, userName));
    
                // Check the user exists & their password is correct (You should use a hashed password here)
                return CurrentUser != null && password == CurrentUser.Password;
            }
        }
    
        // This method is used to populate the session details from the user profile and other source data as required
        public override IHttpResult OnAuthenticated(IServiceBase authService, IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo)
        {
            // Populate the session with the details of the current user
            session.PopulateWith<IAuthSession, MyUser>(CurrentUser);
    
            // Save the session
            authService.SaveSession(session);
    
            return null;
        }
    
        public static void AddUserToRedis(MyUser user)
        {
            using(var redisClient = GetRedisClient())
            {
                // Get a typed Redis Client
                var userClient = redisClient.As<MyUser>();
    
                // Add the user to Redis
                userClient.SetEntry(string.Format(UserKeyFormat, user.Username), user);
            }
        }
    }
    

    在上面的代码中,我使用了一个类MyUser来表示我在Redis中存储的用户配置文件,您当然可以自定义此类以符合您的用户配置文件要求。所以这是基本的用户配置文件类:

    public class MyUser
    {
        public string Username { get; set; }
        public string Password { get; set; } // Replace with a hashed password
        public string Email { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    

    使用Redis设置ServiceStack&amp;您的自定义身份验证提供程序:

    您需要配置ServiceStack以使用Redis并告诉它使用您的自定义身份验证提供程序。您可以在Configure

    中的AppHost方法中添加以下内容
    public override void Configure(Funq.Container container)
    {
        // Configure ServiceStack to connect to Redis
        // Replace with your connection details
        container.Register<IRedisClientsManager>(c => new PooledRedisClientManager("127.0.0.1:6379"));
        container.Register<ICacheClient>(c => c.Resolve<IRedisClientsManager>().GetCacheClient()).ReusedWithin(Funq.ReuseScope.None);
    
        // Add your custom credentials provider
        Plugins.Add(new AuthFeature(() => new AuthUserSession(),
            new IAuthProvider[] {
                new MyRedisBasicAuthProvider()
            }
        ));
    
        // Add some test users. (If you have an existing Redis user source, you won't need to add test users.)
        MyRedisBasicAuthProvider.AddUserToRedis(new MyUser {
            Username = "john.smith",
            Password = "test",
            Email = "john.smith@email.com",
            FirstName = "John",
            LastName = "Smith",
        });
    
        MyRedisBasicAuthProvider.AddUserToRedis(new MyUser {
            Username = "homer.simpson",
    
            Password = "donuts",
            Email = "homer.simpsons@springfield.com",
            FirstName = "Homer",
            LastName = "Simpson",
        });
    
        // Your other configuration settings ...
    }
    

    说明:

    在示例中,我没有使用哈希密码,以保持示例简单明了,但这很简单。将另一个字段public string Salt { get; set; }添加到MyUser,然后将{1}}上的普通密码存储为密码和盐的哈希,即MyUser。你已经有了代码:

    hashedPassword = HashAlgorithm(password + salt)

    因此,当使用string hash, salt; new SaltedHash().GetHashAndSaltString("password", out hash, out salt); 属性保护服务时,此解决方案现在将使用Redis数据源对用户进行身份验证。与标准基本提供程序一样,凭据在标准[Authenticate]路由进行身份验证。

    使用凭据提供程序而不是基本:
    如果您想使用凭据提供程序进行表单发布,而不是基本身份验证,则可以在上面的代码中使用/auth/basic简单地替换单词Basic

    我希望这会有所帮助。