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