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, "未授权的操作。");
}
///考虑如何处理频繁访问,暂时想到是每一次调用接口时记录缓存,一分钟后缓存消失,这时候才可以再次访问,但需要考虑是不是所有将来的接口都需要有这个限制;
///另一个方式就是直接记录日志,访问太频繁线下找对方追责
}
}
}