138 lines
4.4 KiB
C#
138 lines
4.4 KiB
C#
using System.Reflection;
|
|
|
|
namespace YLErp.Web.App.Auth
|
|
{
|
|
static class MyAuthorizeHelper
|
|
{
|
|
const string ControllerSuffix = "Controller";
|
|
|
|
static readonly List<Type> _ignoreList;
|
|
static readonly HashSet<string> _noAttrSet;
|
|
static readonly Dictionary<string, MyAuthorizeAttribute> _attrMap;
|
|
|
|
static MyAuthorizeHelper()
|
|
{
|
|
_ignoreList = new List<Type>(10);
|
|
_noAttrSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
_attrMap = new Dictionary<string, MyAuthorizeAttribute>(StringComparer.OrdinalIgnoreCase);
|
|
|
|
var baseContollerType = typeof(BaseController);
|
|
var types = baseContollerType.Assembly.GetTypes();
|
|
var baseActionType = typeof(ActionResult);
|
|
|
|
foreach (var t in types)
|
|
{
|
|
if (baseContollerType == t || !baseContollerType.IsAssignableFrom(t) || !t.Name.EndsWith(ControllerSuffix, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (t.CustomAttributes.OfType<MyAuthorizeIgnoreAttribute>() != null)
|
|
{
|
|
_ignoreList.Add(t);
|
|
}
|
|
|
|
var controllerName = t.Name.Substring(0, t.Name.Length - ControllerSuffix.Length);
|
|
|
|
var methods = t.GetMethods(BindingFlags.Public | BindingFlags.Instance);
|
|
|
|
foreach (var m in methods)
|
|
{
|
|
var path = $"/{controllerName}/{m.Name}";
|
|
var attr = m.GetCustomAttribute<MyAuthorizeAttribute>();
|
|
|
|
if (attr != null)
|
|
{
|
|
_attrMap[path] = attr;
|
|
}
|
|
else if (baseActionType.IsAssignableFrom(m.ReturnType))
|
|
{
|
|
_noAttrSet.Add(path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static bool CanIgnore(Type controllerType)
|
|
{
|
|
return _ignoreList.Contains(controllerType);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
// 根据referer来关联权限,暂时不能解决特定请求伪造
|
|
//-----------------------------------------------
|
|
|
|
public static bool HasRight(UserInfo userInfo, bool isAjax, string requestPath, string refererPath)
|
|
{
|
|
if (refererPath == "/")
|
|
{
|
|
return true;
|
|
}
|
|
|
|
TrimPathId(ref refererPath, out var canTryAppendIndex);
|
|
|
|
var cacheKey = userInfo.UserId + "_myauth_" + refererPath;
|
|
|
|
var cache = Server.CacheProvider.Get(cacheKey);
|
|
|
|
if (cache != null)
|
|
{
|
|
return cache?.ToString() == "1";
|
|
}
|
|
|
|
var hasRight = InnerHasRight(userInfo, isAjax, requestPath, refererPath, cacheKey);
|
|
|
|
if (hasRight == null && canTryAppendIndex)
|
|
{
|
|
hasRight = InnerHasRight(userInfo, isAjax, requestPath, refererPath + "/index", cacheKey);
|
|
}
|
|
|
|
if (hasRight.HasValue)
|
|
{
|
|
return hasRight.Value;
|
|
}
|
|
|
|
return _noAttrSet.Contains(refererPath);
|
|
}
|
|
|
|
private static bool? InnerHasRight(UserInfo userInfo, bool isAjax, string requestPath, string refererPath, string cacheKey)
|
|
{
|
|
if (_attrMap.TryGetValue(refererPath, out var attr))
|
|
{
|
|
if (!isAjax)
|
|
{
|
|
TrimPathId(ref requestPath, out _);
|
|
_attrMap[requestPath] = attr;
|
|
}
|
|
|
|
var hasRight = attr.HasRight(userInfo);
|
|
|
|
Server.CacheProvider.Set(cacheKey, hasRight ? "1" : "0", TimeSpan.FromMinutes(1));
|
|
|
|
return hasRight;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
//删除第三个斜杠后的路径
|
|
private static void TrimPathId(ref string path, out bool canTryAppendIndex)
|
|
{
|
|
canTryAppendIndex = false;
|
|
var index = path.IndexOf('/', 1);
|
|
if (index > 0)
|
|
{
|
|
index = path.IndexOf('/', index + 1);
|
|
if (index > 0)
|
|
{
|
|
path = path.Substring(0, index);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
canTryAppendIndex = true;
|
|
}
|
|
}
|
|
}
|
|
}
|