缘由
asp.net Session在InProc模式下,容易丢失,经常需要重新登录,且不支持分布式共享。
所以在研究Redis实现原生的Session,本来想用GUID作为key存入cookie,又在想能不能实现跟Session一样的id
实现
ILSpy 是一个开源的.NET反编译工具,简洁强大易用是它的特征。在绝大多数情况下,它都能很好的完成你对未知程序集内部代码的探索。
ILSpy 下载地址:点击下载
在VS中可以得知SessionID是System.Web.SessionState命名空间的HttpSessionState类下的属性。
在ILSpy中搜索HttpSessionState,找到Session属性,是IHttpSessionState接口对象创建的。
查看HttpSessionState的构造函数,原来IHttpSessionState是从构造函数传过来的。
本来是想通过搜索构造函数找到是哪传过来这个对象的,只是ILSpy只提供类型,成员,常量的搜索
折腾了好久,终于找到IHttpSessionState的接口实现类HttpSessionStateContainer
DelayedGetSessionId方法
CreateSessionId方法
在追踪CreateSessionID方法,是个接口中定义的方法
搜索CreateSessionID方法,找到具体的现实
最后找到Create方法的所在类
测试
具体的代码:
internal static class SessionId{internal const int NUM_CHARS_IN_ENCODING = 32;internal const int ENCODING_BITS_PER_CHAR = 5;internal const int ID_LENGTH_BITS = 120;internal const int ID_LENGTH_BYTES = 15;internal const int ID_LENGTH_CHARS = 24;private static char[] s_encoding;private static bool[] s_legalchars;internal static bool IsLegit(string s){if (s == null || s.Length != 24){return false;}bool result;try{int num = 24;while (--num >= 0){char c = s[num];if (!SessionId.s_legalchars[(int)c]){result = false;return result;}}result = true;}catch (IndexOutOfRangeException){result = false;}return result;}internal static string Create(ref RandomNumberGenerator randgen){if (randgen == null){randgen = new RNGCryptoServiceProvider();}byte[] array = new byte[15];randgen.GetBytes(array);return SessionId.Encode(array);}static SessionId(){SessionId.s_encoding = new char[]{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5'};SessionId.s_legalchars = new bool[128];for (int i = SessionId.s_encoding.Length - 1; i >= 0; i--){char c = SessionId.s_encoding[i];SessionId.s_legalchars[(int)c] = true;}}private static string Encode(byte[] buffer){char[] array = new char[24];int num = 0;for (int i = 0; i < 15; i += 5){int num2 = (int)buffer[i] | (int)buffer[i + 1] << 8 | (int)buffer[i + 2] << 16 | (int)buffer[i + 3] << 24;int num3 = num2 & 31;array[num++] = SessionId.s_encoding[num3];num3 = (num2 >> 5 & 31);array[num++] = SessionId.s_encoding[num3];num3 = (num2 >> 10 & 31);array[num++] = SessionId.s_encoding[num3];num3 = (num2 >> 15 & 31);array[num++] = SessionId.s_encoding[num3];num3 = (num2 >> 20 & 31);array[num++] = SessionId.s_encoding[num3];num3 = (num2 >> 25 & 31);array[num++] = SessionId.s_encoding[num3];num2 = ((num2 >> 30 & 3) | (int)buffer[i + 4] << 2);num3 = (num2 & 31);array[num++] = SessionId.s_encoding[num3];num3 = (num2 >> 5 & 31);array[num++] = SessionId.s_encoding[num3];}return new string(array);}}
调用:
public partial class Contact : Page{protected void Page_Load(object sender, EventArgs e){string SessionId = CreateSessionID(Context);Response.Write(SessionId+"<br/>");
Response.Write(Session.SessionID);Response.End();}private RandomNumberGenerator _randgen;public virtual string CreateSessionID(HttpContext context){return SessionId.Create(ref this._randgen);}}
效果截图: