Note: This article is the author’s original, but can be reproduced freely. If you have any questions or mistake, welcome to communicate with the author, the original address: www.cnblogs.com/lyosaki88/p…

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

I took time to update the SAMPLE CODE today. I hosted the code on CODEPLEX. Welcome to download. identityiiemailconfirmation.codeplex.com/\

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

A week ago, on March 20, Microsoft released Asp.Net Identity 2.0 RTM. More powerful and more stable. The current version of Identity is still relatively low, and there will be more changes every time a new version is released.

There are many new features in 2.0, such as

  • “Two-factor authentication (TFA)” – that’s something like encrypted login
  • “Account lock” – you can set your account to be blocked from logging in for a few minutes if it fails a certain number of times within a short period of time
  • “Account authentication” — that is, now the common login mode, the user name is the mailbox, registration after the authentication can be logged in
  • “Password retrieval” — a common feature that has not been integrated into Identity before
  • Single sign-off (SSO) — When several pages are open at the same time, exiting on any page invalidates tokens on the other pages, making it impossible to perform operations under the account
  • “Primary key change” – In version 1.0 the primary key of the user table was a string username. Now you can set any primary key, such as int,Guid, etc
  • Set Query – Supports querying the Users and Roles tables as a set
  • “Delete account” – this function can now be implemented using the UserManager management class. It used to be cumbersome to manipulate tables directly only through dbContext
  • “Enhanced password rules” – at the time of registration, you can set password rules, including digits, whether to uppercase letters, whether to lowercase letters, whether to numbers, whether to special symbols, etc., the rules are more powerful

More please refer to the official blog blogs.msdn.com/b/webdev/ar…

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

Of course, we need to write specific codes to realize the above functions, such as third-party login. Identity only provides the basic scaffolding.

Below, I will implement the authentication function of his registered account based on the new scaffolding of Identity 2.0. That is, after registering with the mailbox, the system will send an email to the user’s mailbox, and the user can log in only after opening the mailbox and clicking the hyperlink to activate the account.

First of all, when you get something new, of course, you look at the document, and then download the Sample to see how the basic function is implemented.

For the official installation method of Sample, use VS to open the menu “Tools “–” NuGet Package Manager “– “Package Manager console”, After open the output “Install – Package Microsoft. AspNet. Identity. Samples – Version 2.0.0 – beta 2 – Pre”. The program will then automatically install Sample for you, during which time if your other nuget packages are too old, or there are duplicate files, you will be prompted to update, etc. You may need to type Y and press Enter. Another thing to note: The SAMPLE package needs to be installed in an Empty MVC project.

The scaffolding content and organization structure of 2.0 is more complex than before, and you can see the basic content of the sample program, which will not be described here. The following describes only the changes required to implement the mailbox authentication function.

Tip: This example requires a basic understanding of Identity and is best read with the Sample Code of Identity 2.0.

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

1. Configure the SMTP service

To send mail to registered users, first of all we need to have a mail, here can casually get a QQ mailbox and so on. The configuration can be written directly in code, but for configuration purposes, we write it to web.config,

  

1 <configSections> 2 ... 3 <sectionGroup name="application"> 4 ... 5 <section name="mail" type="DotNetRocks.Web.Configurations.MailConfig" allowLocation="true" 6 allowDefinition="Everywhere" requirePermission="false" /> 7 ... 8 </sectionGroup> 9 ... 10 </configSections> 11 ... 12 <application> 13 ... 14 <! <mail requireValid="true" server="smtp.qq.com" port="25" uid="[email protected]" pwd="yourpassword" enableSSL="false" enablePwdCheck="false" /> 16 ... 17 </application> 18 ...Copy the code

Web.Config

 

In the code above, in order to customize the configuration nodes, we need to declare our custom nodes in the configSections node. In this case, we have a custom set of nodes called application. We can then configure the application node group in detail below, where the Mail node is the mailbox configuration associated with SMTP. The most important attributes are the SMTP server address, port number (25 by default), and your email account and password. Other content can be configured according to your needs.

The configuration is written and used in a program by simply reading the data in it. We need to read the configuration into a model, so create a new “Configurations” folder and create a new “MailConfig” class that inherits the ConfigurationSection class.

  

1 public class MailConfig : ConfigurationSection 2 {3 /// <summary> 4 /// </summary> 6 [ConfigurationProperty("requireValid", DefaultValue = "false", IsRequired = true)] 7 public bool RequireValid 8 { 9 get 10 { 11 return (bool)this["requireValid"]; 12 } 13 set 14 { 15 this["requireValid"] = value; /// </summary> 21 [ConfigurationProperty("server", IsRequired = true)] 22 public string Server 23 { 24 get 25 { 26 return (string)this["server"]; 27 } 28 set 29 { 30 this["server"] = value; 35 /// </summary> 36 [ConfigurationProperty("port", DefaultValue = "25", IsRequired = true)] 37 public int Port 38 { 39 get 40 { 41 return (int)this["port"]; 42 } 43 set 44 { 45 this["port"] = value; 50 /// </summary> 50 // </summary> 51 [ConfigurationProperty(" UID ", IsRequired = true)] 52 public string Uid 53 { 54 get 55 { 56 return (string)this["uid"]; 57 } 58 set 59 { 60 this["uid"] = value; 61 /// </summary> 64 /// </summary> 66 [ConfigurationProperty(" PWD ", IsRequired = true)] 67 public string Pwd 68 { 69 get 70 { 71 return (string)this["pwd"]; 72 } 73 set 74 { 75 this["pwd"] = value; /// </summary> 81 [ConfigurationProperty("enableSSL", DefaultValue = "false", IsRequired = false)] 82 public bool EnableSSL 83 { 84 get 85 { 86 return (bool)this["enableSSL"]; 87 } 88 set 89 { 90 this["enableSSL"] = value; 91 } 92 } 93 /// <summary> 94 /// 95 /// </summary> 96 [ConfigurationProperty("enablePwdCheck", DefaultValue = "false", IsRequired = false)] 97 public bool EnablePwdCheck 98 { 99 get 100 { 101 return (bool)this["enablePwdCheck"]; 102 } 103 set 104 { 105 this["enablePwdCheck"] = value; 107 106}}Copy the code

MailConfig

When use, only need MailConfig config = (MailConfig) ConfigurationManager. GetSection (” application/mail “); The configuration properties can be read. For more details, refer to MSDN by pressing F1 in the ConfigurtaionSection.

 

2. Configuration UserManager

In the project scaffolding, there is an identityconfig. cs file in the App_Start folder. Open it and there is an ApplicationUserManage class that inherits UserManager<ApplicationUser>. (If you haven’t changed the file structure, of course, you can adjust the entire file organization as needed).

There are many things you can configure in ApplicationUserManager, such as account locking rules, password strength rules, encrypted logins, and so on. Manager.emailservice = new EmailService(); And the EmailService class is in this file, which inherits IIdentityMessageService interface. There is only one method in this interface, SendAsync, which is to send mail. We only need to implement the logic of sending mail in this method. This method is automatically called by UserManager when a message needs to be sent.

  

1 /// </summary> 1 // </summary> 2 /// IIdentityMessageService 5 { 6 public async Task SendAsync(IdentityMessage message) 7 { 8 MailConfig mailConfig = (MailConfig)ConfigurationManager.GetSection("application/mail"); 9 if (mailconfig. RequireValid) 10 {11 var mail = new MailMessage(13 new MailAddress(mailconfig. Uid, "no-reply"), 14 new MailAddress(message.Destination) 15 ); 16 mail.Subject = message.Subject; 17 mail.Body = message.Body; 18 mail.IsBodyHtml = true; 19 mail.BodyEncoding = Encoding.UTF8; 20 // Set the SMTP Server. 21 var SMTP = new SmtpClient(mailconfig. Server, mailconfig.port); 22 smtp.Credentials = new System.Net.NetworkCredential(mailConfig.Uid, mailConfig.Pwd); 23 24 await smtp.SendMailAsync(mail); 25 } 26 await Task.FromResult(0); 28 27}}Copy the code

MailService

The above code is simple to implement the mail sending logic, of course, there can be more complex policies, such as whether to use SSL connections, etc. I have not configured here. For more information about email, see systemnetmail.com/

So I’ll write the code here, run the program, try to register the new user, and if the email configuration is correct, the new user should already be able to receive emails from the system. But now even if the mailbox is not verified can also login, need to achieve their own mailbox not verified login function.

 

3. Change the Login policy

First of all, in the registration function, for the convenience of testing, the jump page after registration directly provides the connection to activate the mailbox, which needs to be deleted if it is officially running. We only need to send the connection to the user’s mailbox.

At login, the PasswordSignIn method in SingInHelper is uniformly called, and an enumeration of type SignInStatus is returned to determine which page to return to the user. There is no mailbox in SignInStatus that is currently disabled. So we’re going to add one, like “InvalidEmail”. If the return is SignInStatus InvalidEmail, allow the user to jump to prompt email inactive interface. Add a case to the switch statement in the Login method, as shown below

  

1 public async Task<ActionResult> Login(LoginViewModel model, string returnUrl){ 2 //... 3 Switch (result) 4 {5 case SignInStatus.Success: 6 return RedirectToLocal(returnUrl); 7 case SignInStatus.LockedOut: 8 return View("Lockout"); 9 case SignInStatus.InvalidEmail: 10 return View("DisplayEmail"); 11 case SignInStatus.RequiresTwoFactorAuthentication: 12 return RedirectToAction("SendCode", new { ReturnUrl = returnUrl }); 13 case SignInStatus.Failure: 14 default: 15 ModelState.AddModelError("", "Invalid login attempt."); 16 return View(model); 18 17}}Copy the code

Login

Here, I jump directly to the DisplayEmail page, prompting the user to deactivate his mailbox, disable login, and ask him if he needs to send a verification email again. Of course, I made the necessary modifications on this page myself.

Then we need to add a policy to the PasswordSignIn method to enable it to return the InvalidEmail status value.

  

 1         public async Task<SignInStatus> PasswordSignIn(string userName, string password, bool isPersistent, bool shouldLockout)
 2         {
 3             var user = await UserManager.FindByNameAsync(userName);
 4             if (user == null)
 5             {
 6                 return SignInStatus.Failure;
 7             }
 8             if (await UserManager.IsLockedOutAsync(user.Id))
 9             {
10                 return SignInStatus.LockedOut;
11             }
12             if (!await UserManager.IsEmailConfirmedAsync(user.Id))
13             {
14                 return SignInStatus.InvalidEmail;
15             }
16             if (await UserManager.CheckPasswordAsync(user, password))
17             {
18                 return await SignInOrTwoFactor(user, isPersistent);
19             }
20             if (shouldLockout)
21             {
22                 // If lockout is requested, increment access failed count which might lock out the user
23                 await UserManager.AccessFailedAsync(user.Id);
24                 if (await UserManager.IsLockedOutAsync(user.Id))
25                 {
26                     return SignInStatus.LockedOut;
27                 }
28             }
29             return SignInStatus.Failure;
30         }
Copy the code

PasswordSignIn

 

In the above code, the logical order of user login before mailbox authentication is not added: 1. Determine whether the account exists, 2. Check whether the account is locked. 3. Check whether the account password is correct (if it is correct to log in directly, otherwise the number of failures +1); 4. According to the above logic, we should add mailbox authentication between 2 and 3, as in the above code, calling the IsEmailConfirmedAsync method of the UserManager to verify that the user’s mailbox is authenticated.

At this point, the entire functionality should be fully implemented.

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

This article is written in the second day after I have implemented, if there are omissions or errors in the steps, welcome to correct and add