前言
每当我们登录互联网服务的时候,这些服务都会使用cookie来记录我们的身份。cookie由少量数据组成,网站会要求我们的浏览器存储这些数据,并在每次服务发送请求的时将这些数据传回给服务。对于用来登录的cookie,有两种常见的方法可以将登录信息存储在cookie里面:一种失去签名cookie,另一种是令牌cookie。
Ps:这里实现的是令牌Cookie验证
正文
使用Redis实现Token验证,可达到20000次/s的令牌记录速度,相比关系型数据库1000-2000/s的写入速度,有很大提升。
RedisHelper及本篇文章源码:https://github.com/TangoKe/RedisToken
RedisHelper主要组成部分:
- RedisManager:管理Redis连接对象
- RedisBase:Redis操作的基类,继承自IDisposable接口,主要用于释放内存
- DoRedisString,DoRedisList,DoRedisHash,DoRedisSet:对Redis基础类型操作的封装,继承自RedisBase
验证
/// <summary>
/// 验证是否有此Token
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
static bool Validate(string token)
{
using (var helper = new DoRedisHash())
{
return helper.HashContainsEntry("Tokens", token);
}
}
登陆
/// <summary>
/// 登陆
/// </summary>
/// <param name="userId"></param>
/// <param name="passWord"></param>
static string Login(string userId, string passWord)
{
if (IsAuth(userId, passWord))//验证密码是否正确
{
using (var helper = new DoRedisHash())
{
//移除失效token
var token = helper.GetValueFromHash("user:" + userId, "Token");
helper.RemoveEntryFromHash("Tokens", token);
token = Guid.NewGuid().ToString();
helper.SetEntryInHash("Tokens", token, userId);//更新到tokens散列
helper.SetEntryInHash("user:" + userId, "Token", token);//更新用户token
return token;
}
}
return null;
}
static bool IsAuth(string userId, string passWord)
{
using (var helper = new DoRedisHash())
{
var p = helper.GetValueFromHash("user:" + userId, "PassWord");
return passWord == p;
}
}
注册
/// <summary>
/// 注册
/// </summary>
/// <returns></returns>
static bool Register(User user)
{
using (var helper = new DoRedisHash())
{
helper.Core.SetRangeInHash("user:" + user.ID, ObjectToKeyValuePairs(user));
helper.SetEntryInHash("Tokens", user.Token, user.ID);
}
return true;
}
/// <summary>
/// 反射转KeyValuePairs
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
static IEnumerable<KeyValuePair<string, string>> ObjectToKeyValuePairs(User user)
{
foreach (System.Reflection.PropertyInfo p in user.GetType().GetProperties())
{
yield return new KeyValuePair<string, string>(p.Name, (string)p.GetValue(user));
}
}
主函数
static void Main(string[] args)
{
using (var helper = new DoRedisString())
{
//var a= helper.Core.GetValueFromHash("user:1","Token");
var id = helper.IncrId("user:*", 1);
Register(new User()
{ ID = id.ToString(), PassWord = "123", Token = Guid.NewGuid().ToString(), UserName = "123" });
}
Console.WriteLine(Validate("d1cb400b-5183-4e26-aa0f-3c892b33185d"));
Login("1", "123");
Console.WriteLine(Validate("d1cb400b-5183-4e26-aa0f-3c892b33185d"));
Console.ReadKey();
}
总结:
到这里就完成了Redis实现Cooke验证,大家有什么想法和建议都可以留言,小编看到的话第一时间回复
PS:同样欢迎在Gitbug上提交分支