注:本文系作者原创,但可随意转载。若有任何疑问或错误,欢迎与原作者交流,原文地址:http://www.cnblogs.com/lyosaki88/p/aspnet-itentity-ii-emailconfirmed.html

==========================================================================================================

今天抽空更新了SAMPLE CODE。我把代码托管到了CODEPLEX平台。欢迎下载。 https://identityiiemailconfirmation.codeplex.com/

==========================================================================================================

  一个星期前,也就是3月20日,微软发布了Asp.Net Identity 2.0 RTM。功能更加强大,也更加稳定。Identity这个东西现在版本还比较低,每次发布新版本都会有较多改动。

  2.0新增了很多功能,比如

  • “双重认证(TFA)" --就是类似密保登陆的功能
  • ”账号锁定”--可以设置账号在短时间内登陆失败达到一定次数则在几分钟内被禁止登陆
  • “账号认证”--即现在普遍的登陆模式,用户名即邮箱,注册后需要认证才可以登陆
  • “密码找回”--这个常用功能以前一直未被集成到Identity中
  • “单点登出(SSO)”--也就是同时打开了几个页面,在任何页面退出,都会导致其他页面的TOKEN失效,从而不能进行账户下的操作
  • “主键变更”--在1.0版本中用户表的主键是string类型的用户名,现在可以设置任意类型的主键,如int,Guid 等
  • “集合查询”-- 支持以集合的方式查询Users和Roles表
  • “删除账号”--现在这个功能可以使用UserManager管理类来实现,过去只能通过dbContext直接操作数据表是很麻烦的
  • “增强密码规则”--在注册时,可以设置密码规则,包括位数,是否必须大写字母,是否必须小写字母,是否必须数字,是否必须特殊符号等,规则更加强大

其他更多功能请参考官方博客http://blogs.msdn.com/b/webdev/archive/2014/03/20/test-announcing-rtm-of-asp-net-identity-2-0-0.aspx

========================================================================================

  当然,上面的功能具体如何实现还需要我们来编写具体的代码,比如实现第三方登陆等,Identity只是给出了基本的脚手架。

  下面我基于Identity 2.0新的脚手架来实现他的 注册账号认证 功能,即使用邮箱注册后,系统发送邮件至用户邮箱,用户打开邮箱点击超链接激活账号后才可以登陆。

  首先,拿到新东西当然是看文档,然后下载Sample看下基本功能是如何实现的。

  官方给出的Sample的安装方法,使用VS 打开菜单 “工具”--》“NuGet程序包管理器"--》”程序包管理器控制台“,打开后输出”Install-Package Microsoft.AspNet.Identity.Samples -Version 2.0.0-beta2 –Pre“ 。然后程序会自动为你安装Sample程序,期间假如你的其他nuget包版本过低,或有重复的文件,会提示你更新等,你可能需要输入Y并按回车。另外需要注意的是:这个SAMPLE包需要安装在一个Empty的MVC项目中。

  2.0的脚手架内容和组织架构比以前更复杂,基本的内容您可以查看样板程序,此处不再赘述。下面仅讲解实现邮箱认证功能需要进行的改动。

  提示:此示例需要您对Identity有基本的了解,并配合Identity 2.0的Sample Code阅读效果更佳。

========================================================================================

1.配置smtp服务

  要发送邮件给注册用户,首先我们需要有个发件邮箱,这里可以随便弄个QQ邮箱之类的。配置的内容可以直接写死在代码里,但为了方便配置,我们把它写到Web.Config中,

  

 <configSections>
...
<sectionGroup name="application">
...
<section name="mail" type="DotNetRocks.Web.Configurations.MailConfig" allowLocation="true"
allowDefinition="Everywhere" requirePermission="false" />
...
</sectionGroup>
...
</configSections>
...
<application>
...
<!-- 测试时可将requireValid 设为false 则不进行邮箱验证-->
<mail requireValid="true" server="smtp.qq.com" port="25" uid="something@qq.com" pwd="yourpassword" enableSSL="false" enablePwdCheck="false" />
...
</application>
...

Web.Config

  上面的代码中,为了自定义配置节点,需要在configSections节点中,声明我们自定义的节点,这里我们自定义了一组节点叫application。然后我们就可以在下文中详细配置application节点组,其中的mail节点就是和smtp相关的邮箱配置。其中最主要的属性就是smtp服务器地址,端口号(一般默认25),和你的邮箱账号和密码。其他内容可以根据你的需要的策略自行配置。

  配置写好了,在程序中要使用时,只需读出其中的数据即可。我们需要将配置读到一个模型中,因此新建一个"Configurations"文件夹,并新建一个"MailConfig"类让它继承ConfigurationSection类,代码如下。

  

 public class MailConfig : ConfigurationSection
{
/// <summary>
/// 注册时是否需要验证邮箱
/// </summary>
[ConfigurationProperty("requireValid", DefaultValue = "false", IsRequired = true)]
public bool RequireValid
{
get
{
return (bool)this["requireValid"];
}
set
{
this["requireValid"] = value;
}
}
/// <summary>
/// SMTP服务器
/// </summary>
[ConfigurationProperty("server", IsRequired = true)]
public string Server
{
get
{
return (string)this["server"];
}
set
{
this["server"] = value;
}
}
/// <summary>
/// 默认端口25(设为-1让系统自动设置)
/// </summary>
[ConfigurationProperty("port", DefaultValue = "", IsRequired = true)]
public int Port
{
get
{
return (int)this["port"];
}
set
{
this["port"] = value;
}
}
/// <summary>
/// 账号
/// </summary>
[ConfigurationProperty("uid", IsRequired = true)]
public string Uid
{
get
{
return (string)this["uid"];
}
set
{
this["uid"] = value;
}
}
/// <summary>
/// 密码
/// </summary>
[ConfigurationProperty("pwd", IsRequired = true)]
public string Pwd
{
get
{
return (string)this["pwd"];
}
set
{
this["pwd"] = value;
}
}
/// <summary>
/// 是否使用SSL连接
/// </summary>
[ConfigurationProperty("enableSSL", DefaultValue = "false", IsRequired = false)]
public bool EnableSSL
{
get
{
return (bool)this["enableSSL"];
}
set
{
this["enableSSL"] = value;
}
}
/// <summary>
///
/// </summary>
[ConfigurationProperty("enablePwdCheck", DefaultValue = "false", IsRequired = false)]
public bool EnablePwdCheck
{
get
{
return (bool)this["enablePwdCheck"];
}
set
{
this["enablePwdCheck"] = value;
}
}

MailConfig

  在使用时,只需要MailConfig config = (MailConfig)ConfigurationManager.GetSection("application/mail"); 即可读取到配置属性,更详细的内容可以在ConfigurtaionSection上按F1参考MSDN。

2.配置UserManager

  在项目脚手架中,App_Start文件夹下有个IdentityConfig.cs文件,打开他,其中有一个继承了UserManager<ApplicationUser>的ApplicationUserManage类。(如果你没有变更文件结构的话,当然你可以根据需求自行调整整个文件组织结构)。

  在ApplicationUserManager中可以配置的东西很多,比如账号锁定规则,密码强度规则,密保登陆等。其中还有一句manager.EmailService = new EmailService();, 而这个EmailService类就在本文件中,他继承了IIdentityMessageService接口,这个接口总共只有一个方法SendAsync,也就是发送邮件,我们只需要在这个方法中实现发送邮件的逻辑,在需要发送邮件时UserManager会自动调用该方法。

  

     /// <summary>
/// 邮箱验证Service
/// </summary>
public class EmailService : IIdentityMessageService
{
public async Task SendAsync(IdentityMessage message)
{
MailConfig mailConfig = (MailConfig)ConfigurationManager.GetSection("application/mail");
if (mailConfig.RequireValid)
{
// 设置邮件内容
var mail = new MailMessage(
new MailAddress(mailConfig.Uid, "no-reply"),
new MailAddress(message.Destination)
);
mail.Subject = message.Subject;
mail.Body = message.Body;
mail.IsBodyHtml = true;
mail.BodyEncoding = Encoding.UTF8;
// 设置SMTP服务器
var smtp = new SmtpClient(mailConfig.Server, mailConfig.Port);
smtp.Credentials = new System.Net.NetworkCredential(mailConfig.Uid, mailConfig.Pwd); await smtp.SendMailAsync(mail);
}
await Task.FromResult();
}
}

MailService

  上面这段代码简单的实现了邮件发送逻辑,当然也可以有更复杂的策略,比如是否使用SSL连接等此处我并未配置。关于电子邮件的相关知识可以参考:http://systemnetmail.com/

  代码写到这里,运行程序,尝试注册新用户,如果邮箱配置没有问题的话,新用户应该已经可以收到系统发来的邮件了。不过现在即使未验证邮箱也可以登陆,需要自己实现未验证邮箱禁止登陆的功能。

3.变更Login策略

  首先说一下,在注册功能中,为了方便测试,注册后跳转的页面直接提供了激活邮箱的连接,正式运行的话需要把它删除,我们只需要把该连接发送到用户邮箱即可。

  在登陆时,统一调用的是SingInHelper中的PasswordSignIn方法,然后返回枚举类型的SignInStatus,来决定将哪个页面返回给用户。现在SignInStatus中并没有邮箱未验证禁止登陆的状态。因此我们要在其中加一个,比如叫”InvalidEmail"。如果返回的是SignInStatus.InvalidEmail,则让用户跳转到提示邮箱未激活的界面。也就是在Login方法中的switch语句中加一个case,如下图

  

 public async Task<ActionResult> Login(LoginViewModel model, string returnUrl){
//...此处省略若干代码
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.InvalidEmail:
return View("DisplayEmail");
case SignInStatus.RequiresTwoFactorAuthentication:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}

Login

  这里,我直接跳转到DisplayEmail页面,提示用户未激活邮箱,禁止登陆,并询问他是否需要再次发送验证邮件。当然这个页面我自己做了需要的修改。

  然后我们需要在PasswordSignIn方法中也加入相应的策略以使它能够返回InvalidEmail状态值。

  

         public async Task<SignInStatus> PasswordSignIn(string userName, string password, bool isPersistent, bool shouldLockout)
{
var user = await UserManager.FindByNameAsync(userName);
if (user == null)
{
return SignInStatus.Failure;
}
if (await UserManager.IsLockedOutAsync(user.Id))
{
return SignInStatus.LockedOut;
}
if (!await UserManager.IsEmailConfirmedAsync(user.Id))
{
return SignInStatus.InvalidEmail;
}
if (await UserManager.CheckPasswordAsync(user, password))
{
return await SignInOrTwoFactor(user, isPersistent);
}
if (shouldLockout)
{
// If lockout is requested, increment access failed count which might lock out the user
await UserManager.AccessFailedAsync(user.Id);
if (await UserManager.IsLockedOutAsync(user.Id))
{
return SignInStatus.LockedOut;
}
}
return SignInStatus.Failure;
}

PasswordSignIn

  在上面的代码中,未加邮箱验证前,用户登录后的逻辑顺序,1.判断是否存在该账号,2.判断该账号是否锁定,3.检测账号密码是否正确(若正确直接登陆,否则失败次数+1),4(若走到这一步则说明账号密码错误)检测是否需要锁定账号,5返回登陆失败。根据上面的逻辑,我们应该把邮箱验证加到2和3之间,也就是如上图代码中调用UserManager的IsEmailConfirmedAsync方法,来验证用户邮箱是否认证。

  至此,整个功能应该已经全部实现了。

================================================================================

  此文是在我已经实现后第二天所写,若步骤有遗漏或错误,欢迎指正补充

  

  

  

使用Asp.Net Identity 2.0 认证邮箱激活账号(附DEMO)的更多相关文章

  1. Asp.Net Identity 2.0 认证

    转Asp.Net Identity 2.0 认证 一个星期前,也就是3月20日,微软发布了Asp.Net Identity 2.0 RTM.功能更加强大,也更加稳定.Identity这个东西现在版本还 ...

  2. asp.net identity 3.0.0 在MVC下的基本使用 序言

    本人也尚在学习使用之中,错误之处请大家指正. 开发环境:vs2015 UP1   项目环境:asp.net 4.6.1   模板为:asp.net 5 模板     identity版本为:asp.n ...

  3. MVC使用ASP.NET Identity 2.0实现用户身份安全相关功能,比如通过短信或邮件发送安全码,账户锁定等

    本文体验在MVC中使用ASP.NET Identity 2.0,体验与用户身份安全有关的功能: →install-package Microsoft.AspNet.Identity.Samples - ...

  4. ASP.NET Identity 3.0教程

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:我相信有些人和我一样,已经开始把ASP.NET 5用于产品开发了.不过现在最大的问题是 ...

  5. Asp.Net Core基于JWT认证的数据接口网关Demo

    近日,应一位朋友的邀请写了个Asp.Net Core基于JWT认证的数据接口网关Demo.朋友自己开了个公司,接到的一个升级项目,客户要求用Aps.Net Core做数据网关服务且基于JWT认证实现对 ...

  6. Asp.net Identity 2.0 作弊条

    Moving ASP.NET Identity model to class library http://stackoverflow.com/questions/23446919/moving-as ...

  7. ASP.net core 2.0.0 中 asp.net identity 2.0.0 的基本使用(一)—修改数据库连接

    开发环境:vs2017  版本:15.3.5 项目环境:.net framework 4.6.1    模板asp.net core 2.0  Web应用程序(模型视图控制器) 身份验证:个人用户账号 ...

  8. asp.net mvc 注册中的邮箱激活功能实现(一)

    基本流程图 注册页面就不再写出,现在将发送邮件的代码粘贴出来 public ActionResult SendEmial() { ; string validataCode = System.Guid ...

  9. asp.net mvc 注册中的邮箱激活功能实现

    基本流程图 注册页面就不再写出,现在将发送邮件的代码粘贴出来   public ActionResult SendEmial() { ; string validataCode = System.Gu ...

随机推荐

  1. python核心编程2 第八章 练习

    8–2. 循环. 编写一个程序, 让用户输入三个数字: (f)rom, (t)o, 和 (i)ncrement . 以 i为步长, 从 f 计数到 t , 包括 f 和 t . 例如, 如果输入的是 ...

  2. TCL之表达式

  3. Laravel5.5.x集成Swagger (L5-Swagger) 只讲Laravel5.5.x的集成,laravel其他版本请自行研究或参考github上的说明

    --------上图 截取自Github 官网上的安装参考----------------------------------------------------------------------- ...

  4. Spark Streaming 交互 Kafka的两种方式

    一.Spark Streaming连Kafka(重点) 方式一:Receiver方式连:走磁盘 使用High Level API(高阶API)实现Offset自动管理,灵活性差,处理数据时,如果某一时 ...

  5. mysql8.0 忘记root密码

    先打开一个cmd:net stop mysql //关闭mysql服务mysqld --shared-memory --skip-grant-tables//跳过登录密码在不关闭第一个CMD的情况下打 ...

  6. B1018 锤子剪刀布 (20分)

    B1018 锤子剪刀布 (20分) 大家应该都会玩"锤子剪刀布"的游戏:两人同时给出手势. 现给出两人的交锋记录,请统计双方的胜.平.负次数,并且给出双方分别出什么手势的胜算最大. ...

  7. opencv 图像的线性混合

    1 线性混合理论 g(x) = (1-α)*f1(x) + α*f2(x) 其中,α代表图像的权重 #include<iostream> #include<opencv2/openc ...

  8. ACM 最大化平均值问题总结

    主要是应用c(x)的满足条件有共通之处: c(x)表示要求解的那个表达式不小于x 可以找到表达式 v/w>=x 如果 v-x*w>0 说明有贡献 那就把贡献最大的找出来 如果找出来之后 s ...

  9. Android 第三方库RxLifecycle使用

    1.简单介绍RxLifecycle 1.1.使用原因. 在使用rxjava的时候,如果没有及时解除订阅,在退出activity的时候,异步线程还在执行. 对activity还存在引用,此时就会产生内存 ...

  10. Sql Server多种分页性能的比较

    一.前言 因为工作关系,遇到了非常大的数据量的分页问题,数据总共有8000万吧,这个显然不是简单的分页能够解决的,需要从多多方面考虑,从分表.分库等等.但是这个也让我考虑到了分页性能的问题,在不同数据 ...