Asp.Net.Identity authentication does not depend on Entity Framework implementation

Keywords: ASP.NET SQL Database Mobile

Please search for Asp.Net.Identity by yourself or turn to this article. http://www.cnblogs.com/shanyou/p/3918178.html

Microsoft has already handled authorization, authentication and database storage for us. But there is always such a situation, such as our project now has a database, and the library has users, roles and other information tables, but

We are still greedy to use Microsoft's authorization and authentication library. Here I come to practice whether it is feasible or not.

The first step is to build a new web project of Asp.Net MVC framework

Second, install Microsoft.AspNet.Identity, Microsoft.AspNet.Identity.Owin on Nuget

Microsoft.AspNet.Identity.Owin has dependencies, and it relies on these packages:

Microsoft. Owin. Security. OAuth -- MSDN annotation: Contains types associated with the OAuth provider. (For more information, refer to https://msdn.microsoft.com/zh-cn/library/microsoft.owin.security.oauth(v=vs.111).aspx)

Microsoft. Owin. Security. Cookies MSDN annotation: Provides types related to identity cookies. (For more information, refer to https://msdn.microsoft.com/zh-cn/library/microsoft.owin.security.cookies(v=vs.111).aspx)

Microsoft.Owin.Security.MSDN annotation: Contains authentication-related types. (For more information, refer to https://msdn.microsoft.com/zh-cn/library/microsoft.owin.security(v=vs.111).aspx)

Microsoft.AspNet.Identity.Core MSDN Annotation: Contains classes and interfaces related to users and roles managing ASP.NET Identity.

(Information reference: https://msdn.microsoft.com/library/microsoft.aspnet.identity(v=vs.111).aspx)

From the annotations of MSDN, it can be seen that Microsoft.AspNet.Identity.Owin is actually the encapsulation of API s needed for website login and business scenario registration.

Part Three: Modeling

If the user table of my current database is BASE_USER, the structure of the table is as follows

CREATE TABLE [dbo].[BASE_USER](
	[ID] [uniqueidentifier] NOT NULL PRIMARY KEY,
	[NAME] [varchar](50) NOT NULL,
	[PWD] [varchar](50) NOT NULL,
) ON [PRIMARY]

  

We create a new BASE_USER class in the Models folder of the engineering site, which inherits Microsoft. AspNet. Identity. IUser < GUID>. Here we add a nickname field of NICKNAME that does not exist in the data table, and see what effect it will have later.

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 
 6 namespace IdeintityDemo.Models
 7 {
 8     public class BASE_USER : Microsoft.AspNet.Identity.IUser<Guid>
 9     {
10         /// <summary>
11         /// User number
12         /// </summary>
13         public Guid Id { get; set; }
14         /// <summary>
15         /// User name
16         /// </summary>
17         public string UserName { get; set; }
18         /// <summary>
19         /// Password
20         /// </summary>
21         public string PWD { get; set; }
22         /// <summary>
23         /// Nickname?
24         /// </summary>
25         public string NickName { get; set; }
26 
27         public bool RememberMe { get; set; }
28     }
29 }

 

The fourth part creates the UserStore class, which implements the api that users store in the database by inheriting the interface IUserStore.

  1 using Microsoft.AspNet.Identity;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Data;
  5 using System.Data.SqlClient;
  6 using System.Linq;
  7 using System.Threading.Tasks;
  8 using System.Web;
  9 using System.Security.Claims;
 10 using IdeintityDemo.Models;
 11 using IdeintityDemo.Common;
 12 
 13 namespace IdeintityDemo.Identity
 14 {
 15 
 16     /// <summary>
 17     /// User persistent storage objects
 18     /// Must achieve Microsoft.AspNet.Identity Corresponding interface, otherwise in SignInManager Class login verification process
 19     /// An exception that does not implement the relevant interface will pop up!   
 20     /// IUserStore:Detect the existence of an account
 21     /// IUserPasswordStore:Check password
 22     /// IUserLockoutStore:Locking Account Related Operations
 23     /// IUserClaimStore:Store user-specific declarations
 24     /// IUserEmailStore: Mailbox association, validation and other related operations
 25     /// IUserPhoneNumberStore:Mobile Phone Association and Verification Related Operations
 26     /// IUserTwoFactorStore: Gets or sets the method of user dual authentication.
 27     /// </summary>
 28     public class HsUserStore : Microsoft.AspNet.Identity.IUserStore<BASE_USER, Guid>,
 29                                Microsoft.AspNet.Identity.IUserPasswordStore<BASE_USER, Guid>,
 30                                Microsoft.AspNet.Identity.IUserLockoutStore<BASE_USER, Guid>,
 31                                Microsoft.AspNet.Identity.IUserClaimStore<BASE_USER, Guid>,
 32                                Microsoft.AspNet.Identity.IUserEmailStore<BASE_USER, Guid>,
 33                                Microsoft.AspNet.Identity.IUserPhoneNumberStore<BASE_USER, Guid>,
 34                                Microsoft.AspNet.Identity.IUserTwoFactorStore<BASE_USER, Guid>
 35     {
 36 
 37         /// <summary>
 38         /// statement
 39         /// </summary>
 40         public IList<System.Security.Claims.Claim> Claims = null;
 41         /// <summary>
 42         /// user
 43         /// </summary>
 44         public BASE_USER UserIdentity = null;
 45 
 46         /// <summary>
 47         /// instantiation
 48         /// </summary>
 49         public HsUserStore()
 50         {
 51             //statement
 52             Claims = new List<System.Security.Claims.Claim>();
 53         }
 54         /// <summary>
 55         /// Create user
 56         /// </summary>
 57         /// <param name="user"></param>
 58         /// <returns></returns>
 59         public Task CreateAsync(BASE_USER user)
 60         {
 61             return Task.Run(() => {
 62                 string sql = @"INSERT INTO [dbo].[BASE_USER]([ID],[NAME],[PWD])
 63                         VALUES(@UserID,@name,@pwd)";
 64                 SqlParameter[] parameters = {
 65                      new SqlParameter("@UserID", Guid.NewGuid()),
 66                      new SqlParameter("@name", user.UserName),
 67                      new SqlParameter("@pwd", user.PWD)
 68                 };
 69                 int iResult = DbHelperSQL.ExecuteSql(sql, parameters);
 70             });
 71         }
 72         /// <summary>
 73         /// delete user
 74         /// </summary>
 75         /// <param name="user"></param>
 76         /// <returns></returns>
 77         public Task DeleteAsync(BASE_USER user)
 78         {
 79             return Task.Run(() => {
 80                 string sql = @"DELETE FROM [dbo].[BASE_USER] WHERE ID=@ID";
 81                 SqlParameter[] parameters = {
 82                      new SqlParameter("@UserID", user.Id)};
 83                 int iResult = DbHelperSQL.ExecuteSql(sql, parameters);
 84             });
 85         }
 86         /// <summary>
 87         /// According to users id Get users
 88         /// </summary>
 89         /// <param name="userId"></param>
 90         /// <returns></returns>
 91         public Task<BASE_USER> FindByIdAsync(Guid userId)
 92         {
 93             return Task<BASE_USER>.Run(() =>
 94              {
 95                  BASE_USER result = new BASE_USER();
 96                  string sql = @"SELECT * FROM [dbo].[BASE_USER] WHERE ID=@ID";
 97                  SqlParameter[] parameters = {
 98                      new SqlParameter("@ID", userId)};
 99                  DataSet ds = DbHelperSQL.Query(sql, parameters);
100                  if (ds == null || ds.Tables == null || ds.Tables[0].Rows.Count <= 0)
101                      return result;
102                  //model
103                  DataRow dr = ds.Tables[0].Rows[0];
104                  result.Id = Guid.Parse(dr["ID"].ToString());
105                  result.UserName = dr["NAME"].ToString();
106                  result.PWD = dr["PWD"].ToString();
107                  return result;
108              });
109         }
110         /// <summary>
111         /// Get user information by name
112         /// </summary>
113         /// <param name="userName"></param>
114         /// <returns></returns>
115         public Task<BASE_USER> FindByNameAsync(string userName)
116         {
117             return Task<BASE_USER>.Run(() =>
118             {
119                 BASE_USER result = new BASE_USER();
120                 string sql = @"SELECT * FROM [dbo].[BASE_USER] WHERE NAME=@NAME";
121                 SqlParameter[] parameters = {
122                      new SqlParameter("@NAME", userName)};
123                 DataSet ds = DbHelperSQL.Query(sql, parameters);
124                 if (ds == null || ds.Tables == null || ds.Tables[0].Rows.Count <= 0)
125                     return result;
126                 //model
127                 DataRow dr = ds.Tables[0].Rows[0];
128                 result.Id = Guid.Parse(dr["ID"].ToString());
129                 result.UserName = dr["NAME"].ToString();
130                 result.PWD = dr["PWD"].ToString();
131 
132                 return result;
133             });
134         }
135         /// <summary>
136         /// Update user
137         /// </summary>
138         /// <param name="user"></param>
139         /// <returns></returns>
140         public Task UpdateAsync(BASE_USER user)
141         {
142             return Task.Run(() =>
143             {
144                 //ellipsis...
145             });
146         }
147         /// <summary>
148         /// Asynchronously returns the number of current failed access attempts. This number is usually reset when the password is verified or the account is locked.
149         /// (Here, because I did not do this piece of record preservation in the database, so I first write to death and return to 1.)
150         /// </summary>
151         /// <param name="user">user</param>
152         /// <returns></returns>
153         public Task<int> GetAccessFailedCountAsync(BASE_USER user)
154         {
155             return Task.FromResult<int>(1);
156         }
157         /// <summary>
158         /// Get the lock state
159         /// </summary>
160         /// <param name="user"></param>
161         /// <returns></returns>
162         public Task<bool> GetLockoutEnabledAsync(BASE_USER user)
163         {
164             return Task.FromResult<bool>(false);
165         }
166         /// <summary>
167         /// Get the lock end time
168         /// </summary>
169         /// <param name="user"></param>
170         /// <returns></returns>
171         public Task<DateTimeOffset> GetLockoutEndDateAsync(BASE_USER user)
172         {
173             throw new NotImplementedException();
174         }
175         /// <summary>
176         /// Records of failed attempts to access users.
177         /// </summary>
178         /// <param name="user"></param>
179         /// <returns></returns>
180         public Task<int> IncrementAccessFailedCountAsync(BASE_USER user)
181         {
182             return Task.FromResult<int>(1);
183         }
184         /// <summary>
185         /// Reset access failure count, usually after successful account access
186         /// </summary>
187         /// <param name="user"></param>
188         /// <returns></returns>
189         public Task ResetAccessFailedCountAsync(BASE_USER user)
190         {
191             return Task.FromResult(false);
192         }
193         /// <summary>
194         /// Whether asynchronous settings can lock users.
195         /// </summary>
196         /// <param name="user"></param>
197         /// <param name="enabled"></param>
198         /// <returns></returns>
199         public Task SetLockoutEnabledAsync(BASE_USER user, bool enabled)
200         {
201             return Task.Run(() => { });
202         }
203         /// <summary>
204         /// Lock the user asynchronously until the specified end date
205         /// </summary>
206         /// <param name="user"></param>
207         /// <param name="lockoutEnd"></param>
208         /// <returns></returns>
209         public Task SetLockoutEndDateAsync(BASE_USER user, DateTimeOffset lockoutEnd)
210         {
211             return Task.Run(() =>
212             {
213 
214             });
215         }
216         /// <summary>
217         /// Get the user password
218         /// </summary>
219         /// <param name="user"></param>
220         /// <returns></returns>
221         public Task<string> GetPasswordHashAsync(BASE_USER user)
222         {
223             return Task<string>.Run(() =>
224             {
225                 return user.PWD;
226             });
227         }
228         /// <summary>
229         /// Is there a password?
230         /// </summary>
231         /// <param name="user"></param>
232         /// <returns></returns>
233         public Task<bool> HasPasswordAsync(BASE_USER user)
234         {
235             return Task.FromResult<bool>(!string.IsNullOrEmpty(user.PWD));
236         }
237         /// <summary>
238         /// Password Encryption
239         /// </summary>
240         /// <param name="user"></param>
241         /// <param name="passwordHash"></param>
242         /// <returns></returns>
243         public Task SetPasswordHashAsync(BASE_USER user, string passwordHash)
244         {
245             return Task.Run(() =>
246             {
247                 user.PWD = passwordHash;//After encryption
248             });
249         }
250         /// <summary>
251         /// Add a declaration
252         /// </summary>
253         /// <param name="user"></param>
254         /// <param name="claim"></param>
255         /// <returns></returns>
256         public Task AddClaimAsync(BASE_USER user, Claim claim)
257         {
258             return Task.Run(() => { Claims.Add(claim); });
259         }
260         /// <summary>
261         /// Get all the declarations of the modified user
262         /// </summary>
263         /// <param name="user"></param>
264         /// <returns></returns>
265         public Task<IList<Claim>> GetClaimsAsync(BASE_USER user)
266         {
267             return Task.Run<IList<System.Security.Claims.Claim>>(() =>
268             {
269                 IList<System.Security.Claims.Claim> list = new List<System.Security.Claims.Claim>();
270                 return list;
271             });
272         }
273         /// <summary>
274         /// Remove declaration
275         /// </summary>
276         /// <param name="user"></param>
277         /// <param name="claim"></param>
278         /// <returns></returns>
279         public Task RemoveClaimAsync(BASE_USER user, Claim claim)
280         {
281             return Task.Run(() =>
282             {
283 
284             });
285         }
286         /// <summary>
287         /// Getting the corresponding user information through mailbox
288         /// </summary>
289         /// <param name="email"></param>
290         /// <returns></returns>
291         public Task<BASE_USER> FindByEmailAsync(string email)
292         {
293             return Task<BASE_USER>.Run(() => new BASE_USER());
294         }
295         /// <summary>
296         /// Get mailbox
297         /// </summary>
298         /// <param name="user"></param>
299         /// <returns></returns>
300         public Task<string> GetEmailAsync(BASE_USER user)
301         {
302             return Task<string>.Run(() => string.Empty);
303         }
304         /// <summary>
305         /// Confirm email
306         /// </summary>
307         /// <param name="user"></param>
308         /// <returns></returns>
309         public Task<bool> GetEmailConfirmedAsync(BASE_USER user)
310         {
311             return Task.FromResult<bool>(true);
312         }
313         /// <summary>
314         /// Modify mailbox
315         /// </summary>
316         /// <param name="user"></param>
317         /// <param name="email"></param>
318         /// <returns></returns>
319         public Task SetEmailAsync(BASE_USER user, string email)
320         {
321             return Task.Run(() => { });
322         }
323         /// <summary>
324         ///Set whether the user is email confirmation or not 
325         /// </summary>
326         /// <param name="user"></param>
327         /// <param name="confirmed"></param>
328         /// <returns></returns>
329         public Task SetEmailConfirmedAsync(BASE_USER user, bool confirmed)
330         {
331             throw new NotImplementedException();
332         }
333         /// <summary>
334         /// Get a contact number
335         /// </summary>
336         /// <param name="user"></param>
337         /// <returns></returns>
338         public Task<string> GetPhoneNumberAsync(BASE_USER user)
339         {
340             return Task.FromResult<string>(string.Empty);
341         }
342         /// <summary>
343         /// Get whether the user's phone number has been confirmed
344         /// </summary>
345         /// <param name="user"></param>
346         /// <returns></returns>
347         public Task<bool> GetPhoneNumberConfirmedAsync(BASE_USER user)
348         {
349             return Task.FromResult<bool>(true);
350         }
351         /// <summary>
352         /// Setting User Telephone Number
353         /// </summary>
354         /// <param name="user"></param>
355         /// <param name="phoneNumber"></param>
356         /// <returns></returns>
357         public Task SetPhoneNumberAsync(BASE_USER user, string phoneNumber)
358         {
359             return Task.Run(() => { });
360         }
361         /// <summary>
362         /// Setting the phone number associated with the user
363         /// </summary>
364         /// <param name="user"></param>
365         /// <param name="confirmed"></param>
366         /// <returns></returns>
367         public Task SetPhoneNumberConfirmedAsync(BASE_USER user, bool confirmed)
368         {
369             return Task.Run(() => { });
370         }
371         /// <summary>
372         /// Is dual authentication enabled for users?
373         /// </summary>
374         /// <param name="user"></param>
375         /// <returns></returns>
376         public Task<bool> GetTwoFactorEnabledAsync(BASE_USER user)
377         {
378             return Task.FromResult<bool>(false);
379         }
380         /// <summary>
381         /// Setting up dual authentication
382         /// </summary>
383         /// <param name="user"></param>
384         /// <param name="enabled"></param>
385         /// <returns></returns>
386         public Task SetTwoFactorEnabledAsync(BASE_USER user, bool enabled)
387         {
388             throw new NotImplementedException();
389         }
390         /// <summary>
391         /// release
392         /// </summary>
393         public void Dispose()
394         {
395             throw new NotImplementedException();
396         }
397 
398     }
399 }

 

 

Step 5 Inheritance of the UserManager class

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using IdeintityDemo.Models;
 6 using Microsoft.AspNet.Identity;
 7 
 8 namespace IdeintityDemo.Identity
 9 {
10     public class HsUserManager:UserManager<BASE_USER,Guid>
11     {
12         /// <summary>
13         /// Implementing classes for user storage by injecting constructors
14         /// </summary>
15         /// <param name="store"></param>
16         public HsUserManager(HsUserStore store) : base(store)
17         {
18 
19         }        
20     }
21 }

 

The above code is particularly simple, but it's really important. You can understand it as injecting the HsUserStore defined above into an IOC container. If you don't inject it, you can't read and write all the db operations to users, and the whole login, registration and verification business can't be implemented!

 

Step 6 Inheritance of SignInManager class

SignInManager class is under Microsoft.AspNet.Identity.Owin namespace. It integrates API s related to user login management and is an indispensable processing class in Asp.Net.Identity.

We need to customize a login management class that inherits SignInManager.

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using IdeintityDemo.Models;
 6 using Microsoft.AspNet.Identity;
 7 using Microsoft.AspNet.Identity.Owin;
 8 using Microsoft.Owin;
 9 using System.Threading.Tasks;
10 using Microsoft.Owin.Security;
11 
12 namespace IdeintityDemo.Identity
13 {
14     /// <summary>
15     /// Login Management, which is used here UserManager
16     /// </summary>
17     public class HsSignInManager : SignInManager<BASE_USER, Guid>
18     {
19 
20         /// <summary>
21         /// Constructor
22         /// </summary>
23         /// <param name="UserManager"></param>
24         /// <param name="AuthenticationManager"></param>
25         public HsSignInManager(Microsoft.AspNet.Identity.UserManager<BASE_USER, Guid> UserManager, Microsoft.Owin.Security.IAuthenticationManager AuthenticationManager)
26             : base(UserManager, AuthenticationManager)
27         {
28 
29         }
30 
31         /// <summary>
32         /// Authenticate user login based on username and password
33         /// </summary>
34         /// <param name="userName"></param>
35         /// <param name="password"></param>
36         /// <param name="isPersistent"></param>
37         /// <param name="shouldLockout"></param>
38         /// <returns></returns>
39         public override System.Threading.Tasks.Task<Microsoft.AspNet.Identity.Owin.SignInStatus> PasswordSignInAsync(string userName,
40                                                                                                                      string password,
41                                                                                                                      bool isPersistent,
42                                                                                                                      bool shouldLockout)
43         {
44             /*Here you can check it directly through PasswordSignInAsync or rewrite ~ */
45             //Use here Find Method returns empty user. . . I don't understand.
46             var user = base.UserManager.FindByName<BASE_USER, Guid>(userName);
47             if (user == null || user.Id == Guid.Empty)
48                 return Task.FromResult<SignInStatus>(SignInStatus.Failure);
49             else if (user.PWD != password)
50                 return Task.FromResult<SignInStatus>(SignInStatus.Failure);
51             else
52             {
53                 /*At this point, if not written to cooks, the Index action of the Home controller will be systematic.
54                     Authorize Brush Selector Interception*/
55                 // utilize ASP.NET Identity Obtain identity object
56                 var identity = base.UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
57                 // Take it up. identity Object login
58                 base.AuthenticationManager.SignIn(new AuthenticationProperties()
59                 { IsPersistent = true }, identity.Result);
60                 return Task.FromResult<SignInStatus>(SignInStatus.Success);
61             }
62             /*Here if you want to use Microsoft's login method directly, you can use base. ok.*/
63             //return base.PasswordSignInAsync(userName,
64             //                                password,
65             //                                isPersistent,
66             //                                shouldLockout);
67         }
68 
69 
70     }
71 }

 

The most important method above is PasswordSignInAsync, which is the login method.

 

It can be said that our encapsulation work has been completed, encapsulating three classes.

 

Now let's see how the code in Controller is written.

This is the registered Action. The Controller belongs to AccountController, of course.

 1  /// <summary>
 2         /// register
 3         /// </summary>
 4         /// <returns></returns>
 5         [HttpPost]
 6         [AllowAnonymous]
 7         public async Task<ActionResult> Register(BASE_USER user)
 8         { 
 9             Microsoft.Owin.IOwinContext OwinContext = HttpContext.GetOwinContext();
10             //User storage
11             HsUserStore userStore = new HsUserStore();
12             //UserManager
13             HsUserManager UserManager = new HsUserManager(userStore);
14             IdentityResult result = await UserManager.CreateAsync(user);
15             if (result.Succeeded)
16             {
17                 Response.Write("Successful registration!");
18                 return RedirectToAction("index", "home");
19             }
20             return View();
21         }
22 
23         [AllowAnonymous]
24         public ActionResult Register()
25         {
26             return View();
27         }

 

Next is the Action code for login.

 1         [AllowAnonymous]
 2         public ActionResult Login()
 3         {
 4             return View();
 5         }
 6 
 7 
 8         [HttpPost]
 9         [AllowAnonymous]
10         public async Task<ActionResult> Login(BASE_USER user)
11         {
12             if (string.IsNullOrEmpty(user.UserName)) { return View(); }
13             if (string.IsNullOrEmpty(user.PWD)) { return View(); }
14             //Context
15             Microsoft.Owin.IOwinContext OwinContext = HttpContext.GetOwinContext();
16             //instantiation UserStore object
17             HsUserStore userStore = new HsUserStore();
18             //UserManager
19             HsUserManager userManager = new HsUserManager(userStore);
20             //Authorized object
21             IAuthenticationManager autherticationManager = OwinContext.Authentication;
22             //Login Management Object
23             HsSignInManager signManager = new HsSignInManager(userManager, autherticationManager);
24 
25             //Sign in
26             Microsoft.AspNet.Identity.Owin.SignInStatus SignInStatus = Microsoft.AspNet.Identity.Owin.SignInStatus.Failure;
27             try
28             {
29                 SignInStatus = await signManager.PasswordSignInAsync(user.UserName,
30                                                                      user.PWD,
31                                                                      true,
32                                                                      shouldLockout: false);
33              
34             }catch(Exception ea)
35             {
36                  
37             }
38             //Logon status
39             switch (SignInStatus)
40             {
41                 //Successful Same Control Inside jump direct use RecirectToAction(ActionName) 
42                 case Microsoft.AspNet.Identity.Owin.SignInStatus.Success:                
43                     //Use of different controllers RedirectToAction
44                     return RedirectToAction("Index", "Home"); //You can jump straight to something else. Controller.                
45                 //locking
46                 case Microsoft.AspNet.Identity.Owin.SignInStatus.LockedOut:
47                     Response.Write("The account is locked~~~!");
48                     break;
49                 //fail
50                 case Microsoft.AspNet.Identity.Owin.SignInStatus.Failure:
51                     Response.Write("Logon failed~~~!");
52                     break;
53                 //Request verification
54                 case Microsoft.AspNet.Identity.Owin.SignInStatus.RequiresVerification:
55                     Response.Write("Need validation!");
56                     break;
57 
58             }
59             return View();
60         }

 

 

Let's see that the default configuration of our Mvc routing initial page is the Index under the Home Controller.

 

This is the Index statement under the Home controller

 

F5 Operation Trial

Running Discovery Browser jumps directly to the login page.

 

 

 

After we entered our account password, we jumped to the Index page

 

 

Then we use the browser to see how cookie s have changed uuuuuuuuuuu

 

It was found that the browser saved a storage item named _IdentityDemo after the whole business was completed, which was executed in our login method.

 

Well, the whole Identity authentication is implemented independent of EF, and several core points are the need to implement IUser interface and various Stores. Then inject the classes that implement various Stores into the UserManager constructor

Wait till you have time to implement the role management in Identity namespace... I have to say that Microsoft's interface is really encapsulated.

Thank you for Li Chaoqiang of Open Source China. I'm looking at his blog and putting it into practice again. ~Thank you.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by Pino on Sat, 12 Jan 2019 11:09:11 -0800