using Bowin.Common.Cache; using Bowin.Common.Encoder.DES; using Bowin.Common.Utility; using Microsoft.AspNetCore.Mvc.Filters; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Bowin.Common.ServiceToken.ApiIdentity { /// /// Header:{ auth-key: 密文(系统ID|访问时间(MMyyyyddmmHHss)), auth-system: 系统ID明文 } /// public class ApiIdentityAttribute : ActionFilterAttribute { public List ScopeList { get; set; } public ApiIdentityAttribute(params string[] scopes) { ScopeList = scopes.ToList(); } public override void OnActionExecuting(ActionExecutingContext context) { if (!ApiIdentityHelper.IsStarted) { return; } var systemService = (ISystemService)HttpHelper.GetService(ApiIdentityHelper.SystemServiceType); var systemList = systemService.GetSystemList(); var systemID = context.HttpContext.Request.Headers["auth-system"].ToString(); var secret = systemList.Where(x => x.SystemID == systemID).FirstOrDefault()?.Secret; if (string.IsNullOrEmpty(secret)) { throw new ServiceException(-1, "无效的auth-system"); } var des = new DesAccessor(); var key = Encoding.UTF8.GetBytes(secret).Take(8).ToArray(); var iv = key; var encodedText = context.HttpContext.Request.Headers["auth-key"].ToString(); var decodedString = des.Decrypt(encodedText, key, iv); var spliteData = decodedString.Split('|', StringSplitOptions.RemoveEmptyEntries); DateTime visitTime; if (spliteData.Length != 2 || spliteData[0] != systemID || !DateTime.TryParseExact(spliteData[1], "MMyyyyddmmHHss", null, System.Globalization.DateTimeStyles.None, out visitTime)) { throw new ServiceException(-1, "无效auth-key"); } var passTime = Math.Abs(DateTime.Now.Subtract(visitTime).TotalMinutes); if (passTime > 5) { throw new ServiceException(-1, "auth-key访问超时,请重新生成auth-key"); } var scopeList = systemService.GetScopeList(systemID); if (scopeList.Intersect(ScopeList).Count() == 0) { throw new ServiceException(-2, "未授权的操作。"); } ///考虑如何处理频繁访问,暂时想到是每一次调用接口时记录缓存,一分钟后缓存消失,这时候才可以再次访问,但需要考虑是不是所有将来的接口都需要有这个限制; ///另一个方式就是直接记录日志,访问太频繁线下找对方追责 } } }