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网站开发专题学习。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 解析JPA的视图查询问题
下一篇: IOS10 配置权限详细介绍