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.
u