ASP.NET?MVC5網(wǎng)站開(kāi)發(fā)用戶(hù)注冊(cè)(四)
一、默認(rèn)Web項(xiàng)目的更改
用戶(hù)這部分還是自己做,所以刪除自動(dòng)生成的用戶(hù)相關(guān)代碼。
二、添加Member區(qū)域
在web項(xiàng)目上點(diǎn)右鍵 添加 區(qū)域Member。
添加Home控制器,選擇MVC5控制器-空
我們給public ActionResult Index()添加一個(gè)視圖,代碼很簡(jiǎn)單就是顯示下用戶(hù)名
@{ ViewBag.Title = "會(huì)員中心"; } <h2>歡迎你!@User.Identity.Name </h2>
我們先運(yùn)行一下,出錯(cuò)啦。
這是因?yàn)轫?xiàng)目中有兩個(gè)名為Home的控制器,必須在路由中加上命名空間。先打開(kāi)區(qū)域中的MemberAreaRegistration添加命名空間。
再打開(kāi)項(xiàng)目中的RouteConfig,添加命名空間
再刷新瀏覽器,可以正常顯示。
再添加用戶(hù)控制器UserController。
三、模型類(lèi)的更改
在這里先對(duì)Models項(xiàng)目User模型進(jìn)行修改,原來(lái)考慮的是每個(gè)用戶(hù)只能屬于一個(gè)用戶(hù)組,后來(lái)仔細(xì)考慮了一下,還是不太合適,比如一個(gè)用戶(hù)兼任多個(gè)角色,所以還是把用戶(hù)和用戶(hù)組改成一對(duì)多的關(guān)系。
- User模型。在模型中刪除GroupID,刪除外鍵Group。
- Role模型。原來(lái)UserGroup(用戶(hù)組)改為角色,考慮到權(quán)限管理感覺(jué)叫角色比叫戶(hù)組更加合適,另外角色的含義更廣,可以是指用戶(hù)組,也可以指職位,還可以指部門(mén)……修改后代碼如下:
using System.ComponentModel.DataAnnotations; namespace Ninesky.Models { /// <summary> /// 角色 /// <remarks> /// 創(chuàng)建:2014.02.02 /// 修改:2014.02.16 /// </remarks> /// </summary> public class Role { [Key] public int RoleID { get; set; } /// <summary> /// 名稱(chēng) /// </summary> [Required(ErrorMessage="必填")] [StringLength(20, MinimumLength = 2, ErrorMessage = "{1}到{0}個(gè)字")] [Display(Name="名稱(chēng)")] public string Name { get; set; } /// <summary> /// 角色類(lèi)型<br /> /// 0普通(普通注冊(cè)用戶(hù)),1特權(quán)(像VIP之類(lèi)的類(lèi)型),3管理(管理權(quán)限的類(lèi)型) /// </summary> [Required(ErrorMessage = "必填")] [Display(Name = "用戶(hù)組類(lèi)型")] public int Type { get; set; } /// <summary> /// 說(shuō)明 /// </summary> [Required(ErrorMessage = "必填")] [StringLength(50, ErrorMessage = "少于{0}個(gè)字")] [Display(Name = "說(shuō)明")] public string Description { get; set; } /// <summary> /// 獲取角色類(lèi)型名稱(chēng) /// </summary> /// <returns></returns> public string TypeToString() { switch (Type) { case 0: return "普通"; case 1: return "特權(quán)"; case 2: return "管理"; default: return "未知"; } } } }
UserRoleRelation類(lèi)。在Models項(xiàng)目添加角色關(guān)系類(lèi)UserRoleRelation類(lèi),代碼:
using System.ComponentModel.DataAnnotations; namespace Ninesky.Models { /// <summary> /// 用戶(hù)角色關(guān)系 /// <remarks> /// 創(chuàng)建:2014.02.16 /// </remarks> /// </summary> public class UserRoleRelation { [Key] public int RelationID { get; set; } /// <summary> /// 用戶(hù)ID /// </summary> [Required()] public int UserID { get; set; } /// <summary> /// 角色I(xiàn)D /// </summary> [Required()] public int RoelID { get; set; } } }
NineskyDbContext類(lèi)。 如下圖藍(lán)色框?yàn)樾薷牟糠?,紅框?yàn)樾略黾?/p>
三、驗(yàn)證碼及Sha256加密
1、驗(yàn)證碼
現(xiàn)在驗(yàn)證碼是網(wǎng)站的必須功能,我把驗(yàn)證碼功能分成三塊:創(chuàng)建驗(yàn)證碼字符、根據(jù)驗(yàn)證碼生成圖片、User控制器action中保存驗(yàn)證碼并返回圖片。
創(chuàng)建驗(yàn)證碼字符 CreateVerificationText()
在Common中添加Security類(lèi),在類(lèi)中利用偽隨機(jī)數(shù)生成器生成驗(yàn)證碼字符串。
/// <summary> /// 創(chuàng)建驗(yàn)證碼字符 /// </summary> /// <param name="length">字符長(zhǎng)度</param> /// <returns>驗(yàn)證碼字符</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); }
根據(jù)驗(yàn)證碼生成圖片CreateVerificationImage()
思路是使用GDI+創(chuàng)建畫(huà)布,使用偽隨機(jī)數(shù)生成器生成漸變畫(huà)刷,然后創(chuàng)建漸變文字。
/// <summary> /// 創(chuàng)建驗(yàn)證碼圖片 /// </summary> /// <param name="verificationText">驗(yàn)證碼字符串</param> /// <param name="width">圖片寬度</param> /// <param name="height">圖片長(zhǎng)度</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); //隨機(jī)數(shù)產(chǎn)生器 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中保存驗(yàn)證碼并返回圖片
首先添加User控制器,在Member區(qū)域中添加控制器UserController。在控制器中寫(xiě)一個(gè)VerificationCode方法。過(guò)程是:在方法中我們先創(chuàng)建6位驗(yàn)證碼字符串->使用CreateVerificationImage創(chuàng)建驗(yàn)證碼圖片->把圖片寫(xiě)入OutputStream中->把驗(yàn)證碼字符串寫(xiě)入TempData中。
保存在TempData中和Session中的區(qū)別:TempData只傳遞一次,也就是傳遞到下一個(gè)action后,action代碼執(zhí)行完畢就會(huì)銷(xiāo)毀,Session會(huì)持續(xù)保存,所以驗(yàn)證碼用TempData比較合適。
/// <summary> /// 驗(yàn)證碼 /// </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; }
我們看看生成圖驗(yàn)證碼效果:
2、Sha256加密
在COmmon項(xiàng)目的Security類(lèi)中添加靜態(tài)方法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); }
四、注冊(cè)
在Ninesky.Web.Areas.Member.Models中添加注冊(cè)視圖模型
using System.ComponentModel.DataAnnotations; namespace Ninesky.Web.Areas.Member.Models { public class RegisterViewModel { /// <summary> /// 用戶(hù)名 /// </summary> [Required(ErrorMessage = "必填")] [StringLength(20, MinimumLength = 4, ErrorMessage = "{2}到{1}個(gè)字符")] [Display(Name = "用戶(hù)名")] public string UserName { get; set; } /// <summary> /// 顯示名 /// </summary> [Required(ErrorMessage = "必填")] [StringLength(20, MinimumLength = 2, ErrorMessage = "{2}到{1}個(gè)字符")] [Display(Name = "顯示名")] public string DisplayName { get; set; } /// <summary> /// 密碼 /// </summary> [Required(ErrorMessage = "必填")] [Display(Name = "密碼")] [StringLength(20,MinimumLength=6,ErrorMessage="{2}到{1}個(gè)字符")] [DataType(DataType.Password)] public string Password { get; set; } /// <summary> /// 確認(rèn)密碼 /// </summary> [Required(ErrorMessage = "必填")] [Compare("Password", ErrorMessage = "兩次輸入的密碼不一致")] [Display(Name = "確認(rèn)密碼")] [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> /// 驗(yàn)證碼 /// </summary> [Required(ErrorMessage = "必填")] [StringLength(6, MinimumLength = 6, ErrorMessage = "驗(yàn)證碼不正確")] [Display(Name = "驗(yàn)證碼")] public string VerificationCode { get; set; } } }
在UserController中添加Register() action ,并返回直接返回強(qiáng)類(lèi)型(RegisterViewModel)視圖
/// <summary> /// 注冊(cè) /// </summary> /// <returns></returns> public ActionResult Register() { return View(); }
視圖
@model Ninesky.Web.Areas.Member.Models.RegisterViewModel @{ ViewBag.Title = "注冊(cè)"; Layout = "~/Views/Shared/_Layout.cshtml"; } @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>用戶(hù)注冊(cè)</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="點(diǎn)擊刷新" 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="#">《用戶(hù)注冊(cè)協(xié)議》</a> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="注冊(cè)" 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") }
再在用戶(hù)控制器中添加public ActionResult Register(RegisterViewModel register)用來(lái)處理用戶(hù)提交的注冊(cè)數(shù)據(jù)
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Register(RegisterViewModel register) { if (TempData["VerificationCode"] == null || TempData["VerificationCode"].ToString() != register.VerificationCode.ToUpper()) { ModelState.AddModelError("VerificationCode", "驗(yàn)證碼不正確"); return View(register); } if(ModelState.IsValid) { if (userService.Exist(register.UserName)) ModelState.AddModelError("UserName", "用戶(hù)名已存在"); else { User _user = new User() { UserName = register.UserName, //默認(rèn)用戶(hù)組代碼寫(xiě)這里 DisplayName = register.DisplayName, Password = Security.Sha256(register.Password), //郵箱驗(yàn)證與郵箱唯一性問(wèn)題 Email = register.Email, //用戶(hù)狀態(tài)問(wèn)題 Status = 0, RegistrationTime = System.DateTime.Now }; _user = userService.Add(_user); if (_user.UserID > 0) { return Content("注冊(cè)成功!"); //AuthenticationManager.SignIn(); } else { ModelState.AddModelError("", "注冊(cè)失??!"); } } } return View(register); }
代碼中很多根用戶(hù)設(shè)置相關(guān)的內(nèi)容先不考慮,等做到用戶(hù)設(shè)置時(shí)在會(huì)后來(lái)修改。注冊(cè)失敗時(shí)返回視圖并顯示錯(cuò)誤;成功時(shí)返回視圖注冊(cè)成功,等下次做用戶(hù)登錄時(shí)可以讓用戶(hù)注冊(cè)完畢直接進(jìn)行登錄??纯葱Ч?。
點(diǎn)擊注冊(cè),注冊(cè)成功。
一個(gè)簡(jiǎn)單的用戶(hù)注冊(cè)完成了,主要有驗(yàn)證碼、sha256加密、注冊(cè)視圖模型、驗(yàn)證用戶(hù)提交數(shù)據(jù)并保存等步驟。后面就是用戶(hù)注冊(cè),注冊(cè)會(huì)用到ClaimsIdentity和HttpContext.GetOwinContext().Authentication.SignIn();
本文已被整理到了《ASP.NET MVC網(wǎng)站開(kāi)發(fā)教程》,歡迎大家學(xué)習(xí)閱讀,更多內(nèi)容還可以參考ASP.NET MVC5網(wǎng)站開(kāi)發(fā)專(zhuān)題學(xué)習(xí)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- ASP.NET用戶(hù)注冊(cè)實(shí)戰(zhàn)(第11節(jié))
- ASP.NET實(shí)現(xiàn)用戶(hù)注冊(cè)和驗(yàn)證功能(第4節(jié))
- ASP.NET jQuery 實(shí)例12 通過(guò)使用jQuery validation插件簡(jiǎn)單實(shí)現(xiàn)用戶(hù)注冊(cè)頁(yè)面驗(yàn)證功能
- Asp.net下利用Jquery Ajax實(shí)現(xiàn)用戶(hù)注冊(cè)檢測(cè)(驗(yàn)證用戶(hù)名是否存)
- asp.net XMLHttpRequest實(shí)現(xiàn)用戶(hù)注冊(cè)前的驗(yàn)證
- ASP.NET登錄注冊(cè)頁(yè)面實(shí)現(xiàn)
- ASP.NET實(shí)現(xiàn)個(gè)人信息注冊(cè)頁(yè)面并跳轉(zhuǎn)顯示
相關(guān)文章
ASP.NET MVC4中使用Html.DropDownListFor的方法示例
這篇文章主要介紹了ASP.NET MVC4中使用Html.DropDownListFor的方法,結(jié)合實(shí)例形式分析了控制器數(shù)據(jù)源及Html.DropDownListFor顯示操作的相關(guān)技巧,需要的朋友可以參考下2016-08-08.NET?Core?使用委托實(shí)現(xiàn)動(dòng)態(tài)流程組裝的思路詳解
模擬管道模型中間件(Middleware)部分,運(yùn)用委托,進(jìn)行動(dòng)態(tài)流程組裝,本次代碼實(shí)現(xiàn)就直接我之前寫(xiě)的動(dòng)態(tài)代理實(shí)現(xiàn)AOP的基礎(chǔ)上改的,就不另起爐灶了,主要思路就是運(yùn)用委托,具體實(shí)現(xiàn)過(guò)程跟隨小編一起看看吧2022-01-01.NET讀寫(xiě)Excel工具Spire.Xls使用 重量級(jí)的Excel圖表功能(5)
這篇文章主要為大家詳細(xì)介紹了.NET讀寫(xiě)Excel工具Spire.Xls使用,重量級(jí)的Excel圖表功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11值得收藏的asp.net基礎(chǔ)學(xué)習(xí)筆記
這篇文章主要分享了一份值得大家收藏的asp.net基礎(chǔ)學(xué)習(xí)筆記,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09Entity Framework使用Code First模式管理事務(wù)
本文詳細(xì)講解了Entity Framework使用Code First模式管理事務(wù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03ASP.NET之Response.Cookies.Remove 無(wú)法刪除COOKIE的原因
在web開(kāi)發(fā)中Cookie是必不可少的,.NET自然也有一個(gè)強(qiáng)大的Cookie操作類(lèi),我們用起來(lái)也非常方便,不過(guò)在使用中我們會(huì)發(fā)現(xiàn)一個(gè)坑爹的事情Response.Cookies.Remove刪除不了Cookie。2013-06-06Asp.Net Oracle數(shù)據(jù)的通用操作類(lèi)
Asp.Net連接Oracle數(shù)據(jù)的通用操作類(lèi)并且利用它對(duì)數(shù)據(jù)庫(kù)查詢(xún)、匯總、更新等操作演示2009-12-12探究ASP.NET Core Middleware實(shí)現(xiàn)方法
這篇文章主要介紹了探究ASP.NET Core Middleware實(shí)現(xiàn)方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02