这是我文件中的自定义用户身份验证设置global.asax,但是我目前正在通过该Configure方法手动提供用户;是否可以从Redis服务器获取值?
global.asax
Configure
例如,如果用户存在并且密码可以,可以自动填写这些详细信息吗?
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
InMemoryAuthRepository
IAuthRepository
BasicAuthProvider
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客户端。
这MyRedisBasicAuthProvider将扩展现有的BasicAuthProvider,而不是IUserAuthRepository像示例代码中所提供的那样从中执行凭据查找,而是建立Redis连接并将用户名与Redis中的条目匹配。
MyRedisBasicAuthProvider
IUserAuthRepository
该代码已完全注释,但是如果您希望进一步解释,请告诉我。
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中的用户个人资料,您当然可以自定义此类以匹配您的用户个人资料要求。因此,这是基本的用户配置文件类:
MyUser
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; } }
您将需要配置ServiceStack以使用Redis,并告诉它使用您的自定义身份验证提供程序。为此,您可以在的Configure方法中添加以下内容AppHost:
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)。您已经有了代码:
public string Salt { get; set; }
hashedPassword = HashAlgorithm(password + salt)
string hash, salt; new SaltedHash().GetHashAndSaltString("password", out hash, out salt);
因此,当使用[Authenticate]属性保护服务安全时,此解决方案现在将使用Redis数据源对用户进行身份验证。与标准基本提供程序一样,凭据在标准/auth/basic路由上进行身份验证。
[Authenticate]
/auth/basic
使用证书提供商,而不是基本的: 如果你想使用的表单提交一个证书提供商,而不是基本身份验证,您可以简单替换的单词Basic用Credentials在上面的代码。
Basic
Credentials
我希望这有帮助。