Files
zszq-trs/YLErpWeb/App/Auth/MyAuthorizeHelper.cs
T
2024-05-09 14:06:26 +08:00

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;
}
}
}
}