ASP.NET MVC5网站开发用户注册(四)_实用技巧

一、默认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网站开发专题学习。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索asp.net
, 网站开发
, mvc5
用户注册
,以便于您获取更多的相关知识。

时间: 2024-10-02 14:40:58

ASP.NET MVC5网站开发用户注册(四)_实用技巧的相关文章

asp.net获取网站绝对路径示例_实用技巧

复制代码 代码如下: VirtualPathUtility.ToAbsolute( " ~/ " )HttpRuntime.AppDomainAppVirtualPathRequest.ApplicationPathPage.ResolveUrl( " ~ " ) 以上代码生成的结果如下:当以网站的方式访问时,结果如下: 复制代码 代码如下: VirtualPathUtility.ToAbsolute("~/") = /HttpRuntime.A

ASP.NET MVC5网站开发修改及删除文章(十)_实用技巧

上次做了显示文章列表,再实现修改和删除文章这部分内容就结束了,这次内容比较简单,由于做过了添加文章,修改文章非常类似,就是多了一个TryUpdateModel部分更新模型数据.一.删除文章 由于公共模型跟,文章,附件有关联,所以这里的删除次序很重要,如果先删除模型,那么文章ModelID和附件的ModelID多会变成null,所以要先先删除文章和附件再删除公共模型. 由于公共模型和附件是一对多的关系,我们把删除公共模型和删除附件写在一起. 在BLL的BaseRepository类中有默认的Del

ASP.NET MVC5网站开发咨询管理的架构(十一)_实用技巧

一.总体说明 1.实现功能 2.类图 由于文章部分把大部分类都是实现了,这里仅多了一个Consultation类. 二.创建咨询模型类 在Ninesky.Models项目添加类Consultation(咨询模型),该模型跟Article类似都是CommonModel的扩展.1.添加Consultation类. using System; using System.ComponentModel.DataAnnotations; namespace Ninesky.Models { /// <sum

ASP.NET MVC5网站开发概述(一)_实用技巧

前段时间一直在用MVC4写个网站开发的demo,由于刚开始学所有的代码都写在一个项目中,越写越混乱,到后来有些代码自己都理不清了.正好看到别人在用MVC5写东西,喜新厌旧的我马上下载了Visual Studio 2013,幸好MVC4到MVC5变化不大,这次准备用MVC5重新写个Demo. 每次看以前写的代码总有把它丢进回收站的冲动,其实没有完美的代码,能解决问题的代码就算是好代码吧,但是我还是决定重新写一个学习的Demo,希望这次能有提高,希望这次能写完吧! 一.开发环境 1.开发环境: Vi

ASP.NET MVC5网站开发管理列表、回复及删除(十三)_实用技巧

一.管理列表跟上次我的列表相似,直接贴代码了. 首先打开Consultation控制器,添加ManageList方法 /// <summary> /// 咨询管理 /// </summary> /// <returns></returns> public ActionResult ManageList() { return View(); } 添加返回json数据的ManageJsonList public JsonResult ManageJsonList

ASP.NET MVC5网站开发我的咨询列表及添加咨询(十二)_实用技巧

上次把咨询的架构搭好了,现在分两次来完成咨询:1.用户部分,2管理部分.这次实现用户部分,包含两个功能,查看我的咨询和进行咨询. 一.菜单 打开上次添加的ConsultationController控制器,添加Menu action,返回分布视图 /// <summary> /// 菜单 /// </summary> /// <returns></returns> public ActionResult Menu() { return PartialView

ASP.NET MVC5网站开发用户修改资料和密码(六)_实用技巧

在上一篇文章网站开发(五)中实现了用户的注销和登录,其实代码里落了点东西,就是用户登录要更新最后一次登录时间和登录IP,这次补上.今天做修改资料和修改密码,TryUpdateModel是新用到的东西. 现完善昨天的登录代码: 一.用户导航菜单这个就是侧栏的导航,以后所有控制器中action名都为Menu.目标效果如下: 先UserController添加Menu action.直接返回分布视图.右键添加视图 <div class="panel panel-primary">

ASP.NET MVC5网站开发添加文章(八)_实用技巧

一.添加文章 1.KindEditor富文本编辑器 到官方网站http://kindeditor.net/down.php下载最新版本,解压后把代码复制到项目的Scripts文件夹下. 2.添加界面的显示. 在ArticleController中添加Add 方法 /// <summary> /// 添加文章 /// </summary> /// <returns>视图页面</returns> public ActionResult Add() { retur

ASP.NET MVC5网站开发显示文章列表(九)_实用技巧

老习惯,先上个效果图: 1.在IBLL在InterfaceCommonModelService接口中添加获取公共模型列表的方法 首先排序方法 /// <summary> /// 排序 /// </summary> /// <param name="entitys">数据实体集</param> /// <param name="roderCode">排序代码[默认:ID降序]</param> //