一、前言 畢業後入職現在的公司快有一個月了,公司主要的產品用的是C/S架構,再加上自己現在還在學習維護很老的delphi項目,還是有很多不情願的。之前實習時主要是做.NET的B/S架構的項目,主要還是用的那種傳統的開發模式,只有一個項目用到了Web API,自己負責後端的介面功能實現。既然現在沒辦法 ...
一、前言
畢業後入職現在的公司快有一個月了,公司主要的產品用的是C/S架構,再加上自己現在還在學習維護很老的delphi項目,還是有很多不情願的。之前實習時主要是做.NET的B/S架構的項目,主要還是用的那種傳統的開發模式,只有一個項目用到了Web API,自己負責後端的介面功能實現。既然現在沒辦法改變現狀,那就先改變自己吧。定了個計劃,下班後慢慢的開始學習ASP.NET Core Web API和Vue,準備從前端到後端自己寫一個小項目玩玩,畢竟代碼這個東西,時間長了是會忘的。
嗯,有點扯遠了。這個MVC項目是我的畢業設計,雖然寫的比較爛,而且當時為了趕緊寫完,代碼的冗餘程度有點高,但還是希望能給一些準備入門ASP.NET Core MVC的童鞋提供些借鑒吧。代碼我放到Github上了,源碼地址https://github.com/Lanesra712/Danvic.PSU,歡迎大神們拍磚,指出不足處。
二、項目介紹
畢業論文的課題是一個大學生的一個報名系統,主要是為了完成大學生報名過程中的一些數據維護,當然最後因為實在來不及了,好多都沒做。。。項目主要使用到的相關技術如下所示:
- 項目框架:ASP.NET Core 2.0 MVC
- ORM:Entity Framework Core(使用Code First)
- 資料庫引擎:MySQL SERVER 5.7
- 許可權驗證:基於策略的許可權驗證(Policy-Based Authorization)
- 前端框架:AdminLte(一個基於Bootstrap的開源前端UI)
- 表格控制項:Jquery Datatables
- 數據可視化組件:Echarts
- 日誌記錄:nlog
三、設計與實現介紹
項目架構採用的是多層架構,通過拆分不同的功能領域,實現各個功能間的相對獨立,項目在VS中搭建完成後如下圖所示。
01_Entity:實體層,包含PSU.Entity這一個系統組件,用於存儲資料庫中表所對應的C#對象實體。
02_Infrastructure:基礎架構層,包含PSU.EFCore、PSU.Utility兩個系統組件。PSU.EFCore類庫通過引用Entity Framework Core來完成對於資料庫的操作。PSU.Utility類庫中包含系統開發過程中可能用到的幫助類文件。
03_Logic:邏輯層,包含PSU.Domain、PSU.Repository兩個系統組件。PSU.Domain用於繼承每個領域的介面類庫(PSU.IService),實現領域介面中的功能。PSU.Repository用來實現PSU.Domain類庫中所包含的對於資料庫的操作。
04_Rule:規則層,包含PSU.IService、PSU.Model這兩個系統組件。PSU.IService為系統領域功能介面類庫,PSU.Model為視圖所對應的數據充血模型,對應MVC模式中的實體Model。
Controller.PSU:控制器層,.NET Core類庫,用來存放MVC模式中的各種控制器文件。
PSU.Site:表現層,ASP.NET Core MVC項目,項目主程式。
系統許可權驗證設計:
整個系統分為三種角色,分別為管理員、教職工、學生用戶,通過使用Area搭建每個角色的頁面,通過在Controller上添加Area特性,指定當前Controller屬於的角色。在創建用戶時,會指定用戶的角色欄位,當用戶登錄成功後,會根據用戶角色進行Claim的創建,通過自定義的AuthorizztionHandler來實現對於當前系統的角色許可權控制。
當用戶登錄成功後,會將當前的用戶信息賦值給一個靜態類(使用Session進行存儲),對於判斷用戶是否登錄,則是通過自定義一個控制器的基類,重寫OnActionExecuting方法來實現對於用戶是否登錄的判斷,實現代碼如下。
1 public class DanvicController : Controller 2 { 3 /// <summary> 4 /// 判斷用戶是否登錄 5 /// </summary> 6 /// <param name="filterContext"></param> 7 public override void OnActionExecuting(ActionExecutingContext filterContext) 8 { 9 if (CurrentUser.UserId == 0) 10 { 11 string path = filterContext.HttpContext.Request.Path; 12 filterContext.Result = new RedirectResult($"/Secret/Login?ReturnUrl={path}"); 13 return; 14 } 15 base.OnActionExecuting(filterContext); 16 } 17 }自定義控制器基類
1 public static class CurrentUser 2 { 3 #region Initialize 4 5 private static IHttpContextAccessor _httpContextAccessor; 6 7 private static ISession _session => _httpContextAccessor.HttpContext.Session; 8 9 public static void Configure(IHttpContextAccessor httpContextAccessor) 10 { 11 _httpContextAccessor = httpContextAccessor; 12 } 13 14 #endregion 15 16 #region Attribute 17 18 /// <summary> 19 /// 用戶主鍵 20 /// </summary> 21 public static string UserOID 22 { 23 get => _session == null ? "" : _session.GetString("CurrentUser_UserOID"); 24 set => _session.SetString("CurrentUser_UserOID", !string.IsNullOrEmpty(value) ? value : ""); 25 } 26 27 /// <summary> 28 ///用戶編號 29 /// </summary> 30 public static long UserId 31 { 32 get => _session == null ? 0 : Convert.ToInt64(_session.GetString("CurrentUser_UserId")); 33 set => _session.SetString("CurrentUser_UserId", value != 0 ? value.ToString() : "0"); 34 } 35 36 /// <summary> 37 /// 用戶姓名 38 /// </summary> 39 public static string UserName 40 { 41 get => _session == null ? "" : _session.GetString("CurrentUser_UserName"); 42 set => _session.SetString("CurrentUser_UserName", !string.IsNullOrEmpty(value) ? value : ""); 43 } 44 45 /// <summary> 46 /// 用戶登錄賬戶 47 /// </summary> 48 public static string UserAccount 49 { 50 get => _session == null ? "" : _session.GetString("CurrentUser_UserAccount"); 51 set => _session.SetString("CurrentUser_UserAccount", !string.IsNullOrEmpty(value) ? value : ""); 52 } 53 54 /// <summary> 55 /// 用戶頭像地址 56 /// </summary> 57 public static string UserImage 58 { 59 get => _session == null ? "" : _session.GetString("CurrentUser_UserImage"); 60 set => _session.SetString("CurrentUser_UserImage", !string.IsNullOrEmpty(value) ? value : ""); 61 } 62 63 /// <summary> 64 /// 用戶角色 65 /// </summary> 66 public static string UserRole 67 { 68 get => _session == null ? "" : _session.GetString("CurrentUser_UserRole"); 69 set => _session.SetString("CurrentUser_UserRole", !string.IsNullOrEmpty(value) ? value : ""); 70 } 71 72 /// <summary> 73 /// 主頁地址 74 /// </summary> 75 public static string UserPage 76 { 77 get => _session == null ? "" : _session.GetString("CurrentUser_UserPage"); 78 set => _session.SetString("CurrentUser_UserPage", !string.IsNullOrEmpty(value) ? value : ""); 79 } 80 81 #endregion 82 }CurrentUser類
許可權驗證代碼如下截圖所示:
控制器示例圖:
基於策略的許可權驗證實現:
自定義驗證Claim:
四、總結
接下來我要開始學習ASP.NET Core Web API和Vue了,希望可以保持住,能夠不間斷的在博客上分享自己的學習經歷與見解。當學的差不多的時候,爭取把這個項目精簡,重構,讓自己在成為更好的自己的路途上前進一大步。
因為也是第一次使用ASP.NET Core MVC進行項目的開發,所以遇到了一些自己沒辦法解決的東西,很感謝博客園裡的各位大佬以及一些幫助我的大佬,正是因為有這麼多樂於分享的人在,才能更好的推動.NET Core在國內的生態發展,在寫畢業設計的過程中,參考了很多位博主的博文,真的是很感謝,致敬。
還是要推廣下自己的個人博客啊,點擊這裡,去看看我的博客啊~~~
項目實現圖如下。