一、預設Web項目的更改
使用者這部分還是自己做,所以刪除自動產生的使用者相關代碼。
二、添加Member地區
在web項目上點右鍵 添加 地區Member。
添加Home控制器,選擇MVC5控制器-空
我們給public ActionResult Index()添加一個視圖,代碼很簡單就是顯示下使用者名稱
@{ ViewBag.Title = "測試人員中樞";}<h2>歡迎你!@User.Identity.Name </h2>
我們先運行一下,出錯啦。
這是因為項目中有兩個名為Home的控制器,必須在路由中加上命名空間。先開啟地區中的MemberAreaRegistration添加命名空間。
再開啟項目中的RouteConfig,添加命名空間
再重新整理瀏覽器,可以正常顯示。
再添加使用者控制器UserController。
三、模型類的更改
在這裡先對Models項目User模型進行修改,原來考慮的是每個使用者只能屬於一個使用者組,後來仔細考慮了一下,還是不太合適,比如一個使用者兼任多個角色,所以還是把使用者和使用者組改成一對多的關係。
- User模型。在模型中刪除GroupID,刪除外鍵Group。
- Role模型。原來UserGroup(使用者組)改為角色,考慮到許可權管理感覺叫角色比叫戶組更加合適,另外角色的含義更廣,可以是指使用者組,也可以指職位,還可以指部門……修改後代碼如下:
using System.ComponentModel.DataAnnotations;namespace Ninesky.Models{ /// <summary> /// 角色 /// <remarks> /// 建立:2014.02.02 /// 修改:2014.02.16 /// </remarks> /// </summary> public class Role { [Key] public int RoleID { get; set; } /// <summary> /// 名稱 /// </summary> [Required(ErrorMessage="必填")] [StringLength(20, MinimumLength = 2, ErrorMessage = "{1}到{0}個字")] [Display(Name="名稱")] public string Name { get; set; } /// <summary> /// 角色類型<br /> /// 0普通(普通註冊使用者),1特權(像VIP之類的類型),3管理(系統管理權限的類型) /// </summary> [Required(ErrorMessage = "必填")] [Display(Name = "使用者群組類型")] public int Type { get; set; } /// <summary> /// 說明 /// </summary> [Required(ErrorMessage = "必填")] [StringLength(50, ErrorMessage = "少於{0}個字")] [Display(Name = "說明")] public string Description { get; set; } /// <summary> /// 擷取角色類型名稱 /// </summary> /// <returns></returns> public string TypeToString() { switch (Type) { case 0: return "普通"; case 1: return "特權"; case 2: return "管理"; default: return "未知"; } } }}
UserRoleRelation類。在Models項目添加角色關係類UserRoleRelation類,代碼:
using System.ComponentModel.DataAnnotations;namespace Ninesky.Models{ /// <summary> /// 使用者角色關係 /// <remarks> /// 建立:2014.02.16 /// </remarks> /// </summary> public class UserRoleRelation { [Key] public int RelationID { get; set; } /// <summary> /// 使用者ID /// </summary> [Required()] public int UserID { get; set; } /// <summary> /// 角色ID /// </summary> [Required()] public int RoelID { get; set; } }}
NineskyDbContext類。 如下圖藍色框為修改部分,紅框為新增加
三、驗證碼及Sha256加密
1、驗證碼
現在驗證碼是網站的必須功能,我把驗證碼功能分成三塊:建立驗證碼字元、根據驗證碼產生圖片、User控制器action中儲存驗證碼並返回圖片。
建立驗證碼字元 CreateVerificationText()
在Common中添加Security類,在類中利用偽隨機數產生器產生驗證碼字串。
/// <summary> /// 建立驗證碼字元 /// </summary> /// <param name="length">字元長度</param> /// <returns>驗證碼字元</returns> public static string CreateVerificationText(int length) { char[] _verification = new char[length]; char[] _dictionary = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; Random _random = new Random(); for (int i = 0; i < length; i++) { _verification[i] = _dictionary[_random.Next(_dictionary.Length - 1)]; } return new string(_verification); }
根據驗證碼產生圖片CreateVerificationImage()
思路是使用GDI+建立畫布,使用偽隨機數產生器產生漸層畫刷,然後建立漸層文字。
/// <summary> /// 建立驗證碼圖片 /// </summary> /// <param name="verificationText">驗證碼字串</param> /// <param name="width">圖片寬度</param> /// <param name="height">圖片長度</param> /// <returns>圖片</returns> public static Bitmap CreateVerificationImage(string verificationText, int width, int height) { Pen _pen= new Pen(Color.Black); Font _font = new Font("Arial", 14, FontStyle.Bold); Brush _brush = null; Bitmap _bitmap = new Bitmap(width,height); Graphics _g = Graphics.FromImage(_bitmap); SizeF _totalSizeF = _g.MeasureString(verificationText,_font); SizeF _curCharSizeF; PointF _startPointF = new PointF((width-_totalSizeF.Width)/2,(height-_totalSizeF.Height)/2); //隨機數產生器 Random _random =new Random(); _g.Clear(Color.White); for(int i=0;i<verificationText.Length;i++) { _brush = new LinearGradientBrush(new Point(0,0),new Point(1,1),Color.FromArgb(_random.Next(255),_random.Next(255),_random.Next(255)),Color.FromArgb(_random.Next(255),_random.Next(255),_random.Next(255))); _g.DrawString(verificationText[i].ToString(),_font,_brush,_startPointF); _curCharSizeF = _g.MeasureString(verificationText[i].ToString(),_font); _startPointF.X+= _curCharSizeF.Width; } _g.Dispose(); return _bitmap; }
User控制器action中儲存驗證碼並返回圖片
首先添加User控制器,在Member地區中添加控制器UserController。在控制器中寫一個VerificationCode方法。過程是:在方法中我們先建立6位驗證碼字串->使用CreateVerificationImage建立驗證碼圖片->把圖片寫入OutputStream中->把驗證碼字串寫入TempData中。
儲存在TempData中和Session中的區別:TempData只傳遞一次,也就是傳遞到下一個action後,action代碼執行完畢就會銷毀,Session會持續儲存,所以驗證碼用TempData比較合適。
/// <summary> /// 驗證碼 /// </summary> /// <returns></returns> public ActionResult VerificationCode() { string verificationCode = Security.CreateVerificationText(6); Bitmap _img = Security.CreateVerificationImage(verificationCode, 160, 30); _img.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg); TempData["VerificationCode"] = verificationCode.ToUpper(); return null; }
我們看看產生圖驗證碼效果:
2、Sha256加密
在COmmon項目的Security類中添加靜態方法Sha256(string plainText)
/// <summary> /// 256位散列加密 /// </summary> /// <param name="plainText">明文</param> /// <returns>密文</returns> public static string Sha256(string plainText) { SHA256Managed _sha256 = new SHA256Managed(); byte[] _cipherText = _sha256.ComputeHash(Encoding.Default.GetBytes(plainText)); return Convert.ToBase64String(_cipherText); }
四、註冊
在Ninesky.Web.Areas.Member.Models中添加註冊視圖模型
using System.ComponentModel.DataAnnotations;namespace Ninesky.Web.Areas.Member.Models{ public class RegisterViewModel { /// <summary> /// 使用者名稱 /// </summary> [Required(ErrorMessage = "必填")] [StringLength(20, MinimumLength = 4, ErrorMessage = "{2}到{1}個字元")] [Display(Name = "使用者名稱")] public string UserName { get; set; } /// <summary> /// 顯示名 /// </summary> [Required(ErrorMessage = "必填")] [StringLength(20, MinimumLength = 2, ErrorMessage = "{2}到{1}個字元")] [Display(Name = "顯示名")] public string DisplayName { get; set; } /// <summary> /// 密碼 /// </summary> [Required(ErrorMessage = "必填")] [Display(Name = "密碼")] [StringLength(20,MinimumLength=6,ErrorMessage="{2}到{1}個字元")] [DataType(DataType.Password)] public string Password { get; set; } /// <summary> /// 確認密碼 /// </summary> [Required(ErrorMessage = "必填")] [Compare("Password", ErrorMessage = "兩次輸入的密碼不一致")] [Display(Name = "確認密碼")] [DataType(DataType.Password)] public string ConfirmPassword { get; set; } /// <summary> /// 郵箱 /// </summary> [Required(ErrorMessage = "必填")] [Display(Name = "郵箱")] [DataType(DataType.EmailAddress,ErrorMessage="Email格式不正確")] public string Email { get; set; } /// <summary> /// 驗證碼 /// </summary> [Required(ErrorMessage = "必填")] [StringLength(6, MinimumLength = 6, ErrorMessage = "驗證碼不正確")] [Display(Name = "驗證碼")] public string VerificationCode { get; set; } }}
在UserController中添加Register() action ,並返回直接返回強型別(RegisterViewModel)視圖
/// <summary> /// 註冊 /// </summary> /// <returns></returns> public ActionResult Register() { return View(); }
視圖
@model Ninesky.Web.Areas.Member.Models.RegisterViewModel@{ ViewBag.Title = "註冊"; Layout = "~/Views/Shared/_Layout.cshtml";}@using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>使用者註冊</h4> <hr /> @Html.ValidationSummary(true) <div class="form-group"> @Html.LabelFor(model => model.UserName, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.UserName) @Html.ValidationMessageFor(model => model.UserName) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.DisplayName, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.DisplayName) @Html.ValidationMessageFor(model => model.DisplayName) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Password, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Password) @Html.ValidationMessageFor(model => model.Password) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.ConfirmPassword, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.ConfirmPassword) @Html.ValidationMessageFor(model => model.ConfirmPassword) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Email, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Email) @Html.ValidationMessageFor(model => model.Email) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.VerificationCode, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.VerificationCode) <img id="verificationcode" title="點擊重新整理" src="@Url.Action("VerificationCode")" style="cursor:pointer" /> @Html.ValidationMessageFor(model => model.VerificationCode) </div> </div> <div class="checkbox"> <input type="checkbox" checked="checked" required />我同意 <a href="#">《使用者註冊協議》</a> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="註冊" class="btn btn-default" /> </div> </div> </div>}<script type="text/javascript"> $("#verificationcode").click(function () { $("#verificationcode").attr("src", "@Url.Action("VerificationCode")?" + new Date()); })</script>@section Scripts { @Scripts.Render("~/bundles/jqueryval")}
再在使用者控制器中添加public ActionResult Register(RegisterViewModel register)用來處理使用者提交的註冊資料
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Register(RegisterViewModel register) { if (TempData["VerificationCode"] == null || TempData["VerificationCode"].ToString() != register.VerificationCode.ToUpper()) { ModelState.AddModelError("VerificationCode", "驗證碼不正確"); return View(register); } if(ModelState.IsValid) { if (userService.Exist(register.UserName)) ModelState.AddModelError("UserName", "使用者名稱已存在"); else { User _user = new User() { UserName = register.UserName, //預設使用者組代碼寫這裡 DisplayName = register.DisplayName, Password = Security.Sha256(register.Password), //郵箱驗證與郵箱唯一性問題 Email = register.Email, //使用者狀態問題 Status = 0, RegistrationTime = System.DateTime.Now }; _user = userService.Add(_user); if (_user.UserID > 0) { return Content("註冊成功!"); //AuthenticationManager.SignIn(); } else { ModelState.AddModelError("", "註冊失敗!"); } } } return View(register); }
代碼中很多根使用者設定相關的內容先不考慮,等做到使用者佈建時在會後來修改。註冊失敗時返回視圖並顯示錯誤;成功時返回視圖註冊成功,等下次做使用者登入時可以讓使用者註冊完畢直接進行登入。看看效果。
點擊註冊,註冊成功。
一個簡單的使用者註冊完成了,主要有驗證碼、sha256加密、註冊視圖模型、驗證使用者提交資料並儲存等步驟。後面就是使用者註冊,註冊會用到ClaimsIdentity和HttpContext.GetOwinContext().Authentication.SignIn();
本文已被整理到了《ASP.NET MVC網站開發教程》,歡迎大家學習閱讀,更多內容還可以參考ASP.NET MVC5網站開發專題學習。
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。