zoukankan      html  css  js  c++  java
  • Asp.Net使用加密cookie代替session验证用户登录状态 源码分享

    首先 session 和 cache 拥有各自的优势而存在.  他们的优劣就不在这里讨论了.

    本实例仅存储用户id于用户名,对于多级权限的架构,可以自行修改增加权限字段

     

    本实例采用vs2010编写,vb和c#的代码都是经过测试的;一些童鞋说代码有问题的 注意下   

    什么? 你还在用vs2008 vs2005? 请自行重载 带有 optional 标致的函数

     

    童鞋们提到的 密码修改后 要失效的问题 当时没有想到 个人认为 大致方向可以》

    》1. 每个用户生成1个xml 里面保存随机的几个字符 或者修改密码的时间戳也行 

    》2. 这个文件在用户刚注册 或修改密码时候生成写入; 写入的同时需要更新当前用户的cookie 否则当前用户也会失效

    》3. 在本实例的基础上 加1个字段 内容为 1中的若干字符 本实例在cookie写入15分钟后才会重新写入新的cookie;可以在重新写入cookie前 比对这几个若干字符是否匹配 用 StreamReader 即可

    》4. 以上不知 大家看懂了没有呢


    以下类实现了 使用加密cookie代替session验证用户登录状态 支持 1小时/1周 有效期2种模式 (期间有新的请求则更新失效时间)

    项目源码下载地址 http://www.370b.com/bbsx/cookie-login/cookie.rar

    csdn下载地址 http://download.csdn.net/detail/rayyu1989/4265766


    在自定义字符 CustomCode 不被知道的情况下 该加密过程是相对安全的.
    你还可以更改其中 的 2处MD5哈希值 生成的方式、DEChar(ENChar)混淆字符 让代码更与众不同


    欢迎大家拍砖

    加密后的cookie值枚举:

    n=rayyu_EJPSiju2JJNeh5&u=VWpc9dv5v8e4APbbhJmSP+yifwZNEcyRy6V/RwzqV2pmo+x6hNLHI/pLlzl8+KgdWpMHtTTOYpGMe3tCrAIKkmeCrKG7BpSVUYF0piopz757NPb43Z4ehA==&i=56-76-68-35-4A-37-57-35

    n=rayyu_P5O7ouiq5JVaMf&u=gWz/itCIlbupWCv7iziBuYCwT1SF4+IbyFbwa5Hmm+up4iuCxKMCl24+bLRb0Y/6RMyfzcpuJwu8gT/Yqg1UV1bd9UqgQYzrLdibP9zaXkYjYyT56gkCBg==&i=5B-65-54-34-6G-35-4C-45

    n=rayyu_bNJuGxps3Kqtxl&u=kUorl6z713eYdjkhRidocZKHMh2Mw6j5LowmevsWiKZsn81dzlsPcH4fp1VJsi2dtObeYvMJTCybLrv45TsdLIT7nhZcQJdxKGn1oaK/7a3Ldfte6zoQqg==&i=4H-5B-53-6A-6H-75-32-4H

    n=rayyu_TF0hpOgdGhliK8&u=1O9Zi4V9Qj2HH63dEfXaLaoj3X6ea9azIBjuLjFBJqhiTQefz2x161IIDpWaviJr1TTECBdb4NCIiFOEsEY9C4gl+/Equjc7tGpO12ixEkZz70bMg48M9w==&i=4H-4E-65-68-35-7A-5B-35

     

    n=rayyu_9INryZvNo1pCKm&u=wQgRgtf+uy9jKQXJhr7DerZtFeYmm2Lx10Asgf52HTzkar9iHXkVaJJqHtwWA9K635QU4bGLYZPWl3nj0rxOhOe93ew+bIAR8FWr2zPwvfZ++TwB3670LQ==&i=4F-37-6F-75-6A-71-35-4H

     

     

    客户端可以获取cookie的 n值 来简单判断是否登录 n为用户名,配合静态页和缓存 动态显示登录状态

    VB.NET调用: (Rayyu 是 namespace)

    [vb] view plaincopy
     
    1. Dim user As New Rayyu.User() '初始化用户信息(检测当前请求用户是否登录)  
    2. If user.Online Then  
    3. Response.Write("<br />name:" & user.Name & ",online:" & user.Online & ",id:" & user.ID)  
    4. End If  
    5.   
    6.   
    7. Dim user2 As New Rayyu.User(1, "用户名"False'初始化(写入新用户)  

     

    C#调用:(Rayyu 是 namespace)

     

    [csharp] view plaincopy
     
    1. Rayyu.User user = new Rayyu.User();// 初始化用户信息(检测当前请求用户是否登录)  
    2.             Rayyu.User user2 = new Rayyu.User(1, "用户名"false);// 初始化(写入新用户) false 表示1小时  true表示1周  
    3.   
    4.   
    5.             if (user.Online)  
    6.             {  
    7.                 Response.Write("<br />name:" + user.Name + ",online:" + user.Online + ",id:" + user.Id);  
    8.             }  



     

    VB.NET 源代码:

     

    [vb] view plaincopy
     
    1. Imports System.Web  
    2. Imports System.Text.RegularExpressions  
    3. Imports System.Text  
    4. Imports System.Security.Cryptography  
    5.     ''' <summary>  
    6.     ''' 用户登录机制 支持1小时/1周状态  
    7.     ''' </summary>  
    8.     ''' <remarks></remarks>  
    9.     Public Class User  
    10. #Region "自定义参数"  
    11.         ''' <summary>  
    12.         ''' 自定义字符 用于第一层加解密密匙  
    13.         ''' </summary>  
    14.         ''' <remarks></remarks>  
    15.     Private Const CustomCode As String = "QQ:867863456"  
    16.     ''' <summary>  
    17.     ''' cookie名  
    18.         ''' </summary>  
    19.         ''' <remarks></remarks>  
    20.         Private Const CookieName As String = "userinfo"  
    21.         ''' <summary>  
    22.         ''' Cookie作用域  
    23.         ''' </summary>  
    24.         ''' <remarks></remarks>  
    25.     Private Const CookieDomain As String = ".370b.com"  
    26.         ''' <summary>  
    27.         ''' 编码  
    28.         ''' </summary>  
    29.         ''' <remarks></remarks>  
    30.         Private Shared Encoder As Encoding = Encoding.UTF8  
    31.         ''' <summary>  
    32.         ''' 用户名的正则检测 我的是:首位由字母或者汉字构成,由字母、数字、下划线、和汉字的 2-20位的字符 组合而成 的  
    33.         ''' </summary>  
    34.         ''' <remarks></remarks>  
    35.         Private Const RegexUserName As String = "[a-zA-Zu4e00-u9fa5][wu4e00-u9fa5]{1,19}"  
    36.         ''' <summary>  
    37.         ''' 区域化信息设置  
    38.         ''' </summary>  
    39.         ''' <remarks></remarks>  
    40.     Private Shared ReadOnly Format As Globalization.CultureInfo = New System.Globalization.CultureInfo("zh-CN"True)  
    41. #End Region  
    42. #Region "回调参数"  
    43.         ''' <summary>  
    44.         ''' 是否在线  
    45.         ''' </summary>  
    46.         ''' <remarks></remarks>  
    47.         Public ReadOnly Property Online As Boolean  
    48.             Get  
    49.                 Return _Online  
    50.             End Get  
    51.         End Property  
    52.         Private _Online As Boolean = False  
    53.         ''' <summary>  
    54.         ''' 用户ID (Online=true情况下使用)  
    55.         ''' </summary>  
    56.         ''' <remarks></remarks>  
    57.         Public ReadOnly Property Id As Integer  
    58.             Get  
    59.                 Return _Id  
    60.             End Get  
    61.         End Property  
    62.         Private _Id As Integer  
    63.         ''' <summary>  
    64.         ''' 用户名 (Online=true情况下使用)  
    65.         ''' </summary>  
    66.         ''' <remarks></remarks>  
    67.         Public ReadOnly Property Name As String  
    68.             Get  
    69.                 Return _Name  
    70.             End Get  
    71.         End Property  
    72.         Private _Name As String  
    73.         ''' <summary>  
    74.         ''' 有效期是否为7天  
    75.         ''' </summary>  
    76.         ''' <remarks></remarks>  
    77.         Public ReadOnly Property IsWeek As Boolean  
    78.             Get  
    79.                 Return _IsWeek  
    80.             End Get  
    81.         End Property  
    82.         Private ReadOnly _IsWeek As Boolean  
    83. #End Region  
    84.         ''' <summary>  
    85.         ''' 初始化用户信息(检测当前请求用户是否登录)  
    86.         ''' </summary>  
    87.         ''' <remarks></remarks>  
    88.         Public Sub New()  
    89.             '读取cookie  
    90.             Dim cookie As HttpCookie = HttpContext.Current.Request.Cookies(CookieName)  
    91.             If cookie IsNot Nothing Then  
    92.                 '存在cookie  
    93.                 Dim value As String = cookie.Values("u"), key As String = cookie.Values("i"), tname As String = cookie.Values("n")  
    94.                 cookie = Nothing  
    95.             If tname IsNot Nothing AndAlso value IsNot Nothing AndAlso key IsNot Nothing AndAlso Regex.IsMatch(key, "^[1-8A-H]{2}(-[1-8A-H]{2}){7}$", Text.RegularExpressions.RegexOptions.None) Then  
    96.                 '存在对应键值  
    97.                 Dim keybyte As Byte() = toByte(DEChar(key)) '解密密匙的后8位字节 由参数i构成  
    98.                 If keybyte IsNot Nothing Then  
    99.                     Dim autocode() As Byte '解密密匙的前16位字节 由用户UserAgent,用户名,自定义字符 组合而成 的 md5   
    100.                     Using m As New System.Security.Cryptography.MD5CryptoServiceProvider()  
    101.                         autocode = m.ComputeHash(Encoder.GetBytes(String.Format(Format, "{0}_{2}_{1}", HttpContext.Current.Request.UserAgent, tname, CustomCode)))  
    102.                         m.Clear()  
    103.                     End Using  
    104.                     Dim keyboard() As Byte = New Byte(keybyte.Length + autocode.Length - 1) {}  
    105.                     autocode.CopyTo(keyboard, 0)  
    106.                     keybyte.CopyTo(keyboard, autocode.Length)  
    107.                     value = DesDecrypt(value, keyboard)  
    108.                     If value.Length > 0 Then  
    109.                         '解密成功 第一层合法  
    110.                         Dim values As Match = Regex.Match(value, "^(?<md5>[w]{32})(?<isweek>[01])(?<id>[d]{1,10})(?<name>" & RegexUserName & ")|(?<exp>[d]{1,19})$")  
    111.                         If values.Success Then  
    112.                             Dim LostDateTime As Long  
    113.                             If Integer.TryParse(values.Groups("id").Value, Me._Id) AndAlso Me._Id > 0 AndAlso Long.TryParse(values.Groups("exp").Value, LostDateTime) AndAlso LostDateTime > 0 Then  
    114.                                 '解密后的字符串格式正确  
    115.                                 Me._IsWeek = (values.Groups("isweek").Value = "1")  
    116.                                 '此md5用于验证解密后的字符串 由用户id,用户名,cookie写入时间,自定义字符串 以及有效期是否是1周 组合  
    117.                                 Dim md5 As String = MD5Public(String.Format(Format, "{0}{5}{1}{2}:rayyu.{3};{4}", values.Groups("id").Value, values.Groups("exp").Value, values.Groups("name").Value, CookieDomain, IsWeek, CustomCode))  
    118.                                 If md5 = values.Groups("md5").Value Then  
    119.                                     'md5正常  
    120.                                     Dim lostdate As Double = (Now - New DateTime(LostDateTime)).TotalMinutes  
    121.                                     Dim l_a As Integer  
    122.                                     If IsWeek Then  
    123.                                         l_a = 10080  
    124.                                     Else  
    125.                                         l_a = 60  
    126.                                     End If  
    127.                                     If lostdate > 0 AndAlso lostdate < l_a Then  
    128.                                         'cookie在有效期内  
    129.                                         Me._Name = values.Groups("name").Value  
    130.                                         Me._Online = True  
    131.                                         If lostdate > 15 Then  
    132.                                             'cookie以写入超过15分钟,从新写入1次cookie  
    133.                                             SetUser(Me._Id, Me._Name, Me._IsWeek, autocode)  
    134.                                         End If  
    135.                                     End If  
    136.                                 Else  
    137.                                     Me._Id = 0  
    138.                                     Me._Name = Nothing  
    139.                                 End If  
    140.                             End If  
    141.                         End If  
    142.                     End If  
    143.                 End If  
    144.             End If  
    145.             End If  
    146.         End Sub  
    147.         ''' <summary>  
    148.         ''' 初始化(写入新用户)  
    149.         ''' </summary>  
    150.         ''' <param name="userid">用户id</param>  
    151.         ''' <param name="username">用户名</param>  
    152.         ''' <param name="isweek">是否保持一周登录状态</param>  
    153.         ''' <remarks></remarks>  
    154.         Public Sub New(ByVal userId As IntegerByVal userName As StringByVal isWeek As Boolean)  
    155.             SetUser(userId, userName, isWeek)  
    156.             Me._ID = userId  
    157.             Me._Name = userName  
    158.             Me._IsWeek = isWeek  
    159.             Me._Online = True  
    160.         End Sub  
    161.         ''' <summary>  
    162.         ''' 写入用户  
    163.         ''' </summary>  
    164.         ''' <param name="userid">用户id</param>  
    165.         ''' <param name="username">用户名</param>  
    166.         ''' <param name="isweek">是否保持一周登录状态</param>  
    167.         ''' <param name="autocode"></param>  
    168.         ''' <remarks></remarks>  
    169.         Private Shared Sub SetUser(ByVal userid As IntegerByVal username As StringByVal isweek As BooleanOptional ByVal autocode As Byte() = Nothing)  
    170.             If autocode Is Nothing Then  
    171.                 '解密密匙的前16位字节 由用户UserAgent,用户名,自定义字符 组合而成 的 md5   
    172.                 Using m As New System.Security.Cryptography.MD5CryptoServiceProvider()  
    173.                     autocode = m.ComputeHash(Encoder.GetBytes(String.Format(Format, "{0}_{2}_{1}", HttpContext.Current.Request.UserAgent, username, CustomCode)))  
    174.             End Using  
    175.             End If  
    176.             Dim expires As DateTime  
    177.             Dim isweekint As Char  
    178.             If isweek Then  
    179.                 expires = Now.AddDays(7)  
    180.                 isweekint = "1"  
    181.             Else  
    182.                 expires = Now.AddHours(1)  
    183.                 isweekint = "0"  
    184.             End If  
    185.             '解密密匙的后8位字节 随机生成参数i  
    186.             Dim rbyte() As Byte = Encoder.GetBytes(RandomCode(8))  
    187.             Dim keyboard() As Byte = New Byte(23) {}  
    188.             autocode.CopyTo(keyboard, 0)  
    189.             '组合密匙 长度为24位  
    190.             rbyte.CopyTo(keyboard, autocode.Length)  
    191.             autocode = Nothing  
    192.             Dim exp As String = Now.Ticks.ToString("D", Format)  
    193.             '加密字符串  
    194.             Dim value As String = DesEncrypt(String.Format(Format, "{4}{0}{1}{2}|{3}", isweekint, userid, username, exp, MD5Public(String.Format(Format, "{0}{5}{1}{2}:rayyu.{3};{4}", userid, exp, username, CookieDomain, isweek, CustomCode))), keyboard)  
    195.             keyboard = Nothing  
    196.             Dim key As String = ENChar(System.BitConverter.ToString(rbyte)) '混淆参数i  
    197.             rbyte = Nothing  
    198.             '写入cookie  
    199.             Dim cookie As New HttpCookie(CookieName)  
    200.             cookie.Values.Add("n", username)  
    201.             cookie.Values.Add("u", value)  
    202.             cookie.Values.Add("i", key)  
    203.             cookie.Path = "/"  
    204.             cookie.Expires = expires  
    205.             cookie.Domain = CookieDomain  
    206.             HttpContext.Current.Response.Cookies.Set(cookie)  
    207.         End Sub  
    208.         ''' <summary>  
    209.         ''' TripleDESC解密  
    210.         ''' </summary>  
    211.         ''' <param name="strText">待解密字符串</param>  
    212.         ''' <param name="key">密匙</param>  
    213.         ''' <returns></returns>  
    214.         ''' <remarks></remarks>  
    215.         Protected Friend Shared Function DesDecrypt(ByVal strText As StringByVal key As Byte()) As String  
    216.             Try  
    217.                 Using provider As New System.Security.Cryptography.TripleDESCryptoServiceProvider()  
    218.                     provider.Key = key  
    219.                     provider.Mode = System.Security.Cryptography.CipherMode.ECB  
    220.                     Dim inputBuffer As Byte() = Convert.FromBase64String(strText)  
    221.                     Return Encoder.GetString(provider.CreateDecryptor().TransformFinalBlock(inputBuffer, 0, inputBuffer.Length)).Trim  
    222.                 End Using  
    223.             Catch ex As CryptographicException  
    224.                 Return String.Empty  
    225.             Catch ex As ArgumentNullException  
    226.                 Return String.Empty  
    227.             Catch ex As DecoderFallbackException  
    228.                 Return String.Empty  
    229.             Catch ex As ArgumentException  
    230.                 Return String.Empty  
    231.             Catch ex As FormatException  
    232.                 Return String.Empty  
    233.             End Try  
    234.         End Function  
    235.         ''' <summary>  
    236.         ''' TripleDESC加密  
    237.         ''' </summary>  
    238.         ''' <param name="strText">待加密字符串</param>  
    239.         ''' <param name="key">密匙</param>  
    240.         ''' <returns></returns>  
    241.         ''' <remarks></remarks>  
    242.         Protected Friend Shared Function DesEncrypt(ByVal strText As StringByVal key As Byte()) As String  
    243.             Try  
    244.                 Using provider As New System.Security.Cryptography.TripleDESCryptoServiceProvider()  
    245.                     provider.Key = key  
    246.                     provider.Mode = System.Security.Cryptography.CipherMode.ECB  
    247.                     Dim bytes As Byte() = Encoder.GetBytes(strText)  
    248.                     Return Convert.ToBase64String(provider.CreateEncryptor().TransformFinalBlock(bytes, 0, bytes.Length))  
    249.                 End Using  
    250.            Catch ex As CryptographicException  
    251.             Return String.Empty  
    252.         Catch ex As ArgumentNullException  
    253.             Return String.Empty  
    254.         Catch ex As DecoderFallbackException  
    255.             Return String.Empty  
    256.         Catch ex As ArgumentException  
    257.             Return String.Empty  
    258.         Catch ex As FormatException  
    259.             Return String.Empty  
    260.         End Try  
    261.     End Function  
    262.         ''' <summary>  
    263.         ''' md5加密  
    264.         ''' </summary>  
    265.         ''' <param name="str">待加密字符串</param>  
    266.         ''' <returns>返回加密后字符串</returns>  
    267.         ''' <remarks></remarks>  
    268.         Private Shared Function MD5Public(ByVal str As StringAs String  
    269.             Dim returnx As String = "0000000000000000"  
    270.             If str IsNot Nothing AndAlso str IsNot String.Empty Then  
    271.                 Try  
    272.                     Using m As New System.Security.Cryptography.MD5CryptoServiceProvider()  
    273.                         Dim MDByte As Byte() = m.ComputeHash(Encoder.GetBytes(str))  
    274.                         returnx = Strings.Replace(System.BitConverter.ToString(MDByte), "-""")  
    275.                         m.Clear()  
    276.                     End Using  
    277.             Catch ex As ObjectDisposedException  
    278.                 returnx = "0000000000000000"  
    279.                 Catch ex As ArgumentOutOfRangeException  
    280.                     returnx = "0000000000000003"  
    281.                 Catch ex As ArgumentNullException  
    282.                     returnx = "0000000000000001"  
    283.                 Catch ex As EncoderFallbackException  
    284.                     returnx = "0000000000000001"  
    285.                 Catch ex As InvalidOperationException  
    286.                     returnx = "0000000000000002"  
    287.                 End Try  
    288.             End If  
    289.             Return returnx  
    290.         End Function  
    291.         ''' <summary>  
    292.         ''' 随机数  
    293.         ''' </summary>  
    294.         ''' <remarks></remarks>  
    295.         Private Shared Randoms As New Random  
    296.         ''' <summary>  
    297.         ''' 随机字符集合  
    298.         ''' </summary>  
    299.         ''' <remarks></remarks>  
    300.         Private Shared xarrChar() As Char = New Char() {"0""1""2""3""4""5""6""7""8""9""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""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"}  
    301.         ''' <summary>  
    302.         ''' 生成随机数  
    303.         ''' </summary>  
    304.         ''' <returns></returns>  
    305.         ''' <remarks></remarks>  
    306.         Public Shared Function RandomCode(ByVal length As IntegerAs String  
    307.             Dim str As String = ""  
    308.             Dim mlength As Integer = xarrChar.Length  
    309.             For i As Integer = 0 To length - 1  
    310.                 str &= xarrChar(Randoms.Next(0, mlength))  
    311.             Next  
    312.             Return str  
    313.         End Function  
    314.         ''' <summary>  
    315.         ''' 16进制字符串转Byte数组  
    316.         ''' </summary>  
    317.         ''' <param name="value"></param>  
    318.         ''' <returns></returns>  
    319.         ''' <remarks></remarks>  
    320.         Private Shared Function toByte(ByVal value As StringAs Byte()  
    321.             Try  
    322.                 Dim chars As String() = value.Split("-")  
    323.                 Dim length As Integer = chars.Length - 1  
    324.                 Dim byte_() As Byte = New Byte(length) {}  
    325.                 For i As Integer = 0 To length  
    326.                     byte_(i) = Convert.ToByte(chars(i), 16)  
    327.                 Next  
    328.                 Return byte_  
    329.             Catch ex As ArgumentException  
    330.                 Return Nothing  
    331.             Catch ex As FormatException  
    332.                 Return Nothing  
    333.             Catch ex As OverflowException  
    334.                 Return Nothing  
    335.             End Try  
    336.         End Function  
    337.         ''' <summary>  
    338.         ''' TripleDESC-部分密匙 字符混淆 如果要修改下面的字符 请注意修改上面的正则  
    339.         ''' </summary>  
    340.         ''' <param name="value"></param>  
    341.         ''' <returns></returns>  
    342.         ''' <remarks></remarks>  
    343.         Private Shared Function ENChar(ByVal value As StringAs String  
    344.             value = Strings.Replace(value, "A""H")  
    345.             value = Strings.Replace(value, "B""G")  
    346.             value = Strings.Replace(value, "0""B")  
    347.             value = Strings.Replace(value, "9""A")  
    348.             Return value  
    349.         End Function  
    350.         ''' <summary>  
    351.         ''' TripleDESC-部分密匙 字符反混淆 如果要修改下面的字符 请注意修改上面的正则  
    352.         ''' </summary>  
    353.         ''' <param name="value"></param>  
    354.         ''' <returns></returns>  
    355.         ''' <remarks></remarks>  
    356.         Private Shared Function DEChar(ByVal value As StringAs String  
    357.             value = Strings.Replace(value, "A""9")  
    358.             value = Strings.Replace(value, "B""0")  
    359.             value = Strings.Replace(value, "G""B")  
    360.             value = Strings.Replace(value, "H""A")  
    361.             Return value  
    362.         End Function  
    363.     End Class  


    C#源代码:

     

     

    [csharp] view plaincopy
     
      1. using System;  
      2. using System.Web;  
      3. using System.Text.RegularExpressions;  
      4. using System.Text;  
      5. using System.Security.Cryptography;  
      6. namespace Rayyu  
      7.     {  
      8.     /// <summary>  
      9.     /// 用户登录机制 支持1小时/1周状态  
      10.     /// </summary>  
      11.     /// <remarks></remarks>  
      12.     public class User  
      13.     {  
      14.         #region "自定义参数"  
      15.         /// <summary>  
      16.         /// 自定义字符 用于第一层加解密密匙  
      17.         /// </summary>  
      18.         /// <remarks></remarks>  
      19.         private const string CustomCode = "QQ:867863456";  
      20.         /// <summary>  
      21.         /// cookie名  
      22.         /// </summary>  
      23.         /// <remarks></remarks>  
      24.         private const string CookieName = "userinfo";  
      25.         /// <summary>  
      26.         /// Cookie作用域  
      27.         /// </summary>  
      28.         /// <remarks></remarks>  
      29.         private const string CookieDomain = ".370b.com";  
      30.         /// <summary>  
      31.         /// 编码  
      32.         /// </summary>  
      33.         /// <remarks></remarks>  
      34.         private static Encoding Encoder = Encoding.UTF8;  
      35.         /// <summary>  
      36.         /// 用户名的正则检测 我的是:首位由字母或者汉字构成,由字母、数字、下划线、和汉字的 2-20位的字符 组合而成 的  
      37.         /// </summary>  
      38.         /// <remarks></remarks>  
      39.         private const string RegexUserName = "[a-zA-Z\u4e00-\u9fa5][\w\u4e00-\u9fa5]{1,19}";  
      40.         /// <summary>  
      41.         /// 区域化信息设置  
      42.         /// </summary>  
      43.         /// <remarks></remarks>  
      44.         private static System.Globalization.CultureInfo Format = new System.Globalization.CultureInfo("zh-CN"true);  
      45.     #endregion          
      46.     #region "回调参数"  
      47.         /// <summary>  
      48.         /// 是否在线  
      49.         /// </summary>  
      50.         /// <remarks></remarks>  
      51.         public  bool Online  
      52.         {  
      53.             get { return _Online; }  
      54.         }  
      55.         private  bool _Online = false;  
      56.         /// <summary>  
      57.         /// 用户ID (Online=true情况下使用)  
      58.         /// </summary>  
      59.         /// <remarks></remarks>  
      60.         public  int Id  
      61.         {  
      62.             get { return _Id; }  
      63.         }  
      64.         private int _Id;  
      65.         /// <summary>  
      66.         /// 用户名 (Online=true情况下使用)  
      67.         /// </summary>  
      68.         /// <remarks></remarks>  
      69.         public  string Name  
      70.         {  
      71.             get { return _Name; }  
      72.         }  
      73.         private string _Name;  
      74.         /// <summary>  
      75.         /// 有效期是否为7天  
      76.         /// </summary>  
      77.         /// <remarks></remarks>  
      78.         public bool IsWeek  
      79.         {  
      80.             get { return _isWeek; }  
      81.         }  
      82.         private bool _isWeek;  
      83.         #endregion  
      84.           
      85.         /// <summary>  
      86.         /// 初始化用户信息(检测当前请求用户是否登录)  
      87.         /// </summary>  
      88.         /// <remarks></remarks>  
      89.         public User()  
      90.         {  
      91.             //读取cookie  
      92.             HttpCookie cookie = HttpContext.Current.Request.Cookies[CookieName];  
      93.             if (cookie != null)  
      94.             {  
      95.                 //存在cookie  
      96.                 string value = cookie.Values["u"];  
      97.                 string key = cookie.Values["i"];  
      98.                 string tname = cookie.Values["n"];  
      99.                 cookie = null;                  
      100.                 if (tname != null && value != null && key != null && Regex.IsMatch(key, "^[1-8A-H]{2}(-[1-8A-H]{2}){7}$", System.Text.RegularExpressions.RegexOptions.None))  
      101.                 {  
      102.                     //存在对应键值  
      103.                     byte[] keybyte = toByte(DEChar(key));  
      104.                     //解密密匙的后8位字节 由参数i构成                      
      105.                     if (keybyte != null)  
      106.                     {                          
      107.                         byte[] autocode;  
      108.                         //解密密匙的前16位字节 由用户UserAgent,用户名,自定义字符 组合而成 的 md5   
      109.                         using (System.Security.Cryptography.MD5CryptoServiceProvider m = new System.Security.Cryptography.MD5CryptoServiceProvider())  
      110.                         {  
      111.                             autocode = m.ComputeHash(Encoder.GetBytes(string.Format(Format, "{0}_{2}_{1}", HttpContext.Current.Request.UserAgent, tname, CustomCode)));  
      112.                         }  
      113.                         byte[] keyboard = new byte[keybyte.Length + autocode.Length];  
      114.                         autocode.CopyTo(keyboard, 0);  
      115.                         keybyte.CopyTo(keyboard, autocode.Length);  
      116.                         value = DesDecrypt(value, keyboard);  
      117.                         if (value.Length > 0)  
      118.                         {  
      119.                             //解密成功 第一层合法  
      120.                             Match values = Regex.Match(value, "^(?<md5>[\w]{32})(?<isweek>[01])(?<id>[\d]{1,10})(?<name>" + RegexUserName + ")\|(?<exp>[\d]{1,19})$");  
      121.                             if (values.Success)  
      122.                             {  
      123.                                 long LostDateTime = 0;  
      124.                                 if (int.TryParse(values.Groups["id"].Value, out this._Id) && this._Id > 0 && long.TryParse(values.Groups["exp"].Value, out LostDateTime) && LostDateTime > 0)  
      125.                                 {  
      126.                                     //解密后的字符串格式正确  
      127.                                     this._isWeek = (values.Groups["isweek"].Value == "1");  
      128.                                     //此md5用于验证解密后的字符串 由用户id,用户名,cookie写入时间,自定义字符串 以及有效期是否是1周 组合  
      129.                                     string md5 = MD5Public(string.Format(Format, "{0}{5}{1}{2}:rayyu.{3};{4}", values.Groups["id"].Value, values.Groups["exp"].Value, values.Groups["name"].Value, CookieDomain, _isWeek, CustomCode));  
      130.                                     if (md5 == values.Groups["md5"].Value)  
      131.                                     {  
      132.                                         //md5正常  
      133.                                         double lostdate = (DateTime.Now - new DateTime(LostDateTime)).TotalMinutes;  
      134.                                         int l_a = 0;  
      135.                                         if (_isWeek)  
      136.                                         {  
      137.                                             l_a = 10080;  
      138.                                         }  
      139.                                         else  
      140.                                         {  
      141.                                             l_a = 60;  
      142.                                         }  
      143.                                         if (lostdate > 0 && lostdate < l_a)  
      144.                                         {  
      145.                                             //cookie在有效期内  
      146.                                             this._Name = values.Groups["name"].Value;  
      147.                                             this._Online = true;  
      148.                                             if (lostdate > 15)  
      149.                                             {  
      150.                                                 //cookie以写入超过15分钟,从新写入1次cookie  
      151.                                                 SetUser(this._Id, this._Name, this._isWeek, autocode);  
      152.                                             }  
      153.                                         }  
      154.                                     }  
      155.                                     else  
      156.                                     {  
      157.                                         this._Id = 0;  
      158.                                         this._Name = null;  
      159.                                     }  
      160.                                 }  
      161.                             }  
      162.                         }  
      163.                     }  
      164.                 }  
      165.             }  
      166.         }  
      167.         /// <summary>  
      168.         /// 初始化(写入新用户)  
      169.         /// </summary>  
      170.         /// <param name="userid">用户id</param>  
      171.         /// <param name="username">用户名</param>  
      172.         /// <param name="isweek">是否保持一周登录状态</param>  
      173.         /// <remarks></remarks>  
      174.         public User(int userId, string userName, bool isWeek)  
      175.         {  
      176.             SetUser(userId, userName, isWeek);  
      177.             this._Id = userId;  
      178.             this._Name = userName;  
      179.             this._isWeek = isWeek;  
      180.             this._Online = true;  
      181.         }  
      182.         /// <summary>  
      183.         /// 写入用户  
      184.         /// </summary>  
      185.         /// <param name="userid">用户id</param>  
      186.         /// <param name="username">用户名</param>  
      187.         /// <param name="isweek">是否保持一周登录状态</param>  
      188.         /// <param name="autocode"></param>  
      189.         /// <remarks></remarks>  
      190.         private static void SetUser(int userid, string username, bool isweek, byte[] autocode = null)  
      191.         {  
      192.             if (autocode == null)  
      193.             {  
      194.                 //解密密匙的前16位字节 由用户UserAgent,用户名,自定义字符 组合而成 的 md5   
      195.                 using (System.Security.Cryptography.MD5CryptoServiceProvider m = new System.Security.Cryptography.MD5CryptoServiceProvider())  
      196.                 {  
      197.                     autocode = m.ComputeHash(Encoder.GetBytes(string.Format(Format,"{0}_{2}_{1}", HttpContext.Current.Request.UserAgent, username, CustomCode)));  
      198.                     m.Clear();  
      199.                 }  
      200.             }  
      201.             DateTime expires = default(DateTime);  
      202.             char isweekint;  
      203.             if (isweek)  
      204.             {  
      205.                 expires = DateTime.Now.AddDays(7);  
      206.                 isweekint = '1';  
      207.             }  
      208.             else  
      209.             {  
      210.                 expires = DateTime.Now.AddHours(1);  
      211.                 isweekint = '0';  
      212.             }  
      213.             //解密密匙的后8位字节 随机生成参数i  
      214.             byte[] rbyte = Encoder.GetBytes(RandomCode(8));  
      215.             byte[] keyboard = new byte[24];  
      216.             autocode.CopyTo(keyboard, 0);  
      217.             //组合密匙 长度为24位  
      218.             rbyte.CopyTo(keyboard, autocode.Length);  
      219.             autocode = null;  
      220.             string exp = DateTime.Now.Ticks.ToString("D", Format);  
      221.             //加密字符串  
      222.             string value = DesEncrypt(string.Format(Format, "{4}{0}{1}{2}|{3}", isweekint, userid, username, exp, MD5Public(string.Format(Format, "{0}{5}{1}{2}:rayyu.{3};{4}", userid, exp, username, CookieDomain, isweek, CustomCode))), keyboard);  
      223.             keyboard = null;  
      224.             string key = ENChar(System.BitConverter.ToString(rbyte));  
      225.             //混淆参数i  
      226.             rbyte = null;  
      227.             //写入cookie  
      228.             HttpCookie cookie = new HttpCookie(CookieName);  
      229.             cookie.Values.Add("n", username);  
      230.             cookie.Values.Add("u", value);  
      231.             cookie.Values.Add("i", key);  
      232.             cookie.Path = "/";  
      233.             cookie.Expires = expires;  
      234.             cookie.Domain = CookieDomain;  
      235.             HttpContext.Current.Response.Cookies.Set(cookie);  
      236.         }  
      237.         /// <summary>  
      238.         /// TripleDESC解密  
      239.         /// </summary>  
      240.         /// <param name="strText">待解密字符串</param>  
      241.         /// <param name="key">密匙</param>  
      242.         /// <returns></returns>  
      243.         /// <remarks></remarks>  
      244.         protected static internal string DesDecrypt(string strText, byte[] key)  
      245.         {  
      246.             try  
      247.             {  
      248.                 using (System.Security.Cryptography.TripleDESCryptoServiceProvider provider = new System.Security.Cryptography.TripleDESCryptoServiceProvider())  
      249.                 {  
      250.                     provider.Key = key;  
      251.                     provider.Mode = System.Security.Cryptography.CipherMode.ECB;  
      252.                     byte[] inputBuffer = Convert.FromBase64String(strText);  
      253.                     return Encoder.GetString(provider.CreateDecryptor().TransformFinalBlock(inputBuffer, 0, inputBuffer.Length)).Trim();  
      254.                 }  
      255.             }  
      256.             catch(CryptographicException){  
      257.                  return string.Empty;  
      258.             }  
      259.             catch(ArgumentNullException){  
      260.                  return string.Empty;  
      261.             }  
      262.             catch(DecoderFallbackException){  
      263.                  return string.Empty;  
      264.             }  
      265.             catch(ArgumentException){  
      266.                  return string.Empty;  
      267.             }  
      268.             catch(FormatException){  
      269.                  return string.Empty;  
      270.             }  
      271.         }  
      272.         /// <summary>  
      273.         /// TripleDESC加密  
      274.         /// </summary>  
      275.         /// <param name="strText">待加密字符串</param>  
      276.         /// <param name="key">密匙</param>  
      277.         /// <returns></returns>  
      278.         /// <remarks></remarks>  
      279.         protected static internal string DesEncrypt(string strText, byte[] key)  
      280.         {  
      281.             try  
      282.             {  
      283.                 using (System.Security.Cryptography.TripleDESCryptoServiceProvider provider = new System.Security.Cryptography.TripleDESCryptoServiceProvider())  
      284.                 {  
      285.                     provider.Key = key;  
      286.                     provider.Mode = System.Security.Cryptography.CipherMode.ECB;  
      287.                     byte[] bytes = Encoder.GetBytes(strText);  
      288.                     return Convert.ToBase64String(provider.CreateEncryptor().TransformFinalBlock(bytes, 0, bytes.Length));  
      289.                 }  
      290.             }  
      291.             catch (CryptographicException)  
      292.             {  
      293.                 return string.Empty;  
      294.             }  
      295.             catch (ArgumentNullException)  
      296.             {  
      297.                 return string.Empty;  
      298.             }  
      299.             catch (DecoderFallbackException)  
      300.             {  
      301.                 return string.Empty;  
      302.             }  
      303.             catch (ArgumentException)  
      304.             {  
      305.                 return string.Empty;  
      306.             }  
      307.             catch (FormatException)  
      308.             {  
      309.                 return string.Empty;  
      310.             }  
      311.         }  
      312.         /// <summary>  
      313.         /// md5加密  
      314.         /// </summary>  
      315.         /// <param name="str">待加密字符串</param>  
      316.         /// <returns>返回加密后字符串</returns>  
      317.         /// <remarks></remarks>  
      318.         private static string MD5Public(string str)  
      319.         {  
      320.             using (System.Security.Cryptography.MD5CryptoServiceProvider m = new System.Security.Cryptography.MD5CryptoServiceProvider())  
      321.             {  
      322.                 byte[] MDByte = m.ComputeHash(Encoder.GetBytes(str));  
      323.                 return System.BitConverter.ToString(MDByte).Replace("-""");  
      324.             }  
      325.         }  
      326.         /// <summary>  
      327.         /// 随机数  
      328.         /// </summary>  
      329.         /// <remarks></remarks>  
      330.         private static Random Randoms = new Random();  
      331.         /// <summary>  
      332.         /// 随机字符集合  
      333.         /// </summary>  
      334.         /// <remarks></remarks>  
      335.         private static char[] xarrChar = new char[] {  
      336.             '0','1','2','3','4','5','6','7','8','9','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','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'  
      337.         };  
      338.         /// <summary>  
      339.         /// 生成随机数  
      340.         /// </summary>  
      341.         /// <returns></returns>  
      342.         /// <remarks></remarks>  
      343.         public static string RandomCode(int length)  
      344.         {  
      345.             string str = "";  
      346.             int mlength = xarrChar.Length;  
      347.             for (int i = 0; i < length; i++)  
      348.             {  
      349.                 str += xarrChar[Randoms.Next(0, mlength)];  
      350.             }  
      351.             return str;  
      352.         }  
      353.         /// <summary>  
      354.         /// 16进制字符串转Byte数组  
      355.         /// </summary>  
      356.         /// <param name="value"></param>  
      357.         /// <returns></returns>  
      358.         /// <remarks></remarks>  
      359.         private static byte[] toByte(string value)  
      360.         {  
      361.             try  
      362.             {  
      363.                 string[] chars = value.Split('-');  
      364.                 int length = chars.Length;  
      365.                 byte[] byte_ = new byte[length];  
      366.                 for (int i = 0; i < length; i++)  
      367.                 {  
      368.                     byte_[i] = Convert.ToByte(chars[i], 16);  
      369.                 }  
      370.                 return byte_;  
      371.             }  
      372.             catch (ArgumentException){  
      373.                  return null;  
      374.             }  
      375.             catch (FormatException){  
      376.                  return null;  
      377.             }  
      378.             catch (OverflowException){  
      379.                 return null;  
      380.             }  
      381.         }  
      382.         /// <summary>  
      383.         /// TripleDESC-部分密匙 字符混淆 如果要修改下面的字符 请注意修改上面的正则  
      384.         /// </summary>  
      385.         /// <param name="value"></param>  
      386.         /// <returns></returns>  
      387.         /// <remarks></remarks>  
      388.         private static string ENChar(string value)  
      389.         {  
      390.             value = value.Replace( "A""H");  
      391.             value = value.Replace( "B""G");  
      392.             value = value.Replace( "0""B");  
      393.             value = value.Replace( "9""A");  
      394.             return value;  
      395.         }  
      396.         /// <summary>  
      397.         /// TripleDESC-部分密匙 字符反混淆 如果要修改下面的字符 请注意修改上面的正则  
      398.         /// </summary>  
      399.         /// <param name="value"></param>  
      400.         /// <returns></returns>  
      401.         /// <remarks></remarks>  
      402.         private static string DEChar(string value)  
      403.         {  
      404.             value = value.Replace( "A""9");  
      405.             value = value.Replace( "B""0");  
      406.             value = value.Replace( "G""B");  
      407.             value = value.Replace( "H""A");  
      408.             return value;  
      409.         }  
      410.     }  
      411. }  
  • 相关阅读:
    电子商务:不只是一个网站那么简单
    sqlserver中使用查询分析器的一点小技巧
    以成败论英雄
    SEO 工具集合
    网页中常用JAVASCRIPT技巧
    调用样式表(基础)
    【转载】fontsize:100%有什么作用
    Div+CSS常见错误
    css简单的总结
    【转载】网页尺寸规范
  • 原文地址:https://www.cnblogs.com/ranran/p/4011620.html
Copyright © 2011-2022 走看看