缘由
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); } }
效果截图: