redis servicestack authentication

¿Cómo puedo llenar un UserAuth de los valores en Redis?



servicestack authentication (1)

Esta es la configuración de autenticación de usuario personalizada en mi archivo global.asax , pero actualmente estoy proporcionando a los usuarios manualmente en el método Configure ; ¿Es posible tomar valores de un servidor Redis?

Por ejemplo, si el usuario existe y la contraseña está bien, ¿puede completar estos detalles automáticamente?

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");


Sí, puede autenticarse contra una fuente de datos Redis. Puede usar el construido en RedisAuthRepository en lugar del InMemoryAuthRepository , o si tiene un conjunto de datos Redis existente que desea usar en lugar del modelo IAuthRepository de IAuthRepository , he incluido una solución para eso, por la cual extiende el BasicAuthProvider . El primer método es el más directo:

Utilice el RedisAuthRepository :

  1. Entonces necesitas establecer una conexión con Redis.
  2. Luego registre sus proveedores de autenticación.
  3. Registre el RedisAuthRepository , con el cual los proveedores verificarán las credenciales, y sea compatible con 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 }

Alternativamente (si tiene un conjunto de datos de autenticación de usuario existente en Redis)

Puede hacerlo creando un proveedor de autenticación personalizado que amplíe el BasicAuthProvider existente .

Para este código, también debe asegurarse de estar familiarizado con el cliente ServiceStack.Redis .

Extienda BasicAuthProvider :

Este MyRedisBasicAuthProvider amplía el BasicAuthProvider existente, y en lugar de realizar la búsqueda de credenciales desde un IUserAuthRepository como figura en su código de ejemplo, realiza una conexión Redis y hace coincidir el nombre de usuario con la entrada en Redis.

El código está completamente comentado, pero si hay algo que deseas más explicado, házmelo saber.

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); } } }

En el código anterior he utilizado una clase MyUser para representar el perfil de usuario que he almacenado en Redis, por supuesto puede personalizar esta clase para que coincida con los requisitos de su perfil de usuario. Esta es la clase de perfil de usuario básico:

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; } }

Configuración de ServiceStack con Redis y su proveedor de autenticación personalizado:

Tendrá que configurar ServiceStack para usar Redis e indicarle que use su proveedor de autenticación personalizado. Para ello, agregue lo siguiente a su método Configure en su 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 = "[email protected]", FirstName = "John", LastName = "Smith", }); MyRedisBasicAuthProvider.AddUserToRedis(new MyUser { Username = "homer.simpson", Password = "donuts", Email = "[email protected]", FirstName = "Homer", LastName = "Simpson", }); // Your other configuration settings ... }

Notas:

En el ejemplo, no he usado una contraseña hash, para mantener el ejemplo sencillo, pero esto es trivial. Agregue otro campo public string Salt { get; set; } public string Salt { get; set; } public string Salt { get; set; } a MyUser entonces, en lugar de almacenar la contraseña simple en MyUser guárdela como un hash de la contraseña y sal, es decir hashedPassword = HashAlgorithm(password + salt) . Ya tienes un código para ello:

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

Por lo tanto, esta solución ahora usará una fuente de datos Redis para autenticar a los usuarios cuando se asegure un servicio utilizando el atributo [Authenticate] . Al igual que con el proveedor básico estándar, las credenciales se autentican en la ruta estándar /auth/basic .

Usar el proveedor de Credenciales en vez de Básico:
Si desea utilizar un proveedor de credenciales para las publicaciones de formularios, en lugar de la autenticación básica, puede simplemente reemplazar la palabra Basic con Credentials en el código anterior.

Espero que esto ayude.