Asp.Net使用加密cookie代替session验证用户登录状态 源码分享 欢迎拍砖

小论坛地址: http://rayyu.5d6d.com/thread-9444-1-1.html


正文:


首先 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)

Dim user As New Rayyu.User() '初始化用户信息(检测当前请求用户是否登录)
If user.Online Then
Response.Write("<br />name:" & user.Name & ",online:" & user.Online & ",id:" & user.ID)
End If


Dim user2 As New Rayyu.User(1, "用户名", False) '初始化(写入新用户)


C#调用:(Rayyu 是 namespace)

Rayyu.User user = new Rayyu.User();// 初始化用户信息(检测当前请求用户是否登录)
            Rayyu.User user2 = new Rayyu.User(1, "用户名", false);// 初始化(写入新用户) false 表示1小时  true表示1周


            if (user.Online)
            {
                Response.Write("<br />name:" + user.Name + ",online:" + user.Online + ",id:" + user.Id);
            }


VB.NET 源代码:

Imports System.Web
Imports System.Text.RegularExpressions
Imports System.Text
Imports System.Security.Cryptography
    ''' <summary>
    ''' 用户登录机制 支持1小时/1周状态
    ''' </summary>
    ''' <remarks></remarks>
    Public Class User
#Region "自定义参数"
        ''' <summary>
        ''' 自定义字符 用于第一层加解密密匙
        ''' </summary>
        ''' <remarks></remarks>
    Private Const CustomCode As String = "QQ:867863456"
    ''' <summary>
    ''' cookie名
        ''' </summary>
        ''' <remarks></remarks>
        Private Const CookieName As String = "userinfo"
        ''' <summary>
        ''' Cookie作用域
        ''' </summary>
        ''' <remarks></remarks>
    Private Const CookieDomain As String = ".370b.com"
        ''' <summary>
        ''' 编码
        ''' </summary>
        ''' <remarks></remarks>
        Private Shared Encoder As Encoding = Encoding.UTF8
        ''' <summary>
        ''' 用户名的正则检测 我的是:首位由字母或者汉字构成,由字母、数字、下划线、和汉字的 2-20位的字符 组合而成 的
        ''' </summary>
        ''' <remarks></remarks>
        Private Const RegexUserName As String = "[a-zA-Z\u4e00-\u9fa5][\w\u4e00-\u9fa5]{1,19}"
        ''' <summary>
        ''' 区域化信息设置
        ''' </summary>
        ''' <remarks></remarks>
    Private Shared ReadOnly Format As Globalization.CultureInfo = New System.Globalization.CultureInfo("zh-CN", True)
#End Region
#Region "回调参数"
        ''' <summary>
        ''' 是否在线
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property Online As Boolean
            Get
                Return _Online
            End Get
        End Property
        Private _Online As Boolean = False
        ''' <summary>
        ''' 用户ID (Online=true情况下使用)
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property Id As Integer
            Get
                Return _Id
            End Get
        End Property
        Private _Id As Integer
        ''' <summary>
        ''' 用户名 (Online=true情况下使用)
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property Name As String
            Get
                Return _Name
            End Get
        End Property
        Private _Name As String
        ''' <summary>
        ''' 有效期是否为7天
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property IsWeek As Boolean
            Get
                Return _IsWeek
            End Get
        End Property
        Private ReadOnly _IsWeek As Boolean
#End Region
        ''' <summary>
        ''' 初始化用户信息(检测当前请求用户是否登录)
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New()
            '读取cookie
            Dim cookie As HttpCookie = HttpContext.Current.Request.Cookies(CookieName)
            If cookie IsNot Nothing Then
                '存在cookie
                Dim value As String = cookie.Values("u"), key As String = cookie.Values("i"), tname As String = cookie.Values("n")
                cookie = Nothing
            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
                '存在对应键值
                Dim keybyte As Byte() = toByte(DEChar(key)) '解密密匙的后8位字节 由参数i构成
                If keybyte IsNot Nothing Then
                    Dim autocode() As Byte '解密密匙的前16位字节 由用户UserAgent,用户名,自定义字符 组合而成 的 md5 
                    Using m As New System.Security.Cryptography.MD5CryptoServiceProvider()
                        autocode = m.ComputeHash(Encoder.GetBytes(String.Format(Format, "{0}_{2}_{1}", HttpContext.Current.Request.UserAgent, tname, CustomCode)))
                        m.Clear()
                    End Using
                    Dim keyboard() As Byte = New Byte(keybyte.Length + autocode.Length - 1) {}
                    autocode.CopyTo(keyboard, 0)
                    keybyte.CopyTo(keyboard, autocode.Length)
                    value = DesDecrypt(value, keyboard)
                    If value.Length > 0 Then
                        '解密成功 第一层合法
                        Dim values As Match = Regex.Match(value, "^(?<md5>[\w]{32})(?<isweek>[01])(?<id>[\d]{1,10})(?<name>" & RegexUserName & ")\|(?<exp>[\d]{1,19})$")
                        If values.Success Then
                            Dim LostDateTime As Long
                            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
                                '解密后的字符串格式正确
                                Me._IsWeek = (values.Groups("isweek").Value = "1")
                                '此md5用于验证解密后的字符串 由用户id,用户名,cookie写入时间,自定义字符串 以及有效期是否是1周 组合
                                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))
                                If md5 = values.Groups("md5").Value Then
                                    'md5正常
                                    Dim lostdate As Double = (Now - New DateTime(LostDateTime)).TotalMinutes
                                    Dim l_a As Integer
                                    If IsWeek Then
                                        l_a = 10080
                                    Else
                                        l_a = 60
                                    End If
                                    If lostdate > 0 AndAlso lostdate < l_a Then
                                        'cookie在有效期内
                                        Me._Name = values.Groups("name").Value
                                        Me._Online = True
                                        If lostdate > 15 Then
                                            'cookie以写入超过15分钟,从新写入1次cookie
                                            SetUser(Me._Id, Me._Name, Me._IsWeek, autocode)
                                        End If
                                    End If
                                Else
                                    Me._Id = 0
                                    Me._Name = Nothing
                                End If
                            End If
                        End If
                    End If
                End If
            End If
            End If
        End Sub
        ''' <summary>
        ''' 初始化(写入新用户)
        ''' </summary>
        ''' <param name="userid">用户id</param>
        ''' <param name="username">用户名</param>
        ''' <param name="isweek">是否保持一周登录状态</param>
        ''' <remarks></remarks>
        Public Sub New(ByVal userId As Integer, ByVal userName As String, ByVal isWeek As Boolean)
            SetUser(userId, userName, isWeek)
            Me._ID = userId
            Me._Name = userName
            Me._IsWeek = isWeek
            Me._Online = True
        End Sub
        ''' <summary>
        ''' 写入用户
        ''' </summary>
        ''' <param name="userid">用户id</param>
        ''' <param name="username">用户名</param>
        ''' <param name="isweek">是否保持一周登录状态</param>
        ''' <param name="autocode"></param>
        ''' <remarks></remarks>
        Private Shared Sub SetUser(ByVal userid As Integer, ByVal username As String, ByVal isweek As Boolean, Optional ByVal autocode As Byte() = Nothing)
            If autocode Is Nothing Then
                '解密密匙的前16位字节 由用户UserAgent,用户名,自定义字符 组合而成 的 md5 
                Using m As New System.Security.Cryptography.MD5CryptoServiceProvider()
                    autocode = m.ComputeHash(Encoder.GetBytes(String.Format(Format, "{0}_{2}_{1}", HttpContext.Current.Request.UserAgent, username, CustomCode)))
            End Using
            End If
            Dim expires As DateTime
            Dim isweekint As Char
            If isweek Then
                expires = Now.AddDays(7)
                isweekint = "1"
            Else
                expires = Now.AddHours(1)
                isweekint = "0"
            End If
            '解密密匙的后8位字节 随机生成参数i
            Dim rbyte() As Byte = Encoder.GetBytes(RandomCode(8))
            Dim keyboard() As Byte = New Byte(23) {}
            autocode.CopyTo(keyboard, 0)
            '组合密匙 长度为24位
            rbyte.CopyTo(keyboard, autocode.Length)
            autocode = Nothing
            Dim exp As String = Now.Ticks.ToString("D", Format)
            '加密字符串
            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)
            keyboard = Nothing
            Dim key As String = ENChar(System.BitConverter.ToString(rbyte)) '混淆参数i
            rbyte = Nothing
            '写入cookie
            Dim cookie As New HttpCookie(CookieName)
            cookie.Values.Add("n", username)
            cookie.Values.Add("u", value)
            cookie.Values.Add("i", key)
            cookie.Path = "/"
            cookie.Expires = expires
            cookie.Domain = CookieDomain
            HttpContext.Current.Response.Cookies.Set(cookie)
        End Sub
        ''' <summary>
        ''' TripleDESC解密
        ''' </summary>
        ''' <param name="strText">待解密字符串</param>
        ''' <param name="key">密匙</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Protected Friend Shared Function DesDecrypt(ByVal strText As String, ByVal key As Byte()) As String
            Try
                Using provider As New System.Security.Cryptography.TripleDESCryptoServiceProvider()
                    provider.Key = key
                    provider.Mode = System.Security.Cryptography.CipherMode.ECB
                    Dim inputBuffer As Byte() = Convert.FromBase64String(strText)
                    Return Encoder.GetString(provider.CreateDecryptor().TransformFinalBlock(inputBuffer, 0, inputBuffer.Length)).Trim
                End Using
            Catch ex As CryptographicException
                Return String.Empty
            Catch ex As ArgumentNullException
                Return String.Empty
            Catch ex As DecoderFallbackException
                Return String.Empty
            Catch ex As ArgumentException
                Return String.Empty
            Catch ex As FormatException
                Return String.Empty
            End Try
        End Function
        ''' <summary>
        ''' TripleDESC加密
        ''' </summary>
        ''' <param name="strText">待加密字符串</param>
        ''' <param name="key">密匙</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Protected Friend Shared Function DesEncrypt(ByVal strText As String, ByVal key As Byte()) As String
            Try
                Using provider As New System.Security.Cryptography.TripleDESCryptoServiceProvider()
                    provider.Key = key
                    provider.Mode = System.Security.Cryptography.CipherMode.ECB
                    Dim bytes As Byte() = Encoder.GetBytes(strText)
                    Return Convert.ToBase64String(provider.CreateEncryptor().TransformFinalBlock(bytes, 0, bytes.Length))
                End Using
           Catch ex As CryptographicException
            Return String.Empty
        Catch ex As ArgumentNullException
            Return String.Empty
        Catch ex As DecoderFallbackException
            Return String.Empty
        Catch ex As ArgumentException
            Return String.Empty
        Catch ex As FormatException
            Return String.Empty
        End Try
    End Function
        ''' <summary>
        ''' md5加密
        ''' </summary>
        ''' <param name="str">待加密字符串</param>
        ''' <returns>返回加密后字符串</returns>
        ''' <remarks></remarks>
        Private Shared Function MD5Public(ByVal str As String) As String
            Dim returnx As String = "0000000000000000"
            If str IsNot Nothing AndAlso str IsNot String.Empty Then
                Try
                    Using m As New System.Security.Cryptography.MD5CryptoServiceProvider()
                        Dim MDByte As Byte() = m.ComputeHash(Encoder.GetBytes(str))
                        returnx = Strings.Replace(System.BitConverter.ToString(MDByte), "-", "")
                        m.Clear()
                    End Using
            Catch ex As ObjectDisposedException
                returnx = "0000000000000000"
                Catch ex As ArgumentOutOfRangeException
                    returnx = "0000000000000003"
                Catch ex As ArgumentNullException
                    returnx = "0000000000000001"
                Catch ex As EncoderFallbackException
                    returnx = "0000000000000001"
                Catch ex As InvalidOperationException
                    returnx = "0000000000000002"
                End Try
            End If
            Return returnx
        End Function
        ''' <summary>
        ''' 随机数
        ''' </summary>
        ''' <remarks></remarks>
        Private Shared Randoms As New Random
        ''' <summary>
        ''' 随机字符集合
        ''' </summary>
        ''' <remarks></remarks>
        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"}
        ''' <summary>
        ''' 生成随机数
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function RandomCode(ByVal length As Integer) As String
            Dim str As String = ""
            Dim mlength As Integer = xarrChar.Length
            For i As Integer = 0 To length - 1
                str &= xarrChar(Randoms.Next(0, mlength))
            Next
            Return str
        End Function
        ''' <summary>
        ''' 16进制字符串转Byte数组
        ''' </summary>
        ''' <param name="value"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Shared Function toByte(ByVal value As String) As Byte()
            Try
                Dim chars As String() = value.Split("-")
                Dim length As Integer = chars.Length - 1
                Dim byte_() As Byte = New Byte(length) {}
                For i As Integer = 0 To length
                    byte_(i) = Convert.ToByte(chars(i), 16)
                Next
                Return byte_
            Catch ex As ArgumentException
                Return Nothing
            Catch ex As FormatException
                Return Nothing
            Catch ex As OverflowException
                Return Nothing
            End Try
        End Function
        ''' <summary>
        ''' TripleDESC-部分密匙 字符混淆 如果要修改下面的字符 请注意修改上面的正则
        ''' </summary>
        ''' <param name="value"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Shared Function ENChar(ByVal value As String) As String
            value = Strings.Replace(value, "A", "H")
            value = Strings.Replace(value, "B", "G")
            value = Strings.Replace(value, "0", "B")
            value = Strings.Replace(value, "9", "A")
            Return value
        End Function
        ''' <summary>
        ''' TripleDESC-部分密匙 字符反混淆 如果要修改下面的字符 请注意修改上面的正则
        ''' </summary>
        ''' <param name="value"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Shared Function DEChar(ByVal value As String) As String
            value = Strings.Replace(value, "A", "9")
            value = Strings.Replace(value, "B", "0")
            value = Strings.Replace(value, "G", "B")
            value = Strings.Replace(value, "H", "A")
            Return value
        End Function
    End Class

C#源代码:

using System;
using System.Web;
using System.Text.RegularExpressions;
using System.Text;
using System.Security.Cryptography;
namespace Rayyu
    {
    /// <summary>
    /// 用户登录机制 支持1小时/1周状态
    /// </summary>
    /// <remarks></remarks>
    public class User
    {
        #region "自定义参数"
        /// <summary>
        /// 自定义字符 用于第一层加解密密匙
        /// </summary>
        /// <remarks></remarks>
        private const string CustomCode = "QQ:867863456";
        /// <summary>
        /// cookie名
        /// </summary>
        /// <remarks></remarks>
        private const string CookieName = "userinfo";
        /// <summary>
        /// Cookie作用域
        /// </summary>
        /// <remarks></remarks>
        private const string CookieDomain = ".370b.com";
        /// <summary>
        /// 编码
        /// </summary>
        /// <remarks></remarks>
        private static Encoding Encoder = Encoding.UTF8;
        /// <summary>
        /// 用户名的正则检测 我的是:首位由字母或者汉字构成,由字母、数字、下划线、和汉字的 2-20位的字符 组合而成 的
        /// </summary>
        /// <remarks></remarks>
        private const string RegexUserName = "[a-zA-Z\\u4e00-\\u9fa5][\\w\\u4e00-\\u9fa5]{1,19}";
        /// <summary>
        /// 区域化信息设置
        /// </summary>
        /// <remarks></remarks>
        private static System.Globalization.CultureInfo Format = new System.Globalization.CultureInfo("zh-CN", true);
    #endregion        
    #region "回调参数"
        /// <summary>
        /// 是否在线
        /// </summary>
        /// <remarks></remarks>
        public  bool Online
        {
            get { return _Online; }
        }
        private  bool _Online = false;
        /// <summary>
        /// 用户ID (Online=true情况下使用)
        /// </summary>
        /// <remarks></remarks>
        public  int Id
        {
            get { return _Id; }
        }
        private int _Id;
        /// <summary>
        /// 用户名 (Online=true情况下使用)
        /// </summary>
        /// <remarks></remarks>
        public  string Name
        {
            get { return _Name; }
        }
        private string _Name;
        /// <summary>
        /// 有效期是否为7天
        /// </summary>
        /// <remarks></remarks>
        public bool IsWeek
        {
            get { return _isWeek; }
        }
        private bool _isWeek;
        #endregion
        
        /// <summary>
        /// 初始化用户信息(检测当前请求用户是否登录)
        /// </summary>
        /// <remarks></remarks>
        public User()
        {
            //读取cookie
            HttpCookie cookie = HttpContext.Current.Request.Cookies[CookieName];
            if (cookie != null)
            {
                //存在cookie
                string value = cookie.Values["u"];
                string key = cookie.Values["i"];
                string tname = cookie.Values["n"];
                cookie = null;                
                if (tname != null && value != null && key != null && Regex.IsMatch(key, "^[1-8A-H]{2}(-[1-8A-H]{2}){7}$", System.Text.RegularExpressions.RegexOptions.None))
                {
                    //存在对应键值
                    byte[] keybyte = toByte(DEChar(key));
                    //解密密匙的后8位字节 由参数i构成                    
                    if (keybyte != null)
                    {                        
                        byte[] autocode;
                        //解密密匙的前16位字节 由用户UserAgent,用户名,自定义字符 组合而成 的 md5 
                        using (System.Security.Cryptography.MD5CryptoServiceProvider m = new System.Security.Cryptography.MD5CryptoServiceProvider())
                        {
                            autocode = m.ComputeHash(Encoder.GetBytes(string.Format(Format, "{0}_{2}_{1}", HttpContext.Current.Request.UserAgent, tname, CustomCode)));
                        }
                        byte[] keyboard = new byte[keybyte.Length + autocode.Length];
                        autocode.CopyTo(keyboard, 0);
                        keybyte.CopyTo(keyboard, autocode.Length);
                        value = DesDecrypt(value, keyboard);
                        if (value.Length > 0)
                        {
                            //解密成功 第一层合法
                            Match values = Regex.Match(value, "^(?<md5>[\\w]{32})(?<isweek>[01])(?<id>[\\d]{1,10})(?<name>" + RegexUserName + ")\\|(?<exp>[\\d]{1,19})$");
                            if (values.Success)
                            {
                                long LostDateTime = 0;
                                if (int.TryParse(values.Groups["id"].Value, out this._Id) && this._Id > 0 && long.TryParse(values.Groups["exp"].Value, out LostDateTime) && LostDateTime > 0)
                                {
                                    //解密后的字符串格式正确
                                    this._isWeek = (values.Groups["isweek"].Value == "1");
                                    //此md5用于验证解密后的字符串 由用户id,用户名,cookie写入时间,自定义字符串 以及有效期是否是1周 组合
                                    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));
                                    if (md5 == values.Groups["md5"].Value)
                                    {
                                        //md5正常
                                        double lostdate = (DateTime.Now - new DateTime(LostDateTime)).TotalMinutes;
                                        int l_a = 0;
                                        if (_isWeek)
                                        {
                                            l_a = 10080;
                                        }
                                        else
                                        {
                                            l_a = 60;
                                        }
                                        if (lostdate > 0 && lostdate < l_a)
                                        {
                                            //cookie在有效期内
                                            this._Name = values.Groups["name"].Value;
                                            this._Online = true;
                                            if (lostdate > 15)
                                            {
                                                //cookie以写入超过15分钟,从新写入1次cookie
                                                SetUser(this._Id, this._Name, this._isWeek, autocode);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        this._Id = 0;
                                        this._Name = null;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 初始化(写入新用户)
        /// </summary>
        /// <param name="userid">用户id</param>
        /// <param name="username">用户名</param>
        /// <param name="isweek">是否保持一周登录状态</param>
        /// <remarks></remarks>
        public User(int userId, string userName, bool isWeek)
        {
            SetUser(userId, userName, isWeek);
            this._Id = userId;
            this._Name = userName;
            this._isWeek = isWeek;
            this._Online = true;
        }
        /// <summary>
        /// 写入用户
        /// </summary>
        /// <param name="userid">用户id</param>
        /// <param name="username">用户名</param>
        /// <param name="isweek">是否保持一周登录状态</param>
        /// <param name="autocode"></param>
        /// <remarks></remarks>
        private static void SetUser(int userid, string username, bool isweek, byte[] autocode = null)
        {
            if (autocode == null)
            {
                //解密密匙的前16位字节 由用户UserAgent,用户名,自定义字符 组合而成 的 md5 
                using (System.Security.Cryptography.MD5CryptoServiceProvider m = new System.Security.Cryptography.MD5CryptoServiceProvider())
                {
                    autocode = m.ComputeHash(Encoder.GetBytes(string.Format(Format,"{0}_{2}_{1}", HttpContext.Current.Request.UserAgent, username, CustomCode)));
                    m.Clear();
                }
            }
            DateTime expires = default(DateTime);
            char isweekint;
            if (isweek)
            {
                expires = DateTime.Now.AddDays(7);
                isweekint = '1';
            }
            else
            {
                expires = DateTime.Now.AddHours(1);
                isweekint = '0';
            }
            //解密密匙的后8位字节 随机生成参数i
            byte[] rbyte = Encoder.GetBytes(RandomCode(8));
            byte[] keyboard = new byte[24];
            autocode.CopyTo(keyboard, 0);
            //组合密匙 长度为24位
            rbyte.CopyTo(keyboard, autocode.Length);
            autocode = null;
            string exp = DateTime.Now.Ticks.ToString("D", Format);
            //加密字符串
            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);
            keyboard = null;
            string key = ENChar(System.BitConverter.ToString(rbyte));
            //混淆参数i
            rbyte = null;
            //写入cookie
            HttpCookie cookie = new HttpCookie(CookieName);
            cookie.Values.Add("n", username);
            cookie.Values.Add("u", value);
            cookie.Values.Add("i", key);
            cookie.Path = "/";
            cookie.Expires = expires;
            cookie.Domain = CookieDomain;
            HttpContext.Current.Response.Cookies.Set(cookie);
        }
        /// <summary>
        /// TripleDESC解密
        /// </summary>
        /// <param name="strText">待解密字符串</param>
        /// <param name="key">密匙</param>
        /// <returns></returns>
        /// <remarks></remarks>
        protected static internal string DesDecrypt(string strText, byte[] key)
        {
            try
            {
                using (System.Security.Cryptography.TripleDESCryptoServiceProvider provider = new System.Security.Cryptography.TripleDESCryptoServiceProvider())
                {
                    provider.Key = key;
                    provider.Mode = System.Security.Cryptography.CipherMode.ECB;
                    byte[] inputBuffer = Convert.FromBase64String(strText);
                    return Encoder.GetString(provider.CreateDecryptor().TransformFinalBlock(inputBuffer, 0, inputBuffer.Length)).Trim();
                }
            }
            catch(CryptographicException){
                 return string.Empty;
            }
            catch(ArgumentNullException){
                 return string.Empty;
            }
            catch(DecoderFallbackException){
                 return string.Empty;
            }
            catch(ArgumentException){
                 return string.Empty;
            }
            catch(FormatException){
                 return string.Empty;
            }
        }
        /// <summary>
        /// TripleDESC加密
        /// </summary>
        /// <param name="strText">待加密字符串</param>
        /// <param name="key">密匙</param>
        /// <returns></returns>
        /// <remarks></remarks>
        protected static internal string DesEncrypt(string strText, byte[] key)
        {
            try
            {
                using (System.Security.Cryptography.TripleDESCryptoServiceProvider provider = new System.Security.Cryptography.TripleDESCryptoServiceProvider())
                {
                    provider.Key = key;
                    provider.Mode = System.Security.Cryptography.CipherMode.ECB;
                    byte[] bytes = Encoder.GetBytes(strText);
                    return Convert.ToBase64String(provider.CreateEncryptor().TransformFinalBlock(bytes, 0, bytes.Length));
                }
            }
            catch (CryptographicException)
            {
                return string.Empty;
            }
            catch (ArgumentNullException)
            {
                return string.Empty;
            }
            catch (DecoderFallbackException)
            {
                return string.Empty;
            }
            catch (ArgumentException)
            {
                return string.Empty;
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// md5加密
        /// </summary>
        /// <param name="str">待加密字符串</param>
        /// <returns>返回加密后字符串</returns>
        /// <remarks></remarks>
        private static string MD5Public(string str)
        {
            using (System.Security.Cryptography.MD5CryptoServiceProvider m = new System.Security.Cryptography.MD5CryptoServiceProvider())
            {
                byte[] MDByte = m.ComputeHash(Encoder.GetBytes(str));
                return System.BitConverter.ToString(MDByte).Replace("-", "");
            }
        }
        /// <summary>
        /// 随机数
        /// </summary>
        /// <remarks></remarks>
        private static Random Randoms = new Random();
        /// <summary>
        /// 随机字符集合
        /// </summary>
        /// <remarks></remarks>
        private static char[] xarrChar = 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'
	    };
        /// <summary>
        /// 生成随机数
        /// </summary>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string RandomCode(int length)
        {
            string str = "";
            int mlength = xarrChar.Length;
            for (int i = 0; i < length; i++)
            {
                str += xarrChar[Randoms.Next(0, mlength)];
            }
            return str;
        }
        /// <summary>
        /// 16进制字符串转Byte数组
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        private static byte[] toByte(string value)
        {
            try
            {
                string[] chars = value.Split('-');
                int length = chars.Length;
                byte[] byte_ = new byte[length];
                for (int i = 0; i < length; i++)
                {
                    byte_[i] = Convert.ToByte(chars[i], 16);
                }
                return byte_;
            }
            catch (ArgumentException){
                 return null;
            }
            catch (FormatException){
                 return null;
            }
            catch (OverflowException){
                return null;
            }
        }
        /// <summary>
        /// TripleDESC-部分密匙 字符混淆 如果要修改下面的字符 请注意修改上面的正则
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        private static string ENChar(string value)
        {
            value = value.Replace( "A", "H");
            value = value.Replace( "B", "G");
            value = value.Replace( "0", "B");
            value = value.Replace( "9", "A");
            return value;
        }
        /// <summary>
        /// TripleDESC-部分密匙 字符反混淆 如果要修改下面的字符 请注意修改上面的正则
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        private static string DEChar(string value)
        {
            value = value.Replace( "A", "9");
            value = value.Replace( "B", "0");
            value = value.Replace( "G", "B");
            value = value.Replace( "H", "A");
            return value;
        }
    }
}


评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值