using System.Reflection; namespace YLErp.Web.App.Auth { static class MyAuthorizeHelper { const string ControllerSuffix = "Controller"; static readonly List _ignoreList; static readonly HashSet _noAttrSet; static readonly Dictionary _attrMap; static MyAuthorizeHelper() { _ignoreList = new List(10); _noAttrSet = new HashSet(StringComparer.OrdinalIgnoreCase); _attrMap = new Dictionary(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() != 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(); 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; } } } }