.Net Core2.2 使用Identity时替换ORM(Dapper替换EF、Oracle替换Sqlserver)层 (一):基本配置

参考文档:

1、https://docs.microsoft.com/zh-cn/aspnet/core/security/?view=aspnetcore-2.2

2、https://github.com/aspnet/AspNetCore.Docs/tree/live/aspnetcore/security/authentication/identity/sample/src

3、https://blog.csdn.net/sD7O95O/article/details/78623698

在Core2.2中,Identity的ORM默认使用了EF,但是这样,一些老项目迁移过程中就会遇到问题,因为很多项目还是使用的sql语句的方式访问数据库,这种情况下,显然不能重构项目为EF,不过,微软还是给Identity留下了自定义ORM的入口。

因为官方默认使用EF+sqlserver且使用了CodeFirst,所以下边的例子则为dapper+oracle,完全使用sql语句访问数据库,尽可能做到差异化。

 

一、数据库结构:

   因为是简单demo,所以配置一个简单的数据库,一个表,两个列足矣

    sys_user(userid varchar2,username varchar2,password varchar2)

二、新建一个core2.2项目:

.Net Core2.2 使用Identity时替换ORM(Dapper替换EF、Oracle替换Sqlserver)层 (一):基本配置_第1张图片.Net Core2.2 使用Identity时替换ORM(Dapper替换EF、Oracle替换Sqlserver)层 (一):基本配置_第2张图片

测试一下,可以运行:

.Net Core2.2 使用Identity时替换ORM(Dapper替换EF、Oracle替换Sqlserver)层 (一):基本配置_第3张图片

二、基础配置:

    1、appsettings.json配置文件中配置连接字符串“OracleConStr”:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "OracleConStr": "Data Source=****;Persist Security Info=True;User ID=**;Password=**;"
}

    2、使用NuGet安装所需类库:

1、Dapper
2、Oracle.ManagedDataAccess.Core

    3、创建SysUser实体类

    public class SysUser : IIdentity
    {
        //必须实现的接口
        public string AuthenticationType { get; set; }
        public bool IsAuthenticated { get; set; }
        public string Name { get; set; }

        //根据表自定义的字段
        public string UserID { get; set; }
        public string UserName { get; set; }
        public string NormalizedUserName { get; set; }
        public string Password { get; set; }
        public string PasswordHash { get; set; }
    }

    4、创建表sysuser对应的Dal类SysUserDal,使用Dapper实现基本的增删改查

    public class SysUserDal
    {
        private readonly OracleConnection _connection;
        public SysUserDal(OracleConnection connection)
        {
            _connection = connection;
        }

        public async Task CreateAsync(SysUser user)
        {
            string sql = "insert into sys_user (userid,username,password) values (:userid, :username,:password)";

            int rows = await _connection.ExecuteAsync(sql, new { userid = user.UserID, username = user.UserName, password = user.PasswordHash });

            if (rows > 0)
            {
                return IdentityResult.Success;
            }
            return IdentityResult.Failed(new IdentityError { Description = $"Could not insert user {user.UserID}." });
        }

        public async Task DeleteAsync(SysUser user)
        {
            string sql = "delete from sys_user where userid = :userid";
            int rows = await _connection.ExecuteAsync(sql, new { user.UserID });

            if (rows > 0)
            {
                return IdentityResult.Success;
            }
            return IdentityResult.Failed(new IdentityError { Description = $"Could not delete user {user.UserID}." });
        }

        public async Task UpdateAsync(SysUser user)
        {
            string sql = "update sys_user set password=:password,username=:username where userid=:userid";
            int rows = await _connection.ExecuteAsync(sql, new { userid = user.UserID, password = user.PasswordHash });
            if (rows > 0)
            {
                return IdentityResult.Success;
            }
            return IdentityResult.Failed(new IdentityError { Description = $"Could not update user {user.UserID}." });
        }

        public async Task FindByIdAsync(string userId)
        {
            string sql = "select * from sys_user where userid = :userid";

            return await _connection.QuerySingleOrDefaultAsync(sql, new
            {
                userid = userId
            });
        }
        public async Task FindByNameAsync(string userName)
        {
            string sql = "select * from sys_user where username = :username";

            return await _connection.QuerySingleOrDefaultAsync(sql, new
            {
                username = userName
            });
        }
    }

    4、创建SysuserRole

    public class SysUserRole
    {
        public string UserID { get; set; } 
        public string UserName { get; set; } 
        public string Password { get; set; }
    }

    5、创建CustomUserStore

   public class CustomUserStore : IUserStore, IUserPasswordStore
    {
        private readonly SysUserDal _usersTable;

        public CustomUserStore(SysUserDal usersTable)
        {
            _usersTable = usersTable;
        }

        #region createuser
        public async Task CreateAsync(SysUser user,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (user == null) throw new ArgumentNullException(nameof(user));

            return await _usersTable.CreateAsync(user);
        }
        #endregion

        public async Task DeleteAsync(SysUser user,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (user == null) throw new ArgumentNullException(nameof(user));

            return await _usersTable.DeleteAsync(user);

        }

        public void Dispose()
        {
        }

        public async Task FindByIdAsync(string userId,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (userId == null) throw new ArgumentNullException(nameof(userId));
            return await _usersTable.FindByIdAsync(userId);

        }

        public async Task FindByNameAsync(string userName,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (userName == null) throw new ArgumentNullException(nameof(userName));

            return await _usersTable.FindByNameAsync(userName);
        }

        public Task GetNormalizedUserNameAsync(SysUser user, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public Task GetPasswordHashAsync(SysUser user, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (user == null) throw new ArgumentNullException(nameof(user));

            return Task.FromResult(user.Password);
        }

        public Task GetUserIdAsync(SysUser user, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (user == null) throw new ArgumentNullException(nameof(user));

            return Task.FromResult(user.UserID);
        }
        public Task CheckPasswordAsync(SysUser user, string pwd,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();
            return Task.FromResult(user.Password == pwd);
        }
        public Task IsEmailConfirmedAsync(SysUser user,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();
            return Task.FromResult(true);
        }

        public Task GetUserNameAsync(SysUser user, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (user == null) throw new ArgumentNullException(nameof(user));

            return Task.FromResult(user.UserID);
        }

        public Task HasPasswordAsync(SysUser user, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public Task SetNormalizedUserNameAsync(SysUser 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(null);
        }

        public Task SetPasswordHashAsync(SysUser 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(null);

        }

        public Task SetUserNameAsync(SysUser user, string userName, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public Task UpdateAsync(SysUser user, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }
    } 
  

    6、创建CustomRoleStore

    public class CustomRoleStore : IRoleStore
    {
        public Task CreateAsync(SysUserRole role, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public Task DeleteAsync(SysUserRole role, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public void Dispose()
        {
        }

        public Task FindByIdAsync(string roleId, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public Task FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public Task GetNormalizedRoleNameAsync(SysUserRole role, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public Task GetRoleIdAsync(SysUserRole role, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public Task GetRoleNameAsync(SysUserRole role, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public Task SetNormalizedRoleNameAsync(SysUserRole role, string normalizedName, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public Task SetRoleNameAsync(SysUserRole role, string roleName, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public Task UpdateAsync(SysUserRole role, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }
    }

    7、StartUp注入:ConfigureServices方法中添加

   string connectionString = Configuration["OracleConStr"];
   services.AddTransient(e => new OracleConnection(connectionString));
   services.AddTransient();
   services.AddIdentity().AddDefaultTokenProviders();
   services.AddTransient, CustomUserStore>();
   services.AddTransient, CustomRoleStore>();

    8、StartUp中Configure的UseMVC之前添加

 app.UseAuthentication();

    至此,基本的代码配置就完成了,下一步就是在controller中调用

三、controller+view使用Identity,因为是简单demo,所以代码比较简单,并不考虑实际使用场景

    1、创建AccountController

    public class AccountController : Controller
    {
        private readonly UserManager _userManager;
        private readonly SignInManager _signInManager;
        public AccountController(UserManager userManager,
            SignInManager signInManager)
        {
            _userManager = userManager;
            _signInManager = signInManager;
        }
        public IActionResult Index()
        {
            return View();
        }
        public async Task Login()
        {
            string userid = "test";
            string pwd = "123ABCabc.";

            var result = await _signInManager.PasswordSignInAsync(userid, pwd, false, false);
            if (result.Succeeded)
            {
                //dosomething
            }
            else if (result.IsLockedOut)
            {
                //dosomething
            }
            else
            {
                ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            }
            return View();
        }
        public async Task Register()
        {

            var user = new SysUser { UserID = "test", UserName = "测试" };
            var result = await _userManager.CreateAsync(user, "123ABCabc.");
            if (result.Succeeded)
            {
                //await _signInManager.SignInAsync(user, isPersistent: false);
            }
            else
            {
                //dosomething
            }
            return View();
        }
        public async Task GetUser()
        {
            var res = await _userManager.GetUserAsync(HttpContext.User);
            return View();
        }
        public async Task Logout()
        {
            await _signInManager.SignOutAsync();
            return View();
        }
    }

    2、创建每个Action的cshtml

    3、debug模式运行程序,在Account中的所有Action打断点,在SysUserDal所有方法打断点,使用浏览器地址栏调用Action,观察Identity工作流程,此处使用Register进行测试,不细看Debug过程,只看结果。

https://localhost:XXXXXX/Account/Register

观察数据库数据,发现数据已经被添加:.Net Core2.2 使用Identity时替换ORM(Dapper替换EF、Oracle替换Sqlserver)层 (一):基本配置_第4张图片

 

至此,可以证明Identity的ORM基础替换已经成功,此时的项目结构:

.Net Core2.2 使用Identity时替换ORM(Dapper替换EF、Oracle替换Sqlserver)层 (一):基本配置_第5张图片

其他安全和权限类配置可根据使用场景阅读Microsoft Docs自定义开发

 

你可能感兴趣的:(.Net Core2.2 使用Identity时替换ORM(Dapper替换EF、Oracle替换Sqlserver)层 (一):基本配置)