关联菜单与功能权限

访问权限
当所有权限关系关联上后,用户访问系统时,需要对其所有操作进行拦截与实时的权限判断,我们注册一个全局的GlobalAuthorizeAttribute,其主要拦截所有已经标识PermissionAttribute的action,查询该用户所关联所有角色的权限是否满足允许通过。
我的实现有个细节,给判断用户IsSuper==true,也就是超级管理员,如果是超级管理员则绕过所有判断,可能有人会问为什么不在角色添加一个名叫超级管理员进行判断,因为名称是不可控的,在代码逻辑里并不知道用户起的所谓的超级管理员,就是我们需要绕过验证的超级管理员,假如他叫无敌管理员呢?
1 /// <summary>
2 /// 全局的访问权限控制
3 /// </summary>
4 public class GlobalAuthorizeAttribute : System.Attribute, IAuthorizationFilter
5 {
6 #region 初始化
7 private string _currentUrl;
8 private string _unauthorizedMessage;
9 private readonly List<string> _noCheckPage = new List<string> { "home/index", "home/indexpage", "/" };
10
11 private readonly AdministratorService _administratorService;
12 private readonly MenuService _menuService;
13
14 public GlobalAuthorizeAttribute(AdministratorService administratorService, MenuService menuService)
15 {
16 _administratorService = administratorService;
17 _menuService = menuService;
18 }
19 #endregion
20
21 public void OnAuthorization(AuthorizationFilterContext context)
22 {
23 context.ThrowIfNull();
24
25 _currentUrl = PermissionUtil.CurrentUrl(context.HttpContext);
26
27 //不需要验证登录的直接跳过
28 if (context.Filters.Count(a => a is AllowAnonymousFilter) > 0)
29 return;
30
31 var user = GetCurrentUser(context);
32 if (user == null)
33 {
34 if (_noCheckPage.Contains(_currentUrl))
35 return;
36
37 _unauthorizedMessage = "登录失效";
38
39 if (context.HttpContext.Request.IsAjax())
40 NoUserResult(context);
41 else
42 LogoutResult(context);
43 return;
44 }
45
46 //超级管理员跳过
47 if (user.IsSuper)
48 return;
49
50 //账号状态判断
51 var administrator = _administratorService.GetById(user.UserId);
52 if (administrator != null && administrator.Status != EAdministratorStatus.Normal)
53 {
54 if (_noCheckPage.Contains(_currentUrl))
55 return;
56
57 _unauthorizedMessage = "亲~您的账号已被停用,如有需要请您联系系统管理员";
58
59 if (context.HttpContext.Request.IsAjax())
60 AjaxResult(context);
61 else
62 AuthResult(context, 403, GoErrorPage(true));
63
64 return;
65 }
66
67 if (_noCheckPage.Contains(_currentUrl))
68 return;
69
70 var userUrl = _administratorService.GetUserCanPassUrl(user.UserId);
71
72 // 判断菜单访问权限与菜单访问权限
73 if (IsMenuPass(userUrl) && IsActionPass(userUrl))
74 return;
75
76 if (context.HttpContext.Request.IsAjax())
77 AuthResult(context, 200, GetJsonResult());
78 else
79 AuthResult(context, 403, GoErrorPage());
80 }
81 }
功能权限
在权限验证通过后,返回view之前,还是利用了Filter进行一个实时的权限查询,主要把该用户所拥有功能权限值查询出来通过ViewData["PermCodes"]传到页面,然后通过razor进行按钮的渲染判断。
然而我在项目中封装了大部分常用的LayUI控件,主要利用.Net Core的TagHelper进行了封装,TagHelper内部与ViewData["PermCodes"]进行判断是否输出HTML。