前言
每當(dāng)我們登錄互聯(lián)網(wǎng)服務(wù)的時(shí)候,這些服務(wù)都會(huì)使用cookie來記錄我們的身份洽故。cookie由少量數(shù)據(jù)組成贝攒,網(wǎng)站會(huì)要求我們的瀏覽器存儲(chǔ)這些數(shù)據(jù),并在每次服務(wù)發(fā)送請(qǐng)求的時(shí)將這些數(shù)據(jù)傳回給服務(wù)时甚。對(duì)于用來登錄的cookie隘弊,有兩種常見的方法可以將登錄信息存儲(chǔ)在cookie里面:一種失去簽名cookie哈踱,另一種是令牌cookie。
Ps:這里實(shí)現(xiàn)的是令牌Cookie驗(yàn)證
正文
使用Redis實(shí)現(xiàn)Token驗(yàn)證梨熙,可達(dá)到20000次/s的令牌記錄速度嚣鄙,相比關(guān)系型數(shù)據(jù)庫(kù)1000-2000/s的寫入速度,有很大提升串结。
RedisHelper及本篇文章源碼:https://github.com/TangoKe/RedisToken
RedisHelper主要組成部分:
- RedisManager:管理Redis連接對(duì)象
- RedisBase:Redis操作的基類,繼承自IDisposable接口,主要用于釋放內(nèi)存
- DoRedisString,DoRedisList肌割,DoRedisHash卧蜓,DoRedisSet:對(duì)Redis基礎(chǔ)類型操作的封裝,繼承自RedisBase
驗(yàn)證
/// <summary>
/// 驗(yàn)證是否有此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))//驗(yàn)證密碼是否正確
{
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;
}
}
注冊(cè)
/// <summary>
/// 注冊(cè)
/// </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>
/// 反射轉(zhuǎn)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));
}
}
主函數(shù)
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();
}
總結(jié):
到這里就完成了Redis實(shí)現(xiàn)Cooke驗(yàn)證把敞,大家有什么想法和建議都可以留言弥奸,小編看到的話第一時(shí)間回復(fù)
PS:同樣歡迎在Gitbug上提交分支