一、默认Web项目的更改
用户这部分还是自己做,所以删除自动生成的用户相关代码。
二、添加Member区域
在web项目上点右键 添加 区域Member。
添加Home控制器,选择MVC5控制器-空
我们给public ActionResult Index()添加一个视图,代码很简单就是显示下用户名
@{
ViewBag.Title = \"会员中心\";
}
<h2>欢迎你!@User.Identity.Name
</h2>
我们先运行一下,出错啦。
这是因为项目中有两个名为Home的控制器,必须在路由中加上命名空间。先打开区域中的MemberAreaRegistration添加命名空间。
再打开项目中的RouteConfig,添加命名空间
再刷新浏览器,可以正常显示。
再添加用户控制器UserController。
三、模型类的更改
在这里先对Models项目User模型进行修改,原来考虑的是每个用户只能属于一个用户组,后来仔细考虑了一下,还是不太合适,比如一个用户兼任多个角色,所以还是把用户和用户组改成一对多的关系。
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();
本文地址:https://www.stayed.cn/item/19104
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我