0 Asp.Net Core 項目實戰之權限管理系統(0) 無中生有css
1 Asp.Net Core 項目實戰之權限管理系統(1) 使用AdminLTE搭建前端html
2 Asp.Net Core 項目實戰之權限管理系統(2) 功能及實體設計前端
3 Asp.Net Core 項目實戰之權限管理系統(3) 經過EntityFramework Core使用PostgreSQLjquery
4 Asp.Net Core 項目實戰之權限管理系統(4) 依賴注入、倉儲、服務的多項目分層實現git
5 Asp.Net Core 項目實戰之權限管理系統(5) 用戶登陸github
6 Asp.Net Core 項目實戰之權限管理系統(6) 功能管理sql
7 Asp.Net Core 項目實戰之權限管理系統(7) 組織機構、角色、用戶權限數據庫
8 Asp.Net Core 項目實戰之權限管理系統(8) 功能菜單的動態加載json
github源碼地址bootstrap
TagHelper是Asp.Net Core中提供的全新的服務端代碼參與建立和渲染 HTML 元素的方法,TagHelpers 在 Razor視圖中減小或避免了 HTML 和 C# 之間的顯示轉換,它具備如下特色:
Razor 標記使用 Tag Helpers 看起來更像標準的 HTML。熟悉 HTML/CSS/JavaScript 的前端設計師在沒有學習 C# Razor 語法的狀況下可以編輯 Razor 。
經過Microsoft.AspNetCore.Razor.Tools提供智能感知和智能提醒,大大提升編碼效率。
TagHelper的使用通常放在「視圖導入頁」中,視圖導入頁中還會放置咱們會用到的服務端引用。
在Fonour.MVC項目中,右鍵Views文件夾,添加新項,選擇MVC視圖導入頁,添加一個默認名稱爲 「_ViewImports.cshtml」的視圖導入頁。
修改視圖導入頁的內容以下:
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Microsoft.AspNetCore.Razor.Tools可以提供TagHelper的智能感知提示和代碼加粗高亮顯示。
最終在project.json文件中的dependencies及tools配置節中會出現Microsoft.AspNetCore.Razor.Tools
"dependencies": { "Microsoft.NETCore.App": "1.0.1", "Microsoft.AspNetCore.Diagnostics": "1.0.0", "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", "Microsoft.AspNetCore.Server.Kestrel": "1.0.1", "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.AspNetCore.Mvc": "1.0.1", "Microsoft.AspNetCore.StaticFiles": "1.0.0", "Microsoft.Extensions.Configuration": "1.0.0", "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0", "Microsoft.Extensions.Configuration.Json": "1.0.0", "Fonour.Application": "1.0.0-*", "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final", "Microsoft.AspNetCore.Session": "1.0.0", "Fonour.Utility": "1.0.0-*" }, "tools": { "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final", "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final" },
打開Login/Index.cshtml文件,隨意輸入一個label標籤,發現已經能夠出現asp-for的TagHelper提示。
一個完整的使用TagHelper的label標籤建立完成後,會以加粗高亮的方式顯示。你本身能夠根據喜愛在 工具 > 選項 > 環境 > 字體和顏色 中自定義TagHelperElement的字體和顏色。更多關於TagHelper的使用,能夠找專門的文章進行了解。
注意:若是安裝完Microsoft.AspNetCore.Razor.Tools時不會出現智能提示,重啓一下Visual Studio便可。
咱們須要在用戶登陸之後記錄當前登陸用戶的會話狀態,ASP.NET Core 發佈了一個關於會話的程序包,裏面提供了用於管理會話狀態的中間件。你能夠在 project.json 中加入對Microsoft.AspNetCore.Session的引用來安裝這個程序包。
0 Microsoft.AspNetCore.Session依賴項添加
經過NuGet程序包管理器、控制檯、或直接修改project.json文件,添加對Microsoft.AspNetCore.Session中間件的引用。
1 修改Startup.cs文件的的ConfigureServices方法,增長Session服務註冊
public void ConfigureServices(IServiceCollection services) { //獲取數據庫鏈接字符串 var sqlConnectionString = Configuration.GetConnectionString("Default"); //添加數據上下文 services.AddDbContext<FonourDbContext>(options =>options.UseNpgsql(sqlConnectionString)); services.AddScoped<IUserRepository, UserRepository>(); services.AddScoped<IUserAppService, UserAppService>(); services.AddMvc(); //Session服務 services.AddSession(); }
2 修改Startup.cs文件的的Configure方法,請求管道中啓用Session
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(); if (env.IsDevelopment()) { //開發環境異常處理 app.UseDeveloperExceptionPage(); } else { //生產環境異常處理 app.UseExceptionHandler("/Shared/Error"); } //使用靜態文件 app.UseStaticFiles(); //Session app.UseSession(); //使用Mvc,設置默認路由爲系統登陸 app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Login}/{action=Index}/{id?}"); }); SeedData.Initialize(app.ApplicationServices); //初始化數據 }
Asp.Net Core中Session的Set方法必須提供一個Byte[]數組來存放對象,此外爲了方便使用,還提供了SetString和SetInt32擴展方法。
void Set(string key, byte[] value);
咱們在Fonour.Utility項目中增長一個Byte數組與對象互相轉換的幫助類ByteConVertHelper。
public class ByteConvertHelper { /// <summary> /// 將對象轉換爲byte數組 /// </summary> /// <param name="obj">被轉換對象</param> /// <returns>轉換後byte數組</returns> public static byte[] Object2Bytes(object obj) { string json = JsonConvert.SerializeObject(obj); byte[] serializedResult = System.Text.Encoding.UTF8.GetBytes(json); return serializedResult; } /// <summary> /// 將byte數組轉換成對象 /// </summary> /// <param name="buff">被轉換byte數組</param> /// <returns>轉換完成後的對象</returns> public static object Bytes2Object(byte[] buff) { string json = System.Text.Encoding.UTF8.GetString(buff); return JsonConvert.DeserializeObject<object>(json); } /// <summary> /// 將byte數組轉換成對象 /// </summary> /// <param name="buff">被轉換byte數組</param> /// <returns>轉換完成後的對象</returns> public static T Bytes2Object<T>(byte[] buff) { string json = System.Text.Encoding.UTF8.GetString(buff); return JsonConvert.DeserializeObject<T>(json); } }
有了以上準備工做,咱們能夠開始正式實現用戶登陸功能了。
在Fonour.MVC項目中增長一個Models文件夾,用於存放前端交互使用的Model類,在Models文件夾下新建一個LoginModel類,並經過DataAnnotations特性指定屬性的驗證信息。
public class LoginModel { [Required(ErrorMessage = "用戶名不能爲空。")] public string UserName { get; set; } [Required(ErrorMessage = "密碼不能爲空。")] [DataType(DataType.Password)] public string Password { get; set; } public bool RememberMe { get; set; } }
在視圖導入頁_ViewImport.cshtml中增長對模型的引用
@using Fonour.MVC.Models
使用TagHelper修改Login/Index.cshtml爲以下內容
@{ Layout = null; } @model LoginModel <!DOCTYPE html> <html> <head> <title>系統登陸</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css"> <link rel="stylesheet" href="~/lib/font-awesome/css/font-awesome.css"> <link rel="stylesheet" href="~/css/AdminLTE.css"> <link rel="stylesheet" href="~/lib/iCheck/skins/square/blue.css"> </head> <body class="hold-transition login-page"> <div class="login-box"> <div class="login-logo"> <a href="http://fonour.cnblogs.com" target="_blank"><b>Fonour</b></a> </div> <!-- /.login-logo --> <div class="login-box-body"> <p class="login-box-msg">權限管理系統</p> <div asp-validation-summary="All" class="text-danger"></div> <form asp-controller="Login" asp-action="Index" method="post"> <div class="form-group has-feedback"> <input asp-for="UserName" type="text" class="form-control" placeholder="用戶名"> <span class="glyphicon glyphicon-user form-control-feedback"></span> <span asp-validation-for="UserName" class="text-danger"></span> </div> <div class="form-group has-feedback"> <input asp-for="Password" type="password" class="form-control" placeholder="密碼"> <span class="glyphicon glyphicon-lock form-control-feedback"></span> </div> <div class="row"> <div class="col-xs-8"> <div class="checkbox icheck"> <label> <input asp-for="RememberMe" type="checkbox"> 記住我 </label> </div> </div> <!-- /.col --> <div class="col-xs-4"> <button type="submit" class="btn btn-primary btn-block btn-flat">登陸</button> </div> <!-- /.col --> </div> </form> </div> <!-- /.login-box-body --> </div> <!-- /.login-box --> <script src="~/lib/jquery/dist/jquery.js"></script> <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script> <script src="~/lib/iCheck/icheck.js"></script> <script> $(function () { $('input').iCheck({ checkboxClass: 'icheckbox_square-blue', radioClass: 'iradio_square-blue', increaseArea: '20%' // optional }); }); </script> </body> </html>
關鍵說明
修改LoginController,增長用戶登陸對應的控制器方法。
[HttpPost] public IActionResult Index(LoginModel model) { if (ModelState.IsValid) { //檢查用戶信息 var user = _userAppService.CheckUser(model.UserName, model.Password); if (user != null) { //記錄Session HttpContext.Session.Set("CurrentUser", ByteConvertHelper.Object2Bytes(user)); //跳轉到系統首頁 return RedirectToAction("Index", "Home"); } ModelState.AddModelError("", "用戶名或密碼錯誤。"); return View(); } return View(model); }
到此咱們基本上就完成了用戶登陸的邏輯,以及服務器端的登陸驗證。當輸入用戶名、密碼信息不符合條件時,會給出詳細的錯誤提示。
上面咱們只作了服務端驗證,並且錯誤信息的提示並非很美觀,咱們能夠根據須要修改樣式對錯誤提示信息進行美化。我這裏直接使用Layer.js這個前端庫。
驗證信息美化
修改用戶登陸控制器方法,有錯誤信息時只返回第一條錯誤信息,客戶端自行處理錯誤信息。
[HttpPost] public IActionResult Index(LoginModel model) { if (ModelState.IsValid) { //檢查用戶信息 var user = _userAppService.CheckUser(model.UserName, model.Password); if (user != null) { //記錄Session HttpContext.Session.Set("CurrentUser", ByteConvertHelper.Object2Bytes(user)); //跳轉到系統首頁 return RedirectToAction("Index", "Home"); } ViewBag.ErrorInfo = "用戶名或密碼錯誤。"; return View(); } ViewBag.ErrorInfo = ModelState.Values.First().Errors[0].ErrorMessage; return View(model); }
經過Bower程序包管理器添加對Layer的引用,在Login/Index.cshtml中增長對layer.js的引用
<script src="~/lib/layer/layer.js"></script>
增長一個隱藏的input標籤用於記錄錯誤信息。
<input id="errorInfo" type="hidden" value="@ViewBag.ErrorInfo" />
初始化完成後增長對錯誤信息的處理。
<script> $(function () { $('input').iCheck({ checkboxClass: 'icheckbox_square-blue', radioClass: 'iradio_square-blue', increaseArea: '20%' // optional }); //顯示服務端驗證的錯誤信息 if ($("#errorInfo").val()) { layer.tips($("#errorInfo").val(), "#btnLogin"); }; }); </script>
此時運行程序,服務器端錯誤信息的展現樣式已經比較美觀了。
記住我
記住我,主要是記錄輸入的用戶名及密碼,經過cookie保存,首先經過Bower前端包管理器增長Jquery.Cookie的引用。在Login/Index.cshtml中增長對jquery.cookie.js的引用。
<script src="~/lib/jquery.cookie/src/jquery.cookie.js"></script>
增長form的onsubmit方法
<form asp-controller="Login" asp-action="Index" method="post" onsubmit="onSubmit()">
<script> $(function () { $('input').iCheck({ checkboxClass: 'icheckbox_square-blue', radioClass: 'iradio_square-blue', increaseArea: '20%' // optional }); //顯示服務端驗證的錯誤信息 if ($("#errorInfo").val()) { layer.tips($("#errorInfo").val(), "#btnLogin"); }; //判斷以前是否有設置cookie,若是有,則設置【記住我】選擇框 if ($.cookie("fonour_userName") != undefined) { $("#RememberMe").attr("checked", "checked"); } else { $("#RememberMe").removeAttr("checked"); } //讀取cookie if ($("#RememberMe:checked").length > 0) { $("#UserName").val($.cookie("fonour_userName")); $("#Password").val($.cookie("fonour_password")); } }); //根據是否勾選記住我記錄或清除cookie function onSubmit() { if ($("#RememberMe:checked").length > 0) {//設置cookie $.cookie("fonour_userName", $("#UserName").val()); $.cookie("fonour_password", $("#Password").val()); } else {//清除cookie $.removeCookie("fonour_userName"); $.removeCookie("fonour_password"); } }; </script>
輸入用戶名密碼登錄後,再次回到登陸界面,會發現用戶名及密碼已經填充。
一個最基本的控制器攔截,就是當咱們直接經過在地址欄輸入訪問路由地址時,首先應該判斷用戶是否已經登陸,若是沒有登陸應該實現跳轉到登陸頁面。大體思路是經過重寫Controller的OnActionExecuting方法,在OnActionExecuting方法中判斷用戶是否登陸並實現跳轉。
在Fonour.MVC中右鍵Controllers文件夾,添加一個名稱爲FonourControllerBase的控制器基類,內容以下。
public abstract class FonourControllerBase : Controller { public override void OnActionExecuting(ActionExecutingContext filterContext) { byte[] result; filterContext.HttpContext.Session.TryGetValue("CurrentUser",out result); if (result == null) { filterContext.Result = new RedirectResult("/Login/Index"); return; } base.OnActionExecuting(filterContext); } }
須要進行登錄驗證的控制器,修改成從FonourControllerBase繼承,這裏咱們修改HomeController
public class HomeController : FonourControllerBase
啓動程序,在未登陸狀況下,經過地址欄直接訪問/Home/Index,會發現已經自動跳轉到系統登陸界面。
本次主要介紹了TagHelper的簡單實用;Asp.Net Core中的Session中間件的使用;以及系統登陸的服務端驗證,並對控制器的訪問進行了統一的是否登陸驗證攔截。下一節主要進行功能管理的實現。