zoukankan      html  css  js  c++  java
  • 用ILSpy查看Session.SessionID的生成算法

      

    缘由

      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); } }

     效果截图:

  • 相关阅读:
    ionic3使用@angular/http 访问nodejs(koa2框架)服务不能返回数据
    FacebookFriendAdderPro
    SEO记录-1
    thanos 实现 prometheus 高可用 数据持久化2
    Prometheus + consul + grafana 监控体系搭建1
    解决问题方法
    原则设定
    docker-基本概念、架构和使用
    如何有效学习
    社会~
  • 原文地址:https://www.cnblogs.com/haomo/p/5764480.html
Copyright © 2011-2022 走看看