.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
publicasyncTaskCreateAsync(ApplicationUseruser,
CancellationTokencancellationToken=default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
if(user==null)thrownewArgumentNullException(nameof(user));
returnawait_usersTable.CreateAsync(user);
}
#endregion
publicasyncTaskDeleteAsync(ApplicationUseruser,
CancellationTokencancellationToken=default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
if(user==null)thrownewArgumentNullException(nameof(user));
returnawait_usersTable.DeleteAsync(user);
}
publicvoidDispose()
{
}
publicTaskFindByEmailAsync(stringnormalizedEmail,CancellationTokencancellationToken)
{
thrownewNotImplementedException();
}
publicasyncTaskFindByIdAsync(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);
}
publicasyncTaskFindByNameAsync(stringuserName,
CancellationTokencancellationToken=default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
if(userName==null)thrownewArgumentNullException(nameof(userName));
returnawait_usersTable.FindByNameAsync(userName);
}
publicTaskGetEmailAsync(ApplicationUseruser,CancellationTokencancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if(user==null)thrownewArgumentNullException(nameof(user));
returnTask.FromResult(user.Email);
}
publicTaskGetEmailConfirmedAsync(ApplicationUseruser,CancellationTokencancellationToken)
{
thrownewNotImplementedException();
}
publicTaskGetNormalizedEmailAsync(ApplicationUseruser,CancellationTokencancellationToken)
{
thrownewNotImplementedException();
}
publicTaskGetNormalizedUserNameAsync(ApplicationUseruser,CancellationTokencancellationToken)
{
thrownewNotImplementedException();
}
publicTaskGetPasswordHashAsync(ApplicationUseruser,CancellationTokencancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if(user==null)thrownewArgumentNullException(nameof(user));
returnTask.FromResult(user.PasswordHash);
}
publicTaskGetUserIdAsync(ApplicationUseruser,CancellationTokencancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if(user==null)thrownewArgumentNullException(nameof(user));
returnTask.FromResult(user.Id.ToString());
}
publicTaskGetUserNameAsync(ApplicationUseruser,CancellationTokencancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if(user==null)thrownewArgumentNullException(nameof(user));
returnTask.FromResult(user.UserName);
}
publicTaskHasPasswordAsync(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
publicasyncTaskDeleteAsync(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}."});
}
publicasyncTaskFindByIdAsync(GuiduserId)
{
stringsql="SELECT*FROMSys_AccountWHEREId=@Id;";
returnawait_connection.QuerySingleOrDefaultAsync(sql,new
{
Id=userId
});
}
publicasyncTaskFindByNameAsync(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);
}
publicasyncTaskUpdateAsync(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(UserManageruserManager,
SignInManagersignInManager,
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存储数据(实例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。