| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- using System;
- using System.Collections.Generic;
- using Top.Api.Util;
- using System.Threading;
- using Top.Api.Report;
- namespace Top.Api.Security
- {
- /// <summary>
- /// 加、解密核心类
- /// </summary>
- public class SecurityCore : SecurityConstants
- {
- private static readonly ITopLogger Log = Top.Api.Log.Instance;
- // 缓存用户单独分配秘钥,需要加同步锁
- private static readonly IDictionary<string, SecretContext> AppUserSecretCache = new Dictionary<string, SecretContext>();
- private static readonly IDictionary<string, SecretContext> AppSecretCache = new Dictionary<string, SecretContext>();
- private static readonly object EmptyObject = new object();
- private static readonly object CacheLock = new object();
- private static readonly object AppLock = new object();
- private static readonly object AsynQueueKeyLock = new object();
- private string randomNum;// 伪随机码
- private DefaultTopClient topClient;
- private static IDictionary<string, object> asynQueueKey = new Dictionary<string, object>();
- private static readonly IDictionary<string, IDictionary<string, object>> AllAppConfig = new Dictionary<string, IDictionary<string, object>>();
- private bool streetest;
- public static IDictionary<string, SecretContext> GetAppUserSecretCache()
- {
- return AppUserSecretCache;
- }
- /// <summary>
- /// 判断密文是否支持检索
- /// </summary>
- /// <param name="key"></param>
- /// <param name="version"></param>
- /// <returns></returns>
- public bool IsIndexEncrypt(string key, Nullable<Int64> version)
- {
- if (version != null && version < 0)
- {
- key = PREVIOUS + key;
- }
- else
- {
- key = CURRENT + key;
- }
- IDictionary<string, Object> appConfig = getAppConfig();
- if (appConfig == null)
- {
- return false;
- }
- object encryptType = null;
- appConfig.TryGetValue(key, out encryptType);
- return INDEX_ENCRYPT_TYPE.Equals(encryptType);
- }
- private IDictionary<string, Object> getAppConfig()
- {
- IDictionary<string, Object> appConfig = null;
- AllAppConfig.TryGetValue(topClient.appKey, out appConfig);
- return appConfig;
- }
- /// <summary>
- /// 获取压缩长度
- /// </summary>
- /// <returns></returns>
- public int GetCompressLen()
- {
- IDictionary<string, Object> appConfig = getAppConfig();
- if (appConfig != null)
- {
- object compressLen = null;
- appConfig.TryGetValue(ENCRYPT_INDEX_COMPRESS_LEN, out compressLen);
- if (compressLen != null)
- {
- return Convert.ToInt32(compressLen);
- }
- }
- return DEFAULT_INDEX_ENCRYPT_COMPRESS_LEN;
- }
- /// <summary>
- /// 获取滑动窗口大小
- /// </summary>
- /// <returns></returns>
- public int GetSlideSize()
- {
- IDictionary<string, Object> appConfig = getAppConfig();
- if (appConfig != null)
- {
- object encryptSlideSize = null;
- appConfig.TryGetValue(ENCRYPT_SLIDE_SIZE, out encryptSlideSize);
- if (encryptSlideSize != null)
- {
- return Convert.ToInt32(encryptSlideSize);
- }
- }
- return DEFAULT_ENCRYPT_SLIDE_SIZE;
- }
- public SecurityCore(DefaultTopClient topClient, string randomNum, bool streetest)
- {
- this.streetest = streetest;
- this.topClient = topClient;
- this.randomNum = randomNum;
- // 初始化报表
- ApiReporter apiReporter = new ApiReporter();
- apiReporter.InitSecret(topClient);
- }
- public void SetRandomNum(string randomNum)
- {
- this.randomNum = randomNum;
- }
-
- /// <summary>
- /// 获取秘钥
- /// </summary>
- /// <param name="session"></param>
- /// <param name="secretVersion"></param>
- /// <returns></returns>
- public SecretContext GetSecret(string session, Nullable<Int64> secretVersion)
- {
- SecretContext secretContext = GetSecret(session, GenerateSecretKey(session, secretVersion));
- if (secretContext != null)
- {
- if (secretContext.IsValid())
- {
- return secretContext;
- }
- if (secretContext.IsMaxValid())
- {
- // 异步更新秘钥
- AsynUpdateSecret(session, secretVersion);
- return secretContext;
- }
- string cacheKey = GenerateSecretKey(session, secretVersion);
- lock (CacheLock)
- {
- if (session != null)
- {
- AppUserSecretCache.Remove(cacheKey);
- }
- else
- {
- AppSecretCache.Remove(cacheKey);
- }
- }
- // 同步调用获取秘钥
- return CallSecretApi(session, secretVersion);
- }
- else
- {
- // 同步调用获取秘钥
- return CallSecretApi(session, secretVersion);
- }
- }
- private string GenerateSecretKey(string session, Nullable<Int64> secretVersion)
- {
- if (session == null)
- {
- return this.topClient.appKey;
- }
- if (secretVersion == null)
- {
- return session;
- }
- return session + "_" + secretVersion;
- }
- /// <summary>
- /// 从本地获取秘钥信息
- /// </summary>
- /// <param name="session"></param>
- /// <param name="cacheKey"></param>
- /// <returns></returns>
- private SecretContext GetSecret(string session, string cacheKey)
- {
- SecretContext secretContext;
- if (session != null)
- {
- AppUserSecretCache.TryGetValue(cacheKey, out secretContext);
- }
- else
- {
- AppSecretCache.TryGetValue(cacheKey, out secretContext);
- }
- return secretContext;
- }
- /// <summary>
- /// 调用获取秘钥api
- /// </summary>
- /// <param name="session"></param>
- /// <param name="secretVersion"></param>
- /// <returns></returns>
- private SecretContext CallSecretApi(string session, Nullable<Int64> secretVersion)
- {
- // 获取伪随机码
- if (string.IsNullOrEmpty(randomNum))
- {
- throw new ArgumentException("randomNum can`t be empty");
- }
- TopSecretGetRequest request = new TopSecretGetRequest();
- request.RandomNum = randomNum;
- request.SecretVersion = secretVersion;
- if (streetest)
- {
- request.AddOtherParameter("tb_eagleeyex_t", "1");
- }
- TopSecretGetResponse response;
- if (session != null && session.StartsWith(UNDERLINE))
- {
- string customerUserId = session.Substring(1);
- if (!StringUtil.IsDigits(customerUserId))
- {
- throw new ArgumentException("session invalid");
- }
- request.CustomerUserId = Convert.ToInt64(customerUserId);
- response = topClient.Execute(request, null);
- }
- else
- {
- response = topClient.Execute(request, session);
- }
- if (!response.IsError)
- {
- IDictionary<string, Object> appConfig = null;
- if (!string.IsNullOrEmpty(response.AppConfig))
- {
- appConfig = (IDictionary<string, Object>)TopUtils.JsonToObject(response.AppConfig);
- putAppConfig(appConfig);
- }
- SecretContext secretContext = new SecretContext();
- if (response.Secret != null)
- {
- long currentTime = TopUtils.GetCurrentTimeMillis();
- secretContext.InvalidTime = currentTime + (response.Interval * 1000);
- secretContext.MaxInvalidTime = (currentTime + (response.MaxInterval * 1000));
- secretContext.Secret = Convert.FromBase64String(response.Secret);
- secretContext.SecretVersion = response.SecretVersion;
- }
- else
- {
- if (appConfig != null)
- {
- object publishStatus = null;
- appConfig.TryGetValue(PUBLISH_STATUS, out publishStatus);
- if (BETA_STATUS.Equals(publishStatus))
- {
- // 设置空缓存
- SetNullCache(secretContext);
- }
- }
- }
-
- PutToCache(session, secretVersion, secretContext);
- return secretContext;
- }
- else
- {
- // 查找不到历史秘钥
- if ("20005".Equals(response.SubErrCode))
- {
- SecretContext secretContext = new SecretContext();
- // 设置空缓存
- SetNullCache(secretContext);
- PutToCache(session, secretVersion, secretContext);
- return secretContext;
- }
- throw new SecretException(response.ErrCode, response.ErrMsg, response.SubErrCode, response.SubErrMsg);
- }
- }
- private void putAppConfig(IDictionary<string, Object> appConfig)
- {
- lock (AppLock)
- {
- if (!AllAppConfig.ContainsKey(topClient.appKey))
- {
- AllAppConfig.Add(topClient.appKey, appConfig);
- }
- }
- }
- private void PutToCache(string session, Nullable<Int64> secretVersion, SecretContext secretContext)
- {
- string cacheKey = GenerateSecretKey(session, secretVersion);
- lock (CacheLock)
- {
- if (session != null)
- {
- if (AppUserSecretCache.ContainsKey(cacheKey))
- {
- AppUserSecretCache[cacheKey] = secretContext;
- }
- else
- {
- AppUserSecretCache.Add(cacheKey, secretContext);
- }
- }
- else
- {
- if (AppSecretCache.ContainsKey(cacheKey))
- {
- AppSecretCache[cacheKey] = secretContext;
- }
- else
- {
- AppSecretCache.Add(cacheKey, secretContext);
- }
- }
- }
- }
- /// <summary>
- /// 设置空缓存
- /// </summary>
- /// <param name="secretContext"></param>
- private void SetNullCache(SecretContext secretContext)
- {
- long currentTime = TopUtils.GetCurrentTimeMillis();
- secretContext.InvalidTime = currentTime + (DEFAULT_INTERVAL * 1000);
- secretContext.MaxInvalidTime = currentTime + (DEFAULT_MAX_INTERVAL * 1000);
- }
- /// <summary>
- /// 异步更新秘钥
- /// </summary>
- /// <param name="session"></param>
- /// <param name="secretVersion"></param>
- private void AsynUpdateSecret(string session, Nullable<Int64> secretVersion)
- {
- string cacheKey = GenerateSecretKey(session, secretVersion);
- lock (AsynQueueKeyLock)
- {
- // 不需要重复提交秘钥请求
- if (asynQueueKey.ContainsKey(cacheKey))
- {
- return;
- }
- SecretContext secretContext = GetSecret(session, GenerateSecretKey(session, secretVersion));
- if (secretContext != null && secretContext.IsValid())
- {
- return;
- }
- asynQueueKey.Add(cacheKey, EmptyObject);
- }
- WaitCallback secretApiCallback = (state) =>
- {
- try
- {
- CallSecretApi(session, secretVersion);
- }
- catch (Exception e)
- {
- Log.Error(string.Format("asyn update secret error: {0}", e.Message));
- }
- finally
- {
- lock (AsynQueueKeyLock)
- {
- asynQueueKey.Remove(cacheKey);
- }
- }
- };
- try
- {
- ThreadPool.QueueUserWorkItem(secretApiCallback);
- }
- catch (Exception e)
- {
- lock (AsynQueueKeyLock)
- {
- asynQueueKey.Remove(cacheKey);
- }
- Log.Error(string.Format("add QueueUserWorkItem error: {0}", e.Message));
- }
-
- }
- }
- }
|