【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目 (16)源碼分享二:登錄功能以及UI、資料庫、倉儲源碼分享

来源:http://www.cnblogs.com/yuangang/archive/2016/08/20/5789748.html
-Advertisement-
Play Games

索引 【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目 目錄索引 前言 前面還沒有下載到UI和資料庫的,這裡再次給大家提供一下:百度網盤 提取碼:fuuv ,UI是參照H+,但是H+是收費授權的(¥998RMB),價格有點貴,所以 我們的 UI 跟H+ 雖然是一個風格,但 ...


索引

 

  

【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做項目 目錄索引

  

 

前言

  

  前面還沒有下載到UI和資料庫的,這裡再次給大家提供一下:百度網盤  提取碼:fuuv ,UI是參照H+,但是H+是收費授權的(¥998RMB),價格有點貴,所以 我們的 UI 跟H+ 雖然是一個風格,但是大家可以看到,CSS基本用的都是Bootstrap,JS 基本都是 最新的開源插件和自己重寫的,不存在版權問題。

 

  我們前一章已經重寫了我們的倉儲類,文章中介面都已列出,實現類也說的很明白,引入 uow 後,大家修改一下原先的提交,就可以。但是很多朋友 總感覺 不給你文件 是因為 有些東西沒有放給你,那麼 就再次給大家 下載一下 我的倉儲,大家可以對比一下,是不是博客中故意少些東西。修改後的倉儲:百度網盤 提取碼:qw64 

其實,只是想讓大家自己動手一下,修改方法很簡單,就是把我們之前的方法加上個條件: bool IsCommit=true,當我們只進行一項操作的時候,預設直接提交,當我們進行多項操作的時候,可以傳入false,不提交,然後通過uow 統一提交。大家可以看一下,使用的例子:

  

 

 

 

賣源碼?

 

  很多朋友都在牢騷,說博主終於還是商業化了...

 

  首先呢,到目前為止,我沒有賣一套源碼,如果你在我們的交流群里,你可以問問大家,很多私聊我買源碼的朋友,我都是跟他們說先按照博客園的文章自己做,學會才是目的,單純的源代碼是沒有任何意義的,博客園貼出的源碼跟我項目中源碼的唯一區別就是,我項目中的源碼沒有註釋,實在不行再來找我。

 

  第二呢,有些源碼出售網站驚現 果凍博客源碼... 這讓我很吃驚,首先是受寵若驚,巧合的是,有個源碼網站是我朋友的,要不是他發給我我還真不知道,我是不反對這種行為的,你學會了就是你的,賣或不賣是你的事,但是扒下來的代碼,都沒有經過測試,這麼多錯誤,都跑不起來,就拿來出售,是很不地道的。

 

  第三呢,我上面說過了,博客園貼出的源碼 跟我源碼的唯一區別就是,我項目中源碼是沒有這麼多註釋的。如果單純是分享源代碼,大可以放到GitHub上,難道一步一步貼出源代碼不就分享源碼,只有把完整的打個包發給每個人才叫分享源碼嗎?那博客園的意義是?博客園不是GitHub,兩個站的目的是不一樣的。對於同樣是新手的我來說,github上的純粹的源代碼,如果ReadMe 寫的不詳細,是很難看懂的,更不用說理解運用了,如果一篇一篇文章,一步一步解釋,一條一條註釋,然後貼出總體的,都不能理解的話,直接一個完整的源碼就能看懂嗎?

 

  傷不起。。。

 

 

 

登錄

  該正事了

  登錄控制器 /Areas/SysManage/AccountController,一共有一個視圖,兩個方法:登錄頁面、登錄驗證、驗證碼

  

  

  首先,我們這個控制器跟區域里其它控制器的一個區別就是,我們沒有繼承 BaseController,我們可以看下我們的 BaseController 都幹了些什麼:

  ① 公用變數:主要就是用於試圖頁傳遞一些公用變數,例如:查詢關鍵字、分頁頁碼、分頁條數等。

  ② 用戶對象:網站後臺的管理員,我們首先從Session中獲取用戶,如果Session 失效,那麼我們從Cookies中獲取用戶信息,模擬登錄重新賦值 Session 並獲取用戶,如果Cookies也失效,那麼重新登錄。

  ③ 郵箱功能變數名稱:這個是內部郵件用的,我們這裡不用。

  ④ 登錄驗證

  ⑤ log4net日誌封裝方法

  ⑥ 輸出消息

  ⑦ 模塊許可權驗證:我們對每一個模塊都有獨立的許可權,並且監控Action和Method,在前面我們已經完成了對模塊許可權的初始化和自定義許可權擴展,這裡我們就需要驗證當前用戶,對此模塊的Action 是否有相應的操作許可權(例如:添加、修改、刪除、列表以及自定義的諸如 審核、列印、下載等),並且輸出許可權到視圖,同時在視圖頁對沒有相應許可權的按鈕Remove掉。通俗的講,就是我們Remove掉視圖頁中沒有許可權的按鈕,並且監控後臺Action的操作,所以即便你自己添加上相應的按鈕和方法,提交到後臺時也不會通過驗證。

  

 

  通過上面詳細的解釋,我們可以發現,登錄頁是不需要這些的,但是後臺操作的其它控制器都需要,所以它們都繼承了BaseController 但是,登錄控制器不需要。

 

  我們再回頭看我們的AccountController:

 

   Index 這個沒什麼可解釋的,就是登陸頁面,我們只是執行了移除Session和Cookies操作。

 

  我們來看下登錄驗證方法:

 

  首先,我們是要驗證驗證碼。(不區分大小寫)if (!string.IsNullOrEmpty(code) && code.ToLower() == Session["gif"].ToString().ToLower())

  然後,我們通過用戶輸入的賬號和密碼驗證用戶,這裡,我們通過匹配賬號和密碼返回用戶的實體類 var users = UserManage.UserLogin(item.ACCOUNT.Trim(), item.PASSWORD.Trim());

  值得註意的是:因為我們用的加密演算法是動態密鑰的,所以對相同的字元串每次加密後的密文都是不一樣的,因此我們不能通過對用戶輸入的密碼進行加密後與數據匹配,而是通過賬號取出密碼,對密碼進行解密與用戶輸入匹配的方式驗證:

  

  

  如果返回正常,我們首先還要驗證用戶是否被禁止登錄

  

  

  如果這一步驗證也通過,我們通過 var acconut = this.UserManage.GetAccountByUser(users); 獲取ViewModel:Account 類

  

 1 public class Account
 2     {
 3         #region Attribute
 4         /// <summary>
 5         /// 主鍵
 6         /// </summary>
 7         public int Id { get; set; }
 8         /// <summary>
 9         /// 姓名
10         /// </summary>
11         public string Name { get; set; }
12         /// <summary>
13         /// 登錄的用戶名
14         /// </summary>
15         public string LogName { get; set; }
16         /// <summary>
17         /// 姓名拼音
18         /// </summary>
19         public string PinYin { get; set; }
20         /// <summary>
21         /// 登錄密碼
22         /// </summary>
23         public string PassWord { get; set; }
24         /// <summary>
25         /// 是否管理員
26         /// </summary>
27         public bool IsAdmin { get; set; }
28         /// <summary>
29         /// 用戶頭像
30         /// </summary>
31         public string Face_Img { get; set; }
32         /// <summary>
33         /// 部門職務
34         /// </summary>
35 
36         public string Levels { get; set; }
37         /// <summary>
38         /// 用戶所屬系統Id
39         /// </summary>
40         public List<string> System_Id { get; set; }
41         /// <summary>
42         /// 用戶主部門
43         /// </summary>
44         public Domain.SYS_DEPARTMENT DptInfo { get; set; }
45         /// <summary>
46         /// 許可權集合
47         /// </summary>
48         public List<Domain.SYS_PERMISSION> Permissions { get; set; }
49         /// <summary>
50         /// 角色的集合
51         /// </summary>
52         public List<Domain.SYS_ROLE> Roles { get; set; }
53         /// <summary>
54         /// 用戶崗位集合
55         /// </summary>
56         public List<Domain.SYS_POST_USER> PostUser { get; set; }
57         /// <summary>
58         /// 用戶可操作的模塊集合
59         /// </summary>
60         public List<Domain.SYS_MODULE> Modules { get; set; }
61         #endregion
62     }

 

  這個類裡面包含了用戶的基本信息和可操作的系統、模塊以及相應的許可權信息。

 

   下一步,我們先來驗證一下,用戶可操作的系統(這裡起名有些誤導了,應該叫Systems,System_Id給人的印象是系統ID,而不是系統集合): if (acconut.System_Id.Count > 0)

  

 

單點登錄

 

  如果可操作系統驗證通過,我們檢測一下配置文件是否開啟了單點登錄:單點登錄的實現方式其實很簡單,這裡大體跟大家說一下思路

  首先,我們有個用戶線上狀態表 UserOnlie

  

  當我們創建用戶的時候,這裡也會創建一個 一對一 的用戶線上狀態記錄。

  我們在最外層的後臺主頁面中,有個 SignalR-Hubs ,也是與內部聊天室一體的,當用戶登錄後或重新連接時,我們便更新用戶的線上狀態:

  

  當用戶離線時,我們更新用戶的線上狀態為離線:

  

 

  通過這個簡單的方式,很簡陋的實現單用戶登錄模式。

 

 

  OK,這樣基本的步驟就算完成了,如果用戶不線上或沒有開啟單用戶登錄,那麼我們記錄Session和Cookies,如果開啟了單用戶模式,並且用戶已線上,那麼我們登錄失敗,提示當前用戶,用戶已登錄

  json.Msg = "當前用戶已登錄,系統不允許重覆登錄!登錄IP:" + UserOnline.UserIP;

 

  這個Login方法大家可以修改一些串列的方法為非同步並行,提高效率。登錄頁的UI 在之前的文章以及本文頂部 已經給大家分享,源碼 在前面的文章中也有,但是沒有加入單點登錄,這個是後來加上的,這裡再給大家貼一下完整的登錄控制器:

  

  1 using Common;
  2 using Service.IService;
  3 using System;
  4 using System.Collections.Generic;
  5 using System.Linq;
  6 using System.Web;
  7 using System.Web.Mvc;
  8 
  9 namespace WebPage.Areas.SysManage.Controllers
 10 {
 11     public class AccountController : Controller
 12     {
 13         #region 聲明容器
 14         /// <summary>
 15         /// 用戶管理
 16         /// add yuangang by 2016-05-16
 17         /// </summary>
 18         IUserManage UserManage { get; set; }
 19         /// <summary>
 20         /// 用戶線上管理
 21         /// </summary>
 22         IUserOnlineManage UserOnlineManage { get; set; }
 23         /// <summary>
 24         /// 日誌記錄
 25         /// </summary>
 26         log4net.Ext.IExtLog log = log4net.Ext.ExtLogManager.GetLogger("dblog");
 27         #endregion
 28 
 29         #region 基本視圖
 30         public ActionResult Index()
 31         {
 32             //移除Session
 33             SessionHelper.Remove("CurrentUser");
 34             CookieHelper.ClearCookie("cookie_rememberme");   
 35             return View();
 36         }
 37         /// <summary>
 38         /// 登錄驗證
 39         /// add yuangang by 2016-05-16
 40         /// </summary>
 41         [ValidateAntiForgeryToken]
 42         public ActionResult Login(Domain.SYS_USER item)
 43         {
 44             var json = new JsonHelper() { Msg = "登錄成功", Status = "n" };
 45             try
 46             {
 47                 //獲取表單驗證碼
 48                 var code = Request.Form["code"];
 49                 if (Session["gif"] != null)
 50                 {
 51                     //判斷用戶輸入的驗證碼是否正確
 52                     if (!string.IsNullOrEmpty(code) && code.ToLower() == Session["gif"].ToString().ToLower())
 53                     {
 54                         //調用登錄驗證介面 返回用戶實體類
 55                         var users = UserManage.UserLogin(item.ACCOUNT.Trim(), item.PASSWORD.Trim());
 56                         if (users != null)
 57                         {
 58                             //是否鎖定
 59                             if (users.ISCANLOGIN)
 60                             {
 61                                 json.Msg = "用戶已鎖定,禁止登錄,請聯繫管理員進行解鎖";
 62                                 log.Warn(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系統登錄,登錄結果:" + json.Msg);
 63                                 return Json(json);
 64                             }
 65 
 66                             var acconut = this.UserManage.GetAccountByUser(users);
 67 
 68                             //系統訪問正常
 69                             if (acconut.System_Id.Count > 0)
 70                             {
 71                                 //是否啟用單用戶登錄
 72                                 if (System.Configuration.ConfigurationManager.AppSettings["IsSingleLogin"] == "True" )
 73                                 {
 74                                     var UserOnline = UserOnlineManage.LoadListAll(p => p.FK_UserId == users.ID).FirstOrDefault();
 75                                     if(UserOnline!=null && UserOnline.IsOnline)
 76                                     {
 77                                         json.Msg = "當前用戶已登錄,系統不允許重覆登錄!登錄IP:" + UserOnline.UserIP;
 78                                         log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "重覆登錄:" + json.Msg);
 79                                     }
 80                                     else
 81                                     {
 82                                         //寫入Session 當前登錄用戶
 83                                         SessionHelper.SetSession("CurrentUser", acconut);
 84 
 85                                         //記錄用戶信息到Cookies
 86                                         string cookievalue = "{\"id\":\"" + acconut.Id + "\",\"username\":\"" + acconut.LogName +
 87                                                              "\",\"password\":\"" + acconut.PassWord + "\",\"ToKen\":\"" +
 88                                                              Session.SessionID + "\"}";
 89                                         CookieHelper.SetCookie("cookie_rememberme", new Common.CryptHelper.AESCrypt().Encrypt(cookievalue),
 90                                             null);
 91 
 92                                         json.Status = "y";
 93                                         json.ReUrl = "/Sys/Home/Index";
 94                                         log.Info(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系統登錄,登錄結果:" + json.Msg);
 95                                     }
 96                                 }
 97                                 else
 98                                 {
 99                                     //寫入Session 當前登錄用戶
100                                     SessionHelper.SetSession("CurrentUser", acconut);
101 
102                                     //記錄用戶信息到Cookies
103                                     string cookievalue = "{\"id\":\"" + acconut.Id + "\",\"username\":\"" + acconut.LogName +
104                                                          "\",\"password\":\"" + acconut.PassWord + "\",\"ToKen\":\"" +
105                                                          Session.SessionID + "\"}";
106                                     CookieHelper.SetCookie("cookie_rememberme", new Common.CryptHelper.AESCrypt().Encrypt(cookievalue),
107                                         null);
108 
109                                     json.Status = "y";
110                                     json.ReUrl = "/Sys/Home/Index";
111                                     log.Info(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系統登錄,登錄結果:" + json.Msg);
112                                 }
113                             }
114                             else
115                             {
116                                 json.Msg = "站點來源不可信,系統拒絕登錄";
117                                 log.Warn(Utils.GetIP(), "其他系統訪問者", "", "Login", "其他系統登錄失敗,原因:系統驗證錯誤,系統拒絕登錄");
118                             }
119 
120                         }
121                         else
122                         {
123                             json.Msg = "用戶名或密碼不正確";
124                             log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系統登錄,登錄結果:" + json.Msg);
125                         }
126                     }
127                     else
128                     {
129                         json.Msg = "驗證碼不正確";
130                         log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系統登錄,登錄結果:" + json.Msg);
131                     }                    
132                 }
133                 else
134                 {
135                     json.Msg = "驗證碼已過期,請刷新驗證碼";
136                     log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系統登錄,登錄結果:" + json.Msg);
137                 }              
138             }
139             catch (Exception e)
140             {
141                 json.Msg = e.Message;
142                 log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系統登錄,登錄結果:" + json.Msg);
143             }
144             return Json(json, JsonRequestBehavior.AllowGet);
145         }
146         #endregion
147 
148         #region 幫助方法
149         /// <summary>
150         /// 驗證碼
151         /// </summary>
152         public FileContentResult ValidateCode()
153         {
154             string code = "";
155             System.IO.MemoryStream ms = new Models.verify_code().Create(out code);
156             Session["gif"] = code;//驗證碼存儲在Session中,供驗證。  
157             Response.ClearContent();//清空輸出流 
158             return File(ms.ToArray(), @"image/png");
159         }
160         #endregion
161     }
162 }
View Code

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在前面隨筆《C#開發微信門戶及應用(41)--基於微信開放平臺的掃碼登錄處理》介紹了基於微信開放平臺介面實現的微信掃碼直接登錄的過程。本篇介紹對掃碼登錄的一些改進和處理,以便更方便應用在實際項目中。 ...
  • 在MVC的邏輯代碼里,Controller和Action是必須的,但是在網址里,並不需要完全體現Controller和Action。比如我們經常希望看到http://localhost/About而不是http://localhost/Home/About。 預設的路由規則 新建MVC應用程式後,G ...
  • 原文網址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 語言編寫的TCP/UDP通信框架 作者是英國人 以前是收費的 目前作者已經開源 開源地址是:https://github.com/MarcFletcher/NetworkComms.Net 使 ...
  • 原文網址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 語言編寫的TCP/UDP通信框架 作者是英國人 以前是收費的 目前作者已經開源 開源地址是:https://github.com/MarcFletcher/NetworkComms.Net 使 ...
  • 開始使用 LINQ(五)- LINQ 中的查詢語法和方法語法 在表示語言集成查詢 (LINQ) 使用 LINQ 性查詢語法,文檔中的多數查詢編寫。但是,編譯代碼時,必須將查詢語法轉換為方法,這就需要 .NET 公共語言運行時 (CLR)。這些方法調用標準查詢運算符的名稱類似 Where、Select ...
  • 開始使用 LINQ(四)- LINQ 查詢操作的類型關係 LINQ 查詢操作在數據源、查詢本身及查詢執行中是強類型的。查詢中變數的類型必須與數據源中元素的類型和 foreach 語句中迭代變數的類型相容。此強類型保證在編譯時捕獲類型錯誤,以便可以在用戶遇到這些錯誤之前更正它們。 一、不轉換源數據的查 ...
  • 【簡訊貓相關問題】 【getDeviceNameByRFID】的引用。註意 一系列配置 【簡訊貓SmsHelper】 【簡訊貓DuanXinMao】 ...
  • MXS&Vincene ─╄OvЁ &0000027─╄OvЁ MXS&Vincene MXS&Vincene ─╄OvЁ:今天很殘酷,明天更殘酷,後天很美好,但是絕大部分人是死在明天晚上,只有那些真正的英雄才能見到後天的太陽。 MXS&Vincene ─╄OvЁ:We're here to put ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...