必须填写至少10个字的日志
nnhy authored at 2012-07-27 18:48:21
33.70 KiB
X
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Web;
using NewLife.Log;

namespace XCode.XLicense
{
#if DEBUG
    /// <summary>
    /// X框架授权许可证
    /// </summary>
    internal static class License
    {
        #region 基本属性
        private static LicenseInfo _Current;
        /// <summary>
        /// 当前授权设置
        /// </summary>
        public static LicenseInfo Current
        {
            get
            {
                //不能试用另外的标记判断是否已经加载
                //用户试用的时候,可能一开始忘了放授权文件,从而出现无效授权,等放上授权文件后,需要重新读取
                //所以,如果没有授权文件,将会一直读取,性能就不是那么好了
                if (_Current == null) _Current = GetLicense();
                return _Current;
            }
        }

        /// <summary>
        /// 内部密钥
        /// </summary>
        internal static String InternalKey
        {
            get
            {
                //这是明文,Key就是使用该明文加密后的字符串,返回的时候需要解密
                //String Text = "qxYw9MTk35bmvhwRxhhf6rjaWqu4SogV4CgGjXRdMQU2akGs5kv/7JP8rgSN3WA92oOh7B8Q9TV3Ux31n4H0hKteSbPmiE47J6u9wBv7tpIp52etQalua1pj2n3IDnDOq1gpB2J3WCELo2De83rCJsiHGoxT9bMPFrk3qFT3QTIMpLenluGsRcYMKZC4B0qTdd1xNgMWdXXUYDDvbd3tOHM9P3KzZHwC40GlWtlTad90VktcmFnSMq9LpqSi61Rr4mc57WuVB59Q666el14i44hGcRZaEK51/fdeu3ZwTh06CQxlRFNH2WukqGXZFEFO7ZxT+kONjYD+pU0TLkMoYtoPUrjukoLQaymQfIH0DnizKNSvwlpK7AP7Pme2OBz8BieO8emRerXne1bJYXvz533GYeqYe1eDQWnprGBUVA3LidkDfqk7gy5eJGwMx3mJhig8/cTIbkoqxjTlTEWU0POeaj+n3nDbOSZOXkOMe7w14MeZD/sJwrgDZiGL/QtmS5w2cPIjJdvzJrFjAag/lUyufV7fqcfTxt1s51dOlLtiRKZ+Th0LRtRb+zD2fxgkWROqjhGXKxRSsmD1hg3aGh1ECM2lcVeKRCHU9hy0/GVSH/peTJ1OvzCAtrYTqH9DHQEP2DafYWMcssy+TYijPAWxfi+loW3u4IG8M6PSn8EpzvaIIsNodQytjv0EEqsKQJTSGq3e47ZVyPl9Vkm6Lf0fqunU7tql2tyTJkFYXqq2Ouu8TouMMCpmTlYmMq4TWBqo9FmG98pC5xxL0n3gnZ+ZA6qdtN8fVmMh2n/NnwVcqO5lamo7PpXteD2DnXW4KMksnvVoYebyTy3s7BcCdev0wJnJ0kJHXWXTX3Lj9pwUipf4";
                String key = "mcy3p61tWka23Yl+e+s6YqcpZn86Su5vSfE3IylHReCWg6b3wrhwTpYwis41apClXodEBzIl5H3aO3Q2UQrR6LYgH+D8MPajQ87RTUPpr73IFJ3UmunPj7QFBDY/xNn8vVh1/U/xgGSsreUv0QNpPGCyUydFAGml2GRplcOjGps34XJIU1J65MYNIft9Jjb+pn9M7mQFJ+24UbeuE7u0yMJsCfzblJ08/fNbS3yU4r/VgFQnmQGY4jFWw/jSCwOJ126xibOBmwPOjj+WCcL5qEDgQyfrOo9BPJiS7XQhdq9QMQcZu+zhHQgR9J/yZ09NLg3vY0d3UsdZ96zUUASrkxRpmSmeQ80Whs1RADPW58DS8Ui0iB7cvf4YMe1X4KAgrPiUh7vBzCW6QOvbEedTIPGc+OFlsxSCRzQxHqLiIZshbF4vB2nKURzlnKVFenqRXELym6MlrL/7l2Xmk4IZr0MNfVsHrjy9O3Hgiq2vEubyudWuZ046zNyDUx9kmFOj/O13QIna4RaqO8gx3Z/XQhVaWy1jUzLPGV/Wg3rsk+/3HVN96HUdmmsWFkgdtbC23C5IFnYEWfedmu73iE7bSr6uno1jyAtQY/pouM9bzwvLgQflAMSo7F6zVI+cV4z4rm7zaBbrTT6fD5CPbvbnjyZYwa3lP46UMLm6vDy9/EeCvRqTmR0OEPmdhG3q2yKViThgxU6JimVcTjRjTMbPNFR51BdmZUe/8amPHHij73EVg8HJeuDPbR/aIMaNbsghjjGSJyGSaXUtqu0NUCaXSUA5odLR+i5S0aZYq5YaG10N000ArZage22kj1eVk9tHOiJWqXrCfTPs/GsWsqouoCDcgk8SoJ6mkPkKoKJKIMGOgIOBufPVJ70QUCag4uW4pgLC83BgdOxkn9FuBeHZl81Jo9N1qWsnHqQPrfntgEVBIBvAWyIEa1BZiXoEW6PPzC5qd7K1CPcoFXt25qfsbXPT8tnA/wZLqqQiKVQFcMhjj6xlP1kp8ZilBRLaWy1+3MeJFxY+Ahyu3u8Si4bZim4v9UTg43BcrTDxoFpeWedbcwhtXKIyXe84rNceUqoO9TRLKXCQTJj4MWKL3lQfS534DM0DNGBnk5VG0GqMJrePp3wjG1Az/6yI2EyzrnU/cdi11rKajNr/Be7VWI3iEg==";
                //RC4解密
                return Encoding.UTF8.GetString(Encrypt(Convert.FromBase64String(key), "XCode.nnhy.org"));
            }
        }

        /// <summary>
        /// 公钥
        /// </summary>
        internal static String PublicKey
        {
            get
            {
                String key = "SE3SBT/eiSI1M2bvHnWuNBGLx+tH8sq9DfCB9UFPUqI/BJ1JNqTB8+VR4OaxmuX48h5oss2zp8lNracPggacMAeE0p/V/BI/7rSjYEuk6UDu6+6cje1WANehg+aMT3ZpEszjZB6cGe1rb5GkDUqkVjjgH4sojUphQxrQWEQw50+JOYPJ73VIK4PLjj79zoUfKC6cY/G0YGdMNUUDc2zNHugYsi613RbmTGy/RrvoGPNdk44nnTZWwklOLvMPlDqlU178YtuJ4/Ws8mUqyHAfzQS+ZAmjdtlNoqTLRGglSBvbP9+Mm18ulhaugycC/X498Inh";
                //RC4解密
                return Encoding.UTF8.GetString(Encrypt(Convert.FromBase64String(key), InternalKey));
            }
        }

        //只允许授权管理器使用私钥
#if ISMANAGE
        /// <summary>
        /// 私钥
        /// </summary>
        internal static String PrivateKey
        {
            get
            {
                String key = "SE3SBT/eiSI1M2bvHnWuNBGLx+tH8sq9DfCB9UFPUqI/BJ1JNqTB8+VR4OaxmuX48h5oss2zp8lNracPggacMAeE0p/V/BI/7rSjYEuk6UDu6+6cje1WANehg+aMT3ZpEszjZB6cGe1rb5GkDUqkVjjgH4sojUphQxrQWEQw50+JOYPJ73VIK4PLjj79zoUfKC6cY/G0YGdMNUUDc2zNHugYsi613RbmTGy/RrvoGPNdk44nnTZWwklOLvMPlDqlU178YtuJ4/Ws8mUqyHAfzQS+ZAmjdtlNoqTLRGglSBvbP9+Mm19R+m6X8SYr4W8pvKmU8w+QhzpwwoeX/NLOELMWyK32kssx4JOYmorqpi6iU2x0PVLQ6h6lmzbCbLLcTozL5xchERO8aNq4Y9rDRFwqFrfNF1kPbCperlev1ubpExqER6pk2ZP7jI9Afi7V7V58/243y9HOpt7VzZoRyJEl998+Sralwk8WPviUvqmYSMdanhjMGzChxn8MNEFgGS4CBeI4usSkrjWBTvaRs+z7m9Gektcq/hVjX+cE+MTpvhvi+J3ZnE4LX18LzL/9qY9KUSaPlTaICiFOWNBxS+WNY8zXm6JDt932Ze92iynMyy4BPmCJ8n7SITvKbvFJKZ8kbjO2XomAyxAxlNG3krmlzu7HTVKWy51oL2UlQIrgnCJxYI8wLjPu3rnPQ2vzYbCeDQwEePT2aldAAg6mo5D0An2fZRSpLHeEd/OjmijsKB2EvmYX5EhZ8gAsCDdAtGLlGUZzBHVmm+ES4jmociddtdAYq3NXaMyMZ04GMtWvNgfLraj4K0NOPrmT5xH7Bo1fLCXxFfGckAgFFVsIIhezGu3xWe9pDG44TbwY1bsMMNJRZD1NAxu0CmSMc1KB8Gse68RAB3AKBxMyVyCJJtbE/09BHk0Jhkr5ILxzHyQhq8IVBlPp/wKob8z5/MoCOkUWmZ+4eYxhU4x9RrL0u2oK5hUvTwsIQqMI7B/FpCzd3DUBXci9L7umYDB7wJR36vCem5eTN70RNvahrzKEPRcpMGwx4SucVA7z6cM55KHHindXHk9vho6RqtUIXYwVYOhQrgl0SBViSvB+E2H3d4ZvP/bixSguluhaxO2pbW6+3hwkyTl5i9LwmUqBM4MIVV6i0dDlNtnIXcuYe18hLOYlc4IYDP2TLmu0B26eUOOUlSnIVsPLKoTJqErIfGyVb4B4";
                //RC4解密
                return Encoding.UTF8.GetString(Encrypt(Convert.FromBase64String(key), InternalKey));
            }
        }
#endif
        #endregion

        #region 属性
        /// <summary>
        /// 开始时间。用户评估执行时间。
        /// </summary>
        private static DateTime StartTime = DateTime.Now;

        /// <summary>
        /// IP列表
        /// </summary>
        private static Dictionary<String, DateTime> IPList = new Dictionary<String, DateTime>();

        /// <summary>
        /// 会话列表
        /// </summary>
        private static Dictionary<String, DateTime> SessionList = new Dictionary<String, DateTime>();

        /// <summary>
        /// 列表锁定专用对象
        /// </summary>
        private static Object ListLockObj = new Object();

        #region 数据库连接数
        private static Int32 _DbConnectCount;
        /// <summary>
        /// 数据库连接数
        /// </summary>
        public static Int32 DbConnectCount
        {
            get { return _DbConnectCount; }
            set
            {
                //Trace.WriteLine("设置:DbConnectCount=" + value);
                _DbConnectCount = value;
                if (Current.MaxDbConnect.Enable && Current.MaxDbConnect.IntVal < _DbConnectCount)
                {
                    ShowErr(String.Format("当前数据库连接数是:{0},已超过授权数:{1}。", _DbConnectCount, Current.MaxDbConnect.IntVal));
                }
            }
        }
        #endregion

        #region 缓存数
        private static Int32 _CacheCount;
        /// <summary>
        /// 缓存数
        /// </summary>
        public static Int32 CacheCount
        {
            get { return _CacheCount; }
            set
            {
                //Trace.WriteLine("设置:CacheCount=" + value);
                _CacheCount = value;
                if (Current.MaxCache.Enable && Current.MaxCache.IntVal < _CacheCount)
                {
                    ShowErr(String.Format("当前缓存数是:{0},已超过授权数:{1}。", _CacheCount, Current.MaxCache.IntVal));
                }
            }
        }
        #endregion

        #region 实体数
        private static Int32 _EntityCount;
        /// <summary>
        /// 实体数
        /// </summary>
        public static Int32 EntityCount
        {
            get { return _EntityCount; }
            set
            {
                //Trace.WriteLine("设置:EntityCount=" + value);
                _EntityCount = value;
                if (Current.MaxEntity.Enable && Current.MaxEntity.IntVal < _EntityCount)
                {
                    ShowErr(String.Format("当前实体数是:{0},已超过授权数:{1}。", _EntityCount, Current.MaxEntity.IntVal));
                }
            }
        }
        #endregion

        private static List<String> _Filters;
        /// <summary>可用站点列表</summary>
        public static List<String> Filters
        {
            get
            {
                if (_Filters == null)
                {
                    List<String> list = new List<String>();
                    if (!String.IsNullOrEmpty(Current.WebSiteList.Value))
                    {
                        String[] ss = Current.WebSiteList.Value.Split(new Char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (String item in ss)
                        {
                            list.Add(item.Trim());
                        }
                    }
                    _Filters = list;
                }
                return _Filters;
            }
            //set{_Filters=value;} 
        }

        private static List<String> _LocalFilters;
        /// <summary>本地站点列表</summary>
        public static List<String> LocalFilters
        {
            get
            {
                if (_LocalFilters == null)
                {
                    _LocalFilters = new List<String>();
                    _LocalFilters.Add("127.0.0.1");
                    _LocalFilters.Add("localhost");
                    _LocalFilters.Add(HardInfo.MachineName.ToLower());
                    if (!String.IsNullOrEmpty(HardInfo.IPs))
                    {
                        String[] ss = HardInfo.IPs.Split(' ');
                        foreach (String item in ss)
                        {
                            _LocalFilters.Add(item);
                        }
                    }
                }
                return _LocalFilters;
            }
            //set { _LocalFilters = value; }
        }
        #endregion

        #region 编码/解码
        /// <summary>
        /// 授权编码
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        internal static String Encode(String text)
        {
            String xml = text;
#if ISMANAGE
            //签名。XCode生成的Lic文件不包含签名,防止私钥泄露
            xml += "$"+ License.Sign(Encoding.UTF8.GetBytes(xml), PrivateKey);
#else
            xml += "$";
#endif
            //DES加密
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            //IV的明文
            String key = "mama shuo wo zhang da le";
            //加密IV
            des.GenerateIV();
            String iv = Convert.ToBase64String(Encrypt(des.IV, key));
            //生成一个Key
            des.GenerateKey();
            key = Convert.ToBase64String(des.Key);
            key = key + "|" + iv;
            //DES加密
            xml = Encrypt(xml, key);
            xml += "@" + key;
            //RC4加密
            Byte[] bts = Encrypt(Encoding.UTF8.GetBytes(xml), InternalKey);
            return Convert.ToBase64String(bts);
        }

        //*****************************************
        //授权读取过程
        //
        //读取->Base64字符串转字节码->RC4用InternalKey解密->字节码转字符串->
        //字符串按@拆为两部分,前数据后密码
        //密码按|分为两部分,前密码后是XCode经RC4加密后的IV
        //DES解密
        //字符串按$拆为两部分,前数据,后签名
        //签名校验
        //
        //*****************************************

        /// <summary>
        /// 授权解码
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        internal static String Decode(String text)
        {
            //解Base64编码
            Byte[] bts = Convert.FromBase64String(text);
            //RC4解密
            bts = Encrypt(bts, InternalKey);
            String key = Encoding.UTF8.GetString(bts);
            //DES解密
            key = Decrypt(key.Substring(0, key.IndexOf("@")), key.Substring(key.IndexOf("@") + 1));
            //验证签名
            String xml = key.Substring(0, key.LastIndexOf("$"));
            key = key.Substring(key.LastIndexOf("$") + 1);
#if !ISMANAGE
            //XCode的解码函数才需要校验签名
            if (!Verify(Encoding.UTF8.GetBytes(xml), key, PublicKey)) return null;
#endif
            return xml;
        }
        #endregion

        #region 读取授权
        /// <summary>
        /// 读取授权。如果成功,则返回授权;否则返回试用授权。
        /// 不需要建立文件监视,因为如果授权文件改变,程序域将会重启。
        /// </summary>
        /// <returns></returns>
        private static LicenseInfo GetLicense()
        {
            try
            {
                String key = ReadLicense();
                //无法读出授权信息,以试用版方式运行。
                if (String.IsNullOrEmpty(key))
                {
                    _Current = LicenseInfo.Trial;
                    return _Current;
                }

                String xml = Decode(key);
                if (String.IsNullOrEmpty(xml))
                {
                    ShowErr("非法授权文件!");
                    _Current = LicenseInfo.Trial;
                    return _Current;
                }
                _Current = LicenseInfo.FromXML(xml);

                //马上检查文件签名授权
                if (!CheckFileSign(_Current))
                {
                    ShowErr("本授权只针对特定版本的XCode,请不要使用其它版本的XCode!");
                    _Current = LicenseInfo.Trial;
                }
            }
            catch (Exception ex)
            {
                XTrace.WriteLine(ex.ToString());
                _Current = LicenseInfo.Trial;
            }
            //放在后面返回,任何错误时都能将其设置为试用版。
            return _Current;
        }

        /// <summary>
        /// 读取授权文件
        /// </summary>
        /// <returns></returns>
        private static String ReadLicense()
        {
            // 获取授权文件路径
            String path = GetPath();
            // 读取授权文件
            String filepath;//= Path.Combine(path, Environment.MachineName + ".lic");
            //如果不存在针对本机的授权文件,则使用通用授权文件
            //if (!File.Exists(filepath)) filepath = Path.Combine(path, "X.lic");
            //写入的时候写机器名,读取的时候读X.lic
            filepath = Path.Combine(path, "X.lic");

            //没有授权文件,准备写机器码文件
            if (!File.Exists(filepath))
            {
                filepath = Path.Combine(path, Environment.MachineName + "授权申请.lic");
                if (!File.Exists(filepath))
                {
                    MakeTrail(filepath);
                }
                return null;
            }

            String key = String.Empty;
            //using (StreamReader sr = new StreamReader(filepath, Encoding.UTF8))
            //{
            //    key = sr.ReadToEnd();
            //    sr.Close();
            //}
            using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read))
            {
                Byte[] bts = new Byte[fs.Length];
                fs.Read(bts, 0, bts.Length);
                key = Encoding.UTF8.GetString(bts);
            }
            return key;
        }

        internal static String GetPath()
        {
            String path;
            if (HttpContext.Current != null)
            {
                //path = HttpContext.Current.Server.MapPath("~/");
                path = HttpContext.Current.Server.MapPath("~/Bin");
            }
            else
            {
                path = AppDomain.CurrentDomain.BaseDirectory;
                if (!String.IsNullOrEmpty(AppDomain.CurrentDomain.RelativeSearchPath))
                    path = Path.Combine(path, AppDomain.CurrentDomain.RelativeSearchPath);
            }
            return path;
        }

        internal static void MakeTrail(String filepath)
        {
            LicenseInfo info = LicenseInfo.Trial;
            info.ReadHardInfo();
            //写入当前URL
            if (HttpContext.Current != null)
            {
                info.WebSiteList.Enable = true;
                info.WebSiteList = HttpContext.Current.Request.Url.ToString();
            }
            String path = GetPath();
            path = Path.Combine(path, "XCode.dll");
            if (File.Exists(path))
            {
                info.FileSignature.Enable = true;
                Byte[] data = File.ReadAllBytes(path);
                if (data != null)
                {
                    MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                    data = md5.ComputeHash(data);
                    info.FileSignature = Convert.ToBase64String(data);
                }
            }
            String content = info.ToXML();
            //Byte[] bts = Encrypt(Encoding.UTF8.GetBytes(content), InternalKey);
            content = Encode(content);
            Byte[] bts = Encoding.UTF8.GetBytes(content);
            //content = Convert.ToBase64String(bts);
            //using (StreamWriter sw = new StreamWriter(filepath, false, Encoding.UTF8))
            //{
            //    sw.Write(content);
            //    sw.Close();
            //}
            using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write))
            {
                fs.Write(bts, 0, bts.Length);
                fs.SetLength(bts.Length);
            }
        }
        #endregion

        #region DES加密解密
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="data">待加密数据</param>
        /// <param name="key">密码</param>
        /// <returns></returns>
        private static String Encrypt(String data, String key)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            String iv = key.Substring(key.IndexOf("|") + 1);
            des.Key = Convert.FromBase64String(key.Substring(0, key.IndexOf("|")));
            des.IV = Encrypt(Convert.FromBase64String(iv), "XCode");
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(data));
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Read);
            //最大10K
            Byte[] bts = new Byte[10240];
            Int32 count = cs.Read(bts, 0, bts.Length);
            return Convert.ToBase64String(bts, 0, count);
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="data">待解密数据</param>
        /// <param name="key">密码</param>
        /// <returns></returns>
        internal static String Decrypt(String data, String key)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            String iv = key.Substring(key.IndexOf("|") + 1);
            des.Key = Convert.FromBase64String(key.Substring(0, key.IndexOf("|")));
            des.IV = Encrypt(Convert.FromBase64String(iv), "XCode");
            MemoryStream ms = new MemoryStream(Convert.FromBase64String(data));
            CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read);
            //最大10K
            Byte[] bts = new Byte[10240];
            Int32 count = cs.Read(bts, 0, bts.Length);
            return Encoding.UTF8.GetString(bts, 0, count);
        }
        #endregion

        #region RC4加密
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="pass">密码</param>
        /// <returns></returns>
        internal static Byte[] Encrypt(Byte[] data, String pass)
        {
            if (data == null || pass == null) return null;
            Byte[] output = new Byte[data.Length];
            Int64 i = 0;
            Int64 j = 0;
            Byte[] mBox = GetKey(Encoding.UTF8.GetBytes(pass), 256);

            // 加密
            for (Int64 offset = 0; offset < data.Length; offset++)
            {
                i = (i + 1) % mBox.Length;
                j = (j + mBox[i]) % mBox.Length;
                Byte temp = mBox[i];
                mBox[i] = mBox[j];
                mBox[j] = temp;
                Byte a = data[offset];
                //Byte b = mBox[(mBox[i] + mBox[j] % mBox.Length) % mBox.Length];
                // mBox[j] 一定比 mBox.Length 小,不需要在取模
                Byte b = mBox[(mBox[i] + mBox[j]) % mBox.Length];
                output[offset] = (Byte)((Int32)a ^ (Int32)b);
            }

            return output;
        }

        /// <summary>
        /// 打乱密码
        /// </summary>
        /// <param name="pass">密码</param>
        /// <param name="kLen">密码箱长度</param>
        /// <returns>打乱后的密码</returns>
        internal static Byte[] GetKey(Byte[] pass, Int32 kLen)
        {
            Byte[] mBox = new Byte[kLen];

            for (Int64 i = 0; i < kLen; i++)
            {
                mBox[i] = (Byte)i;
            }
            Int64 j = 0;
            for (Int64 i = 0; i < kLen; i++)
            {
                j = (j + mBox[i] + pass[i % pass.Length]) % kLen;
                Byte temp = mBox[i];
                mBox[i] = mBox[j];
                mBox[j] = temp;
            }
            return mBox;
        }
        #endregion

        #region RSA签名
        /// <summary>
        /// 签名
        /// </summary>
        /// <param name="data"></param>
        /// <param name="priKey"></param>
        /// <returns></returns>
        internal static String Sign(Byte[] data, String priKey)
        {
            if (data == null | String.IsNullOrEmpty(priKey)) return null;

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            try
            {
                rsa.FromXmlString(priKey);
                return Convert.ToBase64String(rsa.SignHash(md5.ComputeHash(data), "1.2.840.113549.2.5"));
            }
            catch { return null; }
        }
        #endregion

        #region RSA验证签名
        /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="data">待验证的数据</param>
        /// <param name="signdata">签名</param>
        /// <param name="pubKey">公钥</param>
        /// <returns></returns>
        internal static Boolean Verify(Byte[] data, String signdata, String pubKey)
        {
            if (data == null ||
                data.Length < 1 ||
                String.IsNullOrEmpty(signdata) ||
                String.IsNullOrEmpty(pubKey)) return false;

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            try
            {
                rsa.FromXmlString(pubKey);
                return rsa.VerifyHash(md5.ComputeHash(data), "1.2.840.113549.2.5", Convert.FromBase64String(signdata));
            }
            catch { return false; }
        }
        #endregion

        #region 许可检查
        /// <summary>
        /// 检查授权许可证。
        /// 每次请求这里都会执行一次,所以要注意性能问题。
        /// </summary>
        /// <returns>是否有效授权</returns>
        public static Boolean Check()
        {
            //Trace.WriteLine("设置:Check");
            //检查硬件是否匹配
            //if (!Current.CheckHardInfo())
            //{
            //    ShowErr("机器硬件已被修改。");
            //    return false;
            //}
            //检查机器名
            if (Current.MachineName.Enable && Current.MachineName != HardInfo.MachineName)
            {
                ShowErr(String.Format("你只能在名为{0}的机器上使用该授权。", Current.MachineName));
                return false;
            }
            //检查主板
            if (Current.BaseBoard.Enable && Current.BaseBoard != HardInfo.BaseBoard)
            {
                ShowErr("你只能在指定主板上使用该授权。");
                return false;
            }
            //检查CPU
            if (Current.Processors.Enable && Current.Processors != HardInfo.Processors)
            {
                ShowErr("你只能在指定处理器上使用该授权。");
                return false;
            }
            //检查驱动器
            if (Current.DiskDrives.Enable && Current.DiskDrives != HardInfo.DiskDrives)
            {
                ShowErr("你只能在指定驱动器上使用该授权。请不要把程序移动到别的盘来使用,也不要格式化原授权盘。");
                return false;
            }
            //检查网卡
            if (Current.Macs.Enable && Current.Macs != HardInfo.Macs)
            {
                ShowErr("你只能在指定网卡上使用该授权。");
                return false;
            }
            //检查IP地址
            if (Current.IPs.Enable && Current.IPs != HardInfo.IPs)
            {
                ShowErr(String.Format("你只能在IP为{0}的机器上使用该授权。", Current.IPs));
                return false;
            }
            //检查执行时间
            if (Current.EvaluationPeriod.Enable)
            {
                TimeSpan ts = DateTime.Now - StartTime;
                if (ts.TotalMinutes > Current.EvaluationPeriod.IntVal)
                {
                    ShowErr(String.Format("已执行时间:{0}分钟,超过授权数:{1}分钟。", (Int32)(ts.TotalMinutes), Current.EvaluationPeriod.IntVal));
                    return false;
                }
            }
            //检查有效期
            if (Current.ExpirationDate.Enable)
            {
                if (DateTime.Now > Current.ExpirationDate.DateTimeVal)
                {
                    ShowErr("授权已过期!");
                    return false;
                }
                DateTime dt = new DateTime(2010, 07, 09);
                //检查时间,可能经过调整
                if (DateTime.Now < dt)
                {
                    ShowErr("系统时间无效!");
                    return false;
                }
            }
            //检查IP数
            if (Current.MaxIP.Enable && HttpContext.Current != null && HttpContext.Current.Request != null)
            {
                //如果不是HTTP,直接返回验证失败
                //if (HttpContext.Current == null) return false;
                String cip = HttpContext.Current.Request.UserHostAddress;
                if (!CheckList(IPList, cip, Current.MaxIP.IntVal))
                {
                    ShowErr(String.Format("当前在线数是:{0},已超过授权数:{1}。", IPList.Count, Current.MaxIP.IntVal));
                    return false;
                }
            }
            //检查会话数
            if (Current.MaxSession.Enable && HttpContext.Current != null && HttpContext.Current.Session != null)
            {
                //如果不是HTTP,直接返回验证失败
                //if (HttpContext.Current == null || HttpContext.Current.Session == null) return false;
                //建立一个Session值,告诉aspnet,应用程序已经使用Session了,不要每次都改变SessionID了。
                HttpContext.Current.Session["XCode_Session_Holder"] = "该Session值仅仅是为了维持SessionID不变!";
                String cid = HttpContext.Current.Session.SessionID;
                if (!CheckList(SessionList, cid, Current.MaxSession.IntVal))
                {
                    ShowErr(String.Format("当前会话数是:{0},已超过授权数:{1}。", SessionList.Count, Current.MaxSession.IntVal));
                    return false;
                }
            }
            //检查可用站点列表
            if (Current.WebSiteList.Enable && HttpContext.Current != null && HttpContext.Current.Request != null)
            {
                Uri uri = HttpContext.Current.Request.Url;
                String url = uri.ToString().ToLower();
                Boolean pass = false;
                if (LocalFilters.Contains(uri.Host.ToLower())) pass = true;
                if (!pass && Filters.Count > 0)
                {
                    foreach (String item in Filters)
                    {
                        if (url.Contains(item))
                        {
                            pass = true;
                            break;
                        }
                    }
                }
                if (!pass)
                {
                    ShowErr(String.Format("当前请求页{0}不在许可站点列表之中!", uri.ToString()));
                    return false;
                }
            }

            return true;
        }

        private static Boolean CheckList(Dictionary<String, DateTime> List, String item, Int32 max)
        {
            //加入当前item
            if (!List.ContainsKey(item))
            {
                //加双锁,用于多线程
                lock (ListLockObj)
                {
                    if (!List.ContainsKey(item)) List.Add(item, DateTime.Now);
                }
            }
            if (List.Count < max) return true;

            //超过限制,试试删除无效的。超过限制时才删除,这样有利于提高性能
            lock (ListLockObj)
            {
                if (List.Count > max)
                {
                    //每次都遍历,太浪费资源了
                    List<String> todel = new List<String>();
                    foreach (String ip in List.Keys)
                    {
                        if (List[ip].AddMinutes(1) < DateTime.Now) todel.Add(ip);
                    }
                    foreach (String ip in todel)
                    {
                        List.Remove(ip);
                    }
                }
            }
            //没办法了,真的超出了
            if (List.Count > max) return false;
            return true;
        }

        /// <summary>
        /// 检查文件签名
        /// </summary>
        /// <param name="li"></param>
        /// <returns></returns>
        private static Boolean CheckFileSign(LicenseInfo li)
        {
            if (li == null) return false;
            //未启用该限制
            if (!li.FileSignature.Enable) return true;
            if (String.IsNullOrEmpty(li.FileSignature.Value)) return false;
            // 获取授权文件路径
            string path = typeof(License).Module.FullyQualifiedName;
            // 读取授权文件
            string filepath = Path.GetDirectoryName(path) + @"\XCode.dll";
            Byte[] bts;
            using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read))
            {
                bts = new Byte[fs.Length];
                fs.Read(bts, 0, bts.Length);
                fs.Close();
            }

            if (!Verify(bts, li.FileSignature, PublicKey)) return false;

            return true;
        }
        #endregion

        #region 错误信息
        /// <summary>
        /// 授权无效时显示错误信息,同时终止Http处理
        /// </summary>
        /// <param name="msg"></param>
        public static void ShowErr(String msg)
        {
            if (HttpContext.Current != null)
            {
                try
                {
                    HttpResponse res = HttpContext.Current.Response;
                    res.Clear();
                    res.Write("你好 <font color=\"red\">" + (_Current != null ? _Current.EndUser.FormatedValue : "未知用户") + "</font>,这是一个无效授权!<BR>");
                    res.Write(msg);
                    res.Write("<BR>请联系 <font color=\"blue\">" + (_Current != null ? _Current.UserName.FormatedValue : "未知用户") + "</font> 购买合适的授权!");
                    res.Flush();
                    res.End();
                }
                catch (ThreadAbortException ex) { throw new Exception("", ex); }
            }
            else
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("你好 ");
                sb.Append((_Current != null ? _Current.EndUser.FormatedValue : "未知用户"));
                sb.Append(",这是一个无效授权!");
                sb.AppendLine();
                sb.AppendLine(msg);
                sb.Append("请联系 ");
                sb.Append((_Current != null ? _Current.UserName.FormatedValue : "未知用户"));
                sb.Append(" 购买合适的授权!");
                throw new InvalidOperationException(sb.ToString());
            }
        }
        #endregion
    }
#endif
}