日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

.NET Core微服务 权限系统+工作流(一)权限系统

發(fā)布時間:2024/4/15 windows 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET Core微服务 权限系统+工作流(一)权限系统 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、前言

實際上權(quán)限系統(tǒng)老早之前我就在一直開發(fā),大概在剛畢業(yè)沒多久就想一個人寫一個系統(tǒng),斷斷續(xù)續(xù)一直堅持到現(xiàn)在,畢竟自己親動手自寫的系統(tǒng)才有收獲,本篇僅介紹權(quán)限。

  小小系統(tǒng)上不了臺面,望各位大神勿噴。

二、系統(tǒng)介紹

目前采用的是.Net Core微服務(wù)的方式實現(xiàn),本文不討論具體的中間件主要是(ocelot + consul等),一直參考微軟的??eShopOnContainers?,進(jìn)行簡單的實現(xiàn),但是ORM是用的Dapper,并簡單進(jìn)行封裝? 傳送門 ,當(dāng)然自己也封裝了一些簡單的插件進(jìn)行復(fù)用:傳送門,如下:

三、權(quán)限系統(tǒng)

權(quán)限系統(tǒng)實現(xiàn)很簡單,權(quán)限的劃分我覺得可以分為三種:

1、菜單權(quán)限2、按鈕權(quán)限3、數(shù)據(jù)權(quán)限

簡單介紹下:1、菜單權(quán)限。表示用戶是否能夠訪問該頁面(角色掛鉤)

      2、按鈕權(quán)限。表示用戶是否能夠操作該頁面上的功能(角色掛鉤)

      3、數(shù)據(jù)權(quán)限。表示用戶訪問頁面時進(jìn)行數(shù)據(jù)篩選(該功能暫未實現(xiàn),這個要與具體的業(yè)務(wù)結(jié)合才能寫),與部門掛鉤,這個不太好理解,當(dāng)然一般的權(quán)限系統(tǒng)這個功能也不會做,舉個簡單例子,OA系統(tǒng)里面我查看我的工資條,我應(yīng)該只能看到我自己的數(shù)據(jù),但是我的部門經(jīng)理,他可以有權(quán)限看到該部門的全部數(shù)據(jù),這個就是數(shù)據(jù)權(quán)限。

為什么寫這個系統(tǒng)?

  之前待過好幾家公司,發(fā)現(xiàn)他們的系統(tǒng)都是對菜單進(jìn)行分配,當(dāng)然了,業(yè)務(wù)需求只要這個就當(dāng)我沒說,我只是覺得這樣做太不安全并且我覺得之前系統(tǒng)的實現(xiàn)方式可以進(jìn)行一些優(yōu)化,所以就一直寫到現(xiàn)在,可能代碼質(zhì)量不如哪些大神的優(yōu)秀,系統(tǒng)在我看來太小,就簡單搭了個框架實現(xiàn)。你過條小水溝,沒必要造條橋。

要使用該系統(tǒng)前提條件:前端:Sea.js和Vue,對于sea.js,在前端這塊感覺已經(jīng)沒多少人用了,但是這中CMD思想是不會被淘汰的,你看最近比較火的layerui也是的,對于Vues只是簡單的應(yīng)用,也就用到雙向綁定而已,開發(fā)復(fù)雜的頁面確實比較方便,但是簡單的頁面就得不償失了。

           后端:consul、rabbitmq ,具體怎么安裝不在描述

大概的用戶訪問流程描述如下:

用戶登錄? ?   =====》  獲取該用戶角色   ===》  通過角色獲取該角色對應(yīng)的權(quán)限?并集? ===>返回相應(yīng)數(shù)據(jù)

      sys_user_role      sys_role_resource

?

系統(tǒng)關(guān)系圖如下(MySQL):

?

具體功能實現(xiàn)請看代碼,這里不做闡述,菜單權(quán)限的分配通過角色表和菜單表的關(guān)聯(lián)表操作即可,但是按鈕的權(quán)限分配如何實現(xiàn)?我的實現(xiàn)方式是:把按鈕的操作也看成一種菜單的資源分配,只不過比較特殊,我這里不僅僅是對按鈕的顯示進(jìn)行控制,我做的比較絕,也對后臺方法訪問權(quán)限也做了控制,這樣比較安全,對于按鈕權(quán)限的控制,實際上是明確的,比方說,一個刪除按鈕,它只能對應(yīng)后臺的一個刪除方法,這個方法是明確的,對于頁面的按鈕的類型和個數(shù)是固定的,不然你沒辦法分配,基于這個前提,我對菜單的生成進(jìn)行代碼控制從而達(dá)到控制目的,因此,菜單和按鈕和在一起稱之為資源表 sys_resource 。具體的實現(xiàn)代碼也不是很復(fù)雜,一層一層判斷即可,權(quán)限過濾器如下:

1 public class PermissionAuthorizationRequirement : IAuthorizationRequirement 2 { 3 public UrlAndButtonType UrlAndButtonType { get; } 4 5 public PermissionAuthorizationRequirement(string url, ButtonType buttonType, bool isPage) 6 { 7 UrlAndButtonType = new UrlAndButtonType() 8 { 9 Url = url, 10 ButtonType = (byte)buttonType, 11 IsPage = isPage 12 }; 13 } 14 public PermissionAuthorizationRequirement(string url, byte buttonType, bool isPage) 15 { 16 UrlAndButtonType = new UrlAndButtonType() 17 { 18 Url = url, 19 ButtonType = buttonType, 20 IsPage = isPage 21 }; 22 } 23 } 24 /// <summary> 25 /// 權(quán)限過濾器 26 /// </summary> 27 [Authorize] 28 [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] 29 public sealed class PermissionAttribute : TypeFilterAttribute 30 { 31 /// <summary> 32 /// 構(gòu)造器 33 /// </summary> 34 /// <param name="url">地址</param> 35 /// <param name="buttonType">按鈕類型</param> 36 /// <param name="isPage">是否是頁面</param> 37 public PermissionAttribute(string url = default(string), ButtonType buttonType = ButtonType.View, bool isPage = true) : 38 base(typeof(RequiresPermissionAttributeExecutor)) 39 { 40 Arguments = new object[] { new PermissionAuthorizationRequirement(url, buttonType, isPage) }; 41 } 42 /// <summary> 43 /// 構(gòu)造器 44 /// </summary> 45 /// <param name="url">地址</param> 46 /// <param name="buttonType">按鈕類型</param> 47 /// <param name="isPage">是否是頁面</param> 48 public PermissionAttribute(string url, byte buttonType, bool isPage = true) : 49 base(typeof(RequiresPermissionAttributeExecutor)) 50 { 51 Arguments = new object[] { new PermissionAuthorizationRequirement(url, buttonType, isPage) }; 52 } 53 54 private class RequiresPermissionAttributeExecutor : Attribute, IAsyncResourceFilter 55 { 56 private IPermissionStorageContainer _permissionStorage; 57 private PermissionAuthorizationRequirement _requiredPermissions; 58 59 public RequiresPermissionAttributeExecutor( 60 IPermissionStorageContainer permissionStorage, PermissionAuthorizationRequirement requiredPermissions) 61 { 62 _permissionStorage = permissionStorage; 63 _requiredPermissions = requiredPermissions; 64 } 65 66 public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) 67 { 68 string menuUrl = _requiredPermissions.UrlAndButtonType.Url; 69 //判斷用戶權(quán)限 70 if (string.IsNullOrEmpty(menuUrl)) 71 { 72 //區(qū)域判斷 73 string area = context.RouteData.Values["area"].ToString(); 74 if (string.IsNullOrEmpty(area)) 75 { 76 menuUrl = "/" + context.RouteData.Values["controller"] + "/" + context.RouteData.Values["action"]; 77 } 78 else 79 { 80 menuUrl = "/" + area + "/" + context.RouteData.Values["controller"] + "/" + context.RouteData.Values["action"]; 81 } 82 } 83 menuUrl = menuUrl.Trim().ToLower(); 84 var dbpermission = await _permissionStorage.GetPermissionAsync(); 85 var menu = dbpermission.Menus.FirstOrDefault(m => m.MenuUrl != null && m.MenuUrl.Trim().ToLower() == menuUrl); 86 if (menu != null)//地址存在 87 { 88 if (_requiredPermissions.UrlAndButtonType.ButtonType == default(byte)) 89 { 90 await next(); 91 } 92 else 93 { 94 byte buttonType = (byte)_requiredPermissions.UrlAndButtonType.ButtonType; 95 if (menu.MenuButton.Select(m => m.ButtonType).Contains(buttonType))//擁有操作權(quán)限 96 { 97 await next(); 98 } 99 else 100 { 101 //沒有操作權(quán)限 102 if (_requiredPermissions.UrlAndButtonType.IsPage) 103 { 104 context.Result = new RedirectResult("/error/noauth"); 105 } 106 else 107 { 108 context.Result = new ContentResult() 109 { 110 Content = PermissionStatusCodes.Status2Unauthorized.ToString() 111 }; 112 } 113 await context.Result.ExecuteResultAsync(context); 114 } 115 } 116 } 117 else 118 { 119 //沒有操作權(quán)限 120 if (_requiredPermissions.UrlAndButtonType.IsPage) 121 { 122 context.Result = new RedirectResult("/error/noauth"); 123 } 124 else 125 { 126 context.Result = new ContentResult() 127 { 128 Content = PermissionStatusCodes.Status2Unauthorized.ToString() 129 }; 130 } 131 await context.Result.ExecuteResultAsync(context); 132 } 133 } 134 } 135 136 }

在對于的頁面添加過濾器即可,如下:

1 [HttpGet] 2 [Permission] 3 public async Task<IActionResult> Index(int pageIndex=1,int pageSize=10) 4 { 5 var res = await _messageService.GetPageAsync(pageIndex, pageSize); 6 return View(res); 7 } 8 [HttpGet] 9 [Permission("/Sys/Message/Index", ButtonType.View)] 10 public IActionResult Show() 11 { 12 return View(); 13 }

?系統(tǒng)界面展示圖:后臺模板是之前從網(wǎng)上找的并自己簡單改了一下,將就能看吧,實在不想花功夫在前端上面了@-^-@

運行步驟:1、確保數(shù)據(jù)庫mssystem和mssystemlog存在 github文檔中

     2、consul服務(wù)啟動,如下回車運行

     3、VS項目啟動

管理員登錄賬號wms,密碼:所有賬號密碼都是123

代碼地址:

https://github.com/wangmaosheng/MsSystem-BPM-ServiceAndWebApps

如果覺得有點作用的話,可以 start 下,后續(xù)會持續(xù)更新

轉(zhuǎn)載于:https://www.cnblogs.com/wms01/p/10903646.html

總結(jié)

以上是生活随笔為你收集整理的.NET Core微服务 权限系统+工作流(一)权限系统的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。