.net core2.0下使用Identity改用dapper存储数据(实例讲解)
前言、
已经好多天没写博客了,鉴于空闲无聊之时又兴起想写写博客,也当是给自己做个笔记。过了这么些天,我的文笔还是依然那么烂就请多多谅解了。今天主要是分享一下在使用.netcore2.0下的实际遇到的情况。在使用webapi时用了identity做用户验证。官方文档是的是用EF存储数据来使用dapper,因为个人偏好原因所以不想用EF。于是乎就去折腾。改成使用dapper做数据存储。于是就有了以下的经验。
一、使用Identity服务
先找到Startup.cs这个类文件找到ConfigureServices方法
services.AddIdentity().AddDefaultTokenProviders();//添加Identity services.AddTransient ,CustomUserStore>(); services.AddTransient ,CustomRoleStore>(); stringconnectionString=Configuration.GetConnectionString("SqlConnectionStr"); services.AddTransient (e=>newSqlConnection(connectionString)); services.AddTransient ();
然后在Configure方法的app.UseMvc()前加入下列代码,netcore1.0的时候是app.UseIdentity()现在已经弃用改为以下方法。
//使用验证 app.UseAuthentication();
这里的ApplicationUser是自定义的一个用户模型具体是继承IdentityUser继承它的一些属性
publicclassApplicationUser:IdentityUser { publicstringAuthenticationType{get;set;} publicboolIsAuthenticated{get;set;} publicstringName{get;set;} }
这里的CustomUserStore是自定义提供用户的所有数据操作的方法的类它需要继承三个接口:IUserStore,IUserPasswordStore,IUserEmailStore
IUserStore
IUserPasswordStore
IUserEmailStore
这里跟.netcore1.0的实现接口方式有点不同。需要多实现IUserEmailStore才能不报错
具体代码如下。以供大家参考。
CustomUserStore
usingMicrosoft.AspNetCore.Identity; usingSystem; usingSystem.Threading.Tasks; usingSystem.Threading; namespaceYepMarsCRM.Web.CustomProvider { //////Thisstoreisonlypartiallyimplemented.Itsupportsusercreationandfindmethods. /// publicclassCustomUserStore:IUserStore, IUserPasswordStore , IUserEmailStore { privatereadonlyDapperUsersTable_usersTable; publicCustomUserStore(DapperUsersTableusersTable) { _usersTable=usersTable; } #regioncreateuser publicasyncTask CreateAsync(ApplicationUseruser, CancellationTokencancellationToken=default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); if(user==null)thrownewArgumentNullException(nameof(user)); returnawait_usersTable.CreateAsync(user); } #endregion publicasyncTask DeleteAsync(ApplicationUseruser, CancellationTokencancellationToken=default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); if(user==null)thrownewArgumentNullException(nameof(user)); returnawait_usersTable.DeleteAsync(user); } publicvoidDispose() { } publicTask FindByEmailAsync(stringnormalizedEmail,CancellationTokencancellationToken) { thrownewNotImplementedException(); } publicasyncTask FindByIdAsync(stringuserId, CancellationTokencancellationToken=default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); if(userId==null)thrownewArgumentNullException(nameof(userId)); GuididGuid; if(!Guid.TryParse(userId,outidGuid)) { thrownewArgumentException("NotavalidGuidid",nameof(userId)); } returnawait_usersTable.FindByIdAsync(idGuid); } publicasyncTask FindByNameAsync(stringuserName, CancellationTokencancellationToken=default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); if(userName==null)thrownewArgumentNullException(nameof(userName)); returnawait_usersTable.FindByNameAsync(userName); } publicTask GetEmailAsync(ApplicationUseruser,CancellationTokencancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if(user==null)thrownewArgumentNullException(nameof(user)); returnTask.FromResult(user.Email); } publicTask GetEmailConfirmedAsync(ApplicationUseruser,CancellationTokencancellationToken) { thrownewNotImplementedException(); } publicTask GetNormalizedEmailAsync(ApplicationUseruser,CancellationTokencancellationToken) { thrownewNotImplementedException(); } publicTask GetNormalizedUserNameAsync(ApplicationUseruser,CancellationTokencancellationToken) { thrownewNotImplementedException(); } publicTask GetPasswordHashAsync(ApplicationUseruser,CancellationTokencancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if(user==null)thrownewArgumentNullException(nameof(user)); returnTask.FromResult(user.PasswordHash); } publicTask GetUserIdAsync(ApplicationUseruser,CancellationTokencancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if(user==null)thrownewArgumentNullException(nameof(user)); returnTask.FromResult(user.Id.ToString()); } publicTask GetUserNameAsync(ApplicationUseruser,CancellationTokencancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if(user==null)thrownewArgumentNullException(nameof(user)); returnTask.FromResult(user.UserName); } publicTask HasPasswordAsync(ApplicationUseruser,CancellationTokencancellationToken) { thrownewNotImplementedException(); } publicTaskSetEmailAsync(ApplicationUseruser,stringemail,CancellationTokencancellationToken) { thrownewNotImplementedException(); } publicTaskSetEmailConfirmedAsync(ApplicationUseruser,boolconfirmed,CancellationTokencancellationToken) { thrownewNotImplementedException(); } publicTaskSetNormalizedEmailAsync(ApplicationUseruser,stringnormalizedEmail,CancellationTokencancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if(user==null)thrownewArgumentNullException(nameof(user)); if(normalizedEmail==null)thrownewArgumentNullException(nameof(normalizedEmail)); user.NormalizedEmail=normalizedEmail; returnTask.FromResult
二、使用使用dapper做数据存储
接着就是使用dapper做数据存储。该类的方法都是通过CustomUserStore调用去操作数据库的。具体代码如下。根据实际的用户表去操作dapper即可。
DapperUsersTable
usingMicrosoft.AspNetCore.Identity; usingSystem.Threading.Tasks; usingSystem.Threading; usingSystem.Data.SqlClient; usingSystem; usingDapper; usingYepMarsCRM.Enterprise.DataBase.Model; usingYepMarsCRM.Enterprise.DataBase.Data; namespaceYepMarsCRM.Web.CustomProvider { publicclassDapperUsersTable { privatereadonlySqlConnection_connection; privatereadonlySys_AccountData_sys_AccountData; publicDapperUsersTable(SqlConnectionconnection) { _connection=connection; _sys_AccountData=newSys_AccountData(); } privateSys_AccountApplicationUserToAccount(ApplicationUseruser) { returnnewSys_Account { Id=user.Id, UserName=user.UserName, PasswordHash=user.PasswordHash, Email=user.Email, EmailConfirmed=user.EmailConfirmed, PhoneNumber=user.PhoneNumber, PhoneNumberConfirmed=user.PhoneNumberConfirmed, LockoutEnd=user.LockoutEnd?.DateTime, LockoutEnabled=user.LockoutEnabled, AccessFailedCount=user.AccessFailedCount, }; } #regioncreateuser publicasyncTaskCreateAsync(ApplicationUseruser) { introws=await_sys_AccountData.InsertAsync(ApplicationUserToAccount(user)); if(rows>0) { returnIdentityResult.Success; } returnIdentityResult.Failed(newIdentityError{Description=$"Couldnotinsertuser{user.Email}."}); } #endregion publicasyncTask DeleteAsync(ApplicationUseruser) { //stringsql="DELETEFROMSys_AccountWHEREId=@Id"; //introws=await_connection.ExecuteAsync(sql,new{user.Id}); introws=await_sys_AccountData.DeleteForPKAsync(ApplicationUserToAccount(user)); if(rows>0) { returnIdentityResult.Success; } returnIdentityResult.Failed(newIdentityError{Description=$"Couldnotdeleteuser{user.Email}."}); } publicasyncTask FindByIdAsync(GuiduserId) { stringsql="SELECT*FROMSys_AccountWHEREId=@Id;"; returnawait_connection.QuerySingleOrDefaultAsync (sql,new { Id=userId }); } publicasyncTask FindByNameAsync(stringuserName) { stringsql="SELECT*FROMSys_AccountWHEREUserName=@UserName;"; returnawait_connection.QuerySingleOrDefaultAsync (sql,new { UserName=userName }); //varuser=newApplicationUser(){UserName=userName,Email=userName,EmailConfirmed=false}; //user.PasswordHash=newPasswordHasher ().HashPassword(user,"test"); //returnawaitTask.FromResult(user); } publicasyncTask UpdateAsync(ApplicationUserapplicationUser) { varuser=ApplicationUserToAccount(applicationUser); varresult=await_sys_AccountData.UpdateForPKAsync(user); if(result>0) { returnIdentityResult.Success; } returnIdentityResult.Failed(newIdentityError{Description=$"Couldnotupdateuser{user.Email}."}); } } }
三、使用UserManager、SignInManager验证操作
新建一个AccountController控制器并在构造函数中获取依赖注入的对象UserManager与SignInManager如下:
[Authorize] publicclassAccountController:Controller { privatereadonlyUserManager_userManager; privatereadonlySignInManager _signInManager; privatereadonlyILogger_logger; publicAccountController(UserManager userManager, SignInManager signInManager, ILoggerFactoryloggerFactory) { _userManager=userManager; _signInManager=signInManager; _logger=loggerFactory.CreateLogger (); } }
SignInManager是提供用户登录登出的API,UserManager是提供用户管理的API。
接着来实现一下简单的登录登出。
//////登录 /// [HttpPost] [AllowAnonymous] publicasyncTaskLogin(ReqLoginModelreq) { varjson=newJsonResultModel (); if(ModelState.IsValid) { varresult=await_signInManager.PasswordSignInAsync(req.UserName,req.Password,isPersistent:true,lockoutOnFailure:false); if(result.Succeeded) { json.code="200"; json.message="登录成功"; } else { json.code="400"; json.message="登录失败"; } if(result.IsLockedOut) { json.code="401"; json.message="账户密码已错误3次,账户被锁定,请30分钟后再尝试"; } } else { varerrorMessges=ModelState.GetErrorMessage(); json.code="403"; json.message=string.Join(",",errorMessges); } returnjson.ToJsonResult(); }
//////登出 /// ///[HttpPost] publicasyncTask LogOut() {await_signInManager.SignOutAsync(); varjson=newJsonResultModel () { code="200", data=null, message="登出成功", remark=string.Empty }; returnjson.ToJsonResult(); }
四、使用Identity配置
在ConfigureServices方法中加入
services.Configure(options=> { //密码配置 options.Password.RequireDigit=false;//是否需要数字(0-9). options.Password.RequiredLength=6;//设置密码长度最小为6 options.Password.RequireNonAlphanumeric=false;//是否包含非字母或数字字符。 options.Password.RequireUppercase=false;//是否需要大写字母(A-Z). options.Password.RequireLowercase=false;//是否需要小写字母(a-z). //options.Password.RequiredUniqueChars=6; //锁定设置 options.Lockout.DefaultLockoutTimeSpan=TimeSpan.FromMinutes(30);//账户锁定时长30分钟 options.Lockout.MaxFailedAccessAttempts=3;//10次失败的尝试将账户锁定 //options.Lockout.AllowedForNewUsers=true; //用户设置 options.User.RequireUniqueEmail=false;//是否Email地址必须唯一 }); services.ConfigureApplicationCookie(options=> { //Cookiesettings options.Cookie.HttpOnly=true; //options.Cookie.Expiration=TimeSpan.FromMinutes(30);//30分钟 options.Cookie.Expiration=TimeSpan.FromHours(12);//12小时 options.LoginPath="/api/Account/NotLogin";//IftheLoginPathisnotsethere,ASP.NETCorewilldefaultto/Account/Login //options.LogoutPath="/api/Account/Logout";//IftheLogoutPathisnotsethere,ASP.NETCorewilldefaultto/Account/Logout //options.AccessDeniedPath="/Account/AccessDenied";//IftheAccessDeniedPathisnotsethere,ASP.NETCorewilldefaultto/Account/AccessDenied options.SlidingExpiration=true; });
五、其他
在实现的过程中遇到一些小状况。例如Identity不生效。是因为未在app.UseMvc()之前使用造成的。如果未登录会造成跳转。后来查看了.netcoreIdentity的源码后发现如果是ajax情况下不会跳转而时返回401的状态码页面。
然后就是Idenetity的密码加密是用PasswordHasher这个类去加密的。如果想用自己的加密方式。只能通过继承接口去更改原本的方式。然后大致说到这么些。也当是给自己做做笔记。做得不好请大家多给点意见。多多谅解。谢谢。
以上这篇.netcore2.0下使用Identity改用dapper存储数据(实例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。