当前位置: 首页 > 面试题库 >

如何从Redis中的值填充UserAuth?

沈骞仕
2023-03-14
问题内容

这是我文件中的自定义用户身份验证设置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");

问题答案:

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

使用RedisAuthRepository

  1. 因此,您需要建立与Redis的连接。
  2. 然后注册您的身份验证提供程序。
  3. 注册RedisAuthRepository,身份验证提供者将检查,并且与兼容RegistrationFeature
    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
    }

您可以通过创建扩展现有BasicAuthProvider的自定义身份验证提供程序来实现。

对于此代码,还应该确保您熟悉ServiceStack.Redis客户端。

扩展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:

您将需要配置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而不是将普通密码MyUser存储为密码和salt的哈希值,即hashedPassword = HashAlgorithm(password + salt)。您已经有了代码:

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

因此,当使用[Authenticate]属性保护服务安全时,此解决方案现在将使用Redis数据源对用户进行身份验证。与标准基本提供程序一样,凭据在标准/auth/basic路由上进行身份验证。

使用证书提供商,而不是基本的:
如果你想使用的表单提交一个证书提供商,而不是基本身份验证,您可以简单替换的单词BasicCredentials在上面的代码。

我希望这有帮助。



 类似资料:
  • 问题内容: 我有一个大查询表,看起来像这样:![Table [(https://ibb.co/1ZXMH71)如您所见,大多数值都是空的。我想向前填充这些空值,这意味着使用按时间排序的最后一个已知值。 显然,有一个名为FILL的函数但是我不知道如何使用它。 这是我尝试过发布到Web UI的查询: 我得到的错误是:语法错误:[3:6]处出现意外的标识符“ sns_6”,我想要的是获取一个新表,其中s

  • 我有一个用分号分隔的字符串,如下所示:。 看,后面缺少一个值。我想用(以前的值)填充丢失的数字,并将其存储到另一个字符串中。

  • 作为我作业的一部分,我们得到了一个我们不能更改的接口,以及一些用来开发我们方法的预定义测试。 界面如下: 我正在运行的特定测试: 以及我需要从测试中创建的方法: 从测试中我可以看出,在方法中,我需要创建并用注册映射中匹配的学生填充它,然后返回列表。 我创建了以下字段:- 我搞不懂的是,如何将注册地图中的数据传递到学生列表中,以使测试中的断言为真。

  • 我有以下示例数据框架: 我只想替换前两列中的空值——列“a”和“b”: 这是创建示例数据帧的代码: 我知道如何使用替换所有空值: 当我尝试这样做时,我失去了第三列:

  • 第一张照片就是我想要的。第二张图是我已经实现的。如您所见,TextInputLayout底部有一个填充,使灰色背景溢出edittext行。 请不要建议使用负边距或填充,因为它在较新的API中不起作用。 这是我为第一个文本输入布局准备的XML。

  • 所以我用Java处理这些数据: 我需要将其转换为JSON: 但是我不知道怎么做。 目前我认为这是最好的方法: 但我不确定如何使用Hashmap实现这一点。我知道是这样的: 但确切的语法,以及如何将其与其他数据一起添加,我无法计算。有什么想法吗?