当前位置: 移动技术网 > IT编程>开发语言>.net > .net core2.0下使用Identity改用dapper存储数据(实例讲解)

.net core2.0下使用Identity改用dapper存储数据(实例讲解)

2017年12月07日  | 移动技术网IT编程  | 我要评论

小爸爸全集迅雷下载,宝宝咳嗽,敦烟网

前言、

已经好多天没写博客了,鉴于空闲无聊之时又兴起想写写博客,也当是给自己做个笔记。过了这么些天,我的文笔还是依然那么烂就请多多谅解了。今天主要是分享一下在使用.net core2.0下的实际遇到的情况。在使用webapi时用了identity做用户验证。官方文档是的是用ef存储数据来使用dapper,因为个人偏好原因所以不想用ef。于是乎就去折腾。改成使用dapper做数据存储。于是就有了以下的经验。

一、使用identity服务

先找到startup.cs 这个类文件 找到 configureservices 方法

services.addidentity<applicationuser, applicationrole>().adddefaulttokenproviders();//添加identity
services.addtransient<iuserstore<applicationuser>, customuserstore>();
services.addtransient<irolestore<applicationrole>, customrolestore>();
string connectionstring = configuration.getconnectionstring("sqlconnectionstr");
services.addtransient<sqlconnection>(e => new sqlconnection(connectionstring));
services.addtransient<dapperuserstable>();

然后在 configure 方法 的 app.usemvc() 前加入下列代码,net core 1.0的时候是app.useidentity() 现在已经弃用改为以下方法。

//使用验证
app.useauthentication();

这里的 applicationuser 是自定义的一个用户模型 具体是继承 identityuser 继承它的一些属性

public class applicationuser :identityuser
 {
  public string authenticationtype { get; set; }
  public bool isauthenticated { get; set; }
  public string name { get; set; }
 }

这里的 customuserstore 是自定义提供用户的所有数据操作的方法的类它需要继承三个接口:iuserstore,iuserpasswordstore,iuseremailstore

iuserstore<tuser>接口是在用户存储中必须实现的唯一接口。 它定义了用于创建、 更新、 删除和检索用户的方法。

iuserpasswordstore<tuser>接口定义实现以保持经过哈希处理的密码的方法。 它包含用于获取和设置工作经过哈希处理的密码,以及用于指示用户是否已设置密码的方法的方法。

iuseremailstore<tuser>接口定义实现以存储用户电子邮件地址的方法。 它包含用于获取和设置的电子邮件地址和是否确认电子邮件的方法。

这里跟.net core 1.0的实现接口方式有点不同。需要多实现 iuseremailstore 才能不报错

具体代码如下。以供大家参考。

customuserstore

using microsoft.aspnetcore.identity;
using system;
using system.threading.tasks;
using system.threading;

namespace yepmarscrm.web.customprovider
{
 /// <summary>
 /// this store is only partially implemented. it supports user creation and find methods.
 /// </summary>
 public class customuserstore : iuserstore<applicationuser>,
  iuserpasswordstore<applicationuser>,
  iuseremailstore<applicationuser>
 {
  private readonly dapperuserstable _userstable;

  public customuserstore(dapperuserstable userstable)
  {
   _userstable = userstable;
  }

  #region createuser
  public async task<identityresult> createasync(applicationuser user,
   cancellationtoken cancellationtoken = default(cancellationtoken))
  {
   cancellationtoken.throwifcancellationrequested();
   if (user == null) throw new argumentnullexception(nameof(user));

   return await _userstable.createasync(user);
  }
  #endregion

  public async task<identityresult> deleteasync(applicationuser user,
   cancellationtoken cancellationtoken = default(cancellationtoken))
  {
   cancellationtoken.throwifcancellationrequested();
   if (user == null) throw new argumentnullexception(nameof(user));

   return await _userstable.deleteasync(user);

  }

  public void dispose()
  {
  }

  public task<applicationuser> findbyemailasync(string normalizedemail, cancellationtoken cancellationtoken)
  {
   throw new notimplementedexception();
  }

  public async task<applicationuser> findbyidasync(string userid,
   cancellationtoken cancellationtoken = default(cancellationtoken))
  {
   cancellationtoken.throwifcancellationrequested();
   if (userid == null) throw new argumentnullexception(nameof(userid));
   guid idguid;
   if (!guid.tryparse(userid, out idguid))
   {
    throw new argumentexception("not a valid guid id", nameof(userid));
   }

   return await _userstable.findbyidasync(idguid);

  }

  public async task<applicationuser> findbynameasync(string username,
   cancellationtoken cancellationtoken = default(cancellationtoken))
  {
   cancellationtoken.throwifcancellationrequested();
   if (username == null) throw new argumentnullexception(nameof(username));

   return await _userstable.findbynameasync(username);
  }

  public task<string> getemailasync(applicationuser user, cancellationtoken cancellationtoken)
  {
   cancellationtoken.throwifcancellationrequested();
   if (user == null) throw new argumentnullexception(nameof(user));

   return task.fromresult(user.email);
  }

  public task<bool> getemailconfirmedasync(applicationuser user, cancellationtoken cancellationtoken)
  {
   throw new notimplementedexception();
  }

  public task<string> getnormalizedemailasync(applicationuser user, cancellationtoken cancellationtoken)
  {
   throw new notimplementedexception();
  }

  public task<string> getnormalizedusernameasync(applicationuser user, cancellationtoken cancellationtoken)
  {
   throw new notimplementedexception();
  }

  public task<string> getpasswordhashasync(applicationuser user, cancellationtoken cancellationtoken)
  {
   cancellationtoken.throwifcancellationrequested();
   if (user == null) throw new argumentnullexception(nameof(user));

   return task.fromresult(user.passwordhash);
  }

  public task<string> getuseridasync(applicationuser user, cancellationtoken cancellationtoken)
  {
   cancellationtoken.throwifcancellationrequested();
   if (user == null) throw new argumentnullexception(nameof(user));

   return task.fromresult(user.id.tostring());
  }

  public task<string> getusernameasync(applicationuser user, cancellationtoken cancellationtoken)
  {
   cancellationtoken.throwifcancellationrequested();
   if (user == null) throw new argumentnullexception(nameof(user));

   return task.fromresult(user.username);
  }

  public task<bool> haspasswordasync(applicationuser user, cancellationtoken cancellationtoken)
  {
   throw new notimplementedexception();
  }

  public task setemailasync(applicationuser user, string email, cancellationtoken cancellationtoken)
  {
   throw new notimplementedexception();
  }

  public task setemailconfirmedasync(applicationuser user, bool confirmed, cancellationtoken cancellationtoken)
  {
   throw new notimplementedexception();
  }

  public task setnormalizedemailasync(applicationuser user, string normalizedemail, cancellationtoken cancellationtoken)
  {
   cancellationtoken.throwifcancellationrequested();
   if (user == null) throw new argumentnullexception(nameof(user));
   if (normalizedemail == null) throw new argumentnullexception(nameof(normalizedemail));

   user.normalizedemail = normalizedemail;
   return task.fromresult<object>(null);
  }

  public task setnormalizedusernameasync(applicationuser user, string normalizedname, cancellationtoken cancellationtoken)
  {
   cancellationtoken.throwifcancellationrequested();
   if (user == null) throw new argumentnullexception(nameof(user));
   if (normalizedname == null) throw new argumentnullexception(nameof(normalizedname));

   user.normalizedusername = normalizedname;
   return task.fromresult<object>(null);
  }

  public task setpasswordhashasync(applicationuser user, string passwordhash, cancellationtoken cancellationtoken)
  {
   cancellationtoken.throwifcancellationrequested();
   if (user == null) throw new argumentnullexception(nameof(user));
   if (passwordhash == null) throw new argumentnullexception(nameof(passwordhash));

   user.passwordhash = passwordhash;
   return task.fromresult<object>(null);

  }

  public task setusernameasync(applicationuser user, string username, cancellationtoken cancellationtoken)
  {
   throw new notimplementedexception();
  }

  public task<identityresult> updateasync(applicationuser user, cancellationtoken cancellationtoken)
  {
   return _userstable.updateasync(user);
  }
 }
}

二、使用使用dapper做数据存储

接着就是使用dapper做数据存储。该类的方法都是通过 customuserstore 调用去操作数据库的。具体代码如下。根据实际的用户表去操作dapper即可。

dapperuserstable

using microsoft.aspnetcore.identity;
using system.threading.tasks;
using system.threading;
using system.data.sqlclient;
using system;
using dapper;
using yepmarscrm.enterprise.database.model;
using yepmarscrm.enterprise.database.data;

namespace yepmarscrm.web.customprovider
{
 public class dapperuserstable
 {
  private readonly sqlconnection _connection;
  private readonly sys_accountdata _sys_accountdata;
  public dapperuserstable(sqlconnection connection)
  {
   _connection = connection;
   _sys_accountdata = new sys_accountdata();
  }

  private sys_account applicationusertoaccount(applicationuser user)
  {
   return new sys_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,
   };
  }

  #region createuser
  public async task<identityresult> createasync(applicationuser user)
  {
   int rows = await _sys_accountdata.insertasync(applicationusertoaccount(user));
   if (rows > 0)
   {
    return identityresult.success;
   }
   return identityresult.failed(new identityerror { description = $"could not insert user {user.email}." });
  }
  #endregion

  public async task<identityresult> deleteasync(applicationuser user)
  {
   //string sql = "delete from sys_account where id = @id";
   //int rows = await _connection.executeasync(sql, new { user.id });

   int rows = await _sys_accountdata.deleteforpkasync(applicationusertoaccount(user));

   if (rows > 0)
   {
    return identityresult.success;
   }
   return identityresult.failed(new identityerror { description = $"could not delete user {user.email}." });
  }


  public async task<applicationuser> findbyidasync(guid userid)
  {
   string sql = "select * from sys_account where id = @id;";
   return await _connection.querysingleordefaultasync<applicationuser>(sql, new
   {
    id = userid
   });
  }


  public async task<applicationuser> findbynameasync(string username)
  {
   string sql = "select * from sys_account where username = @username;";

   return await _connection.querysingleordefaultasync<applicationuser>(sql, new
   {
    username = username
   });

   //var user = new applicationuser() { username = username, email = username, emailconfirmed = false };
   //user.passwordhash = new passwordhasher<applicationuser>().hashpassword(user, "test");
   //return await task.fromresult(user);
  }

  public async task<identityresult> updateasync(applicationuser applicationuser)
  {
   var user = applicationusertoaccount(applicationuser);
   var result = await _sys_accountdata.updateforpkasync(user);
   if (result > 0)
   {
    return identityresult.success;
   }
   return identityresult.failed(new identityerror { description = $"could not update user {user.email}." });
  }
 }
}

三、使用usermanager、signinmanager验证操作

新建一个 accountcontroller 控制器 并在构造函数中获取 依赖注入的对象 usermanager 与 signinmanager 如下:

[authorize]
  public class accountcontroller : controller
 {
  private readonly usermanager<applicationuser> _usermanager;
  private readonly signinmanager<applicationuser> _signinmanager;
  private readonly ilogger _logger;

public accountcontroller(usermanager<applicationuser> usermanager,
   signinmanager<applicationuser> signinmanager,
   iloggerfactory loggerfactory)
  {
   _usermanager = usermanager;
   _signinmanager = signinmanager;
   _logger = loggerfactory.createlogger<accountcontroller>();
  }
 }

signinmanager 是提供用户登录登出的api ,usermanager 是提供用户管理的api。

接着来实现一下简单的登录登出。

/// <summary>
  /// 登录
  /// </summary>
  [httppost]
  [allowanonymous]
  public async task<iactionresult> login(reqloginmodel req)
  {
   var json = new jsonresultmodel<object>();
   if (modelstate.isvalid)
   {
    var result = 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
   {
    var errormessges = modelstate.geterrormessage();
    json.code = "403";
    json.message = string.join(",", errormessges);
   }
   return json.tojsonresult();
  }
/// <summary>
  /// 登出
  /// </summary>
  /// <returns></returns>
  [httppost]
  public async task<iactionresult> logout()
  {await _signinmanager.signoutasync();
   var json = new jsonresultmodel<object>()
   {
    code = "200",
    data = null,
    message = "登出成功",
    remark = string.empty
   };
   return json.tojsonresult();
  }

四、使用identity配置

在 configureservices 方法中加入

services.configure<identityoptions>(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 =>
   {
    // cookie settings
    options.cookie.httponly = true;
    //options.cookie.expiration = timespan.fromminutes(30);//30分钟
    options.cookie.expiration = timespan.fromhours(12);//12小时
    options.loginpath = "/api/account/notlogin"; // if the loginpath is not set here, asp.net core will default to /account/login
    //options.logoutpath = "/api/account/logout"; // if the logoutpath is not set here, asp.net core will default to /account/logout
    //options.accessdeniedpath = "/account/accessdenied"; // if the accessdeniedpath is not set here, asp.net core will default to /account/accessdenied
    options.slidingexpiration = true;
   });

五、其他

在实现的过程中遇到一些小状况。例如identity不生效。是因为未在app.usemvc() 之前使用造成的。 如果未登录会造成跳转。后来查看了.net core identity 的源码后 发现 如果是ajax情况下 不会跳转而时 返回401的状态码页面。

然后就是idenetity的密码加密 是用 passwordhasher 这个类去加密的。如果想用自己的加密方式。只能通过继承接口去更改原本的方式。然后大致说到这么些。也当是给自己做做笔记。做得不好请大家多给点意见。多多谅解。谢谢。

以上这篇.net core2.0下使用identity改用dapper存储数据(实例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网