有没有办法在 Asp.Net Core Identity 中将 PasswordHash 的数据类型从字符串更改为字节数组

Posted

技术标签:

【中文标题】有没有办法在 Asp.Net Core Identity 中将 PasswordHash 的数据类型从字符串更改为字节数组【英文标题】:Is there a way to change the Data Type of PasswordHash from String to Byte array in Asp.Net Core Identity 【发布时间】:2021-12-31 14:37:25 【问题描述】:

我正在最小化 API 项目中实现 asp.net 核心身份库,并且用户表的 PasswordHash 字段执行其默认哈希和加盐,但我想执行我的自定义哈希和加盐密码。 那么,如何将 PasswordHash 的类型从“string”更改为“byte[]”

此外,PasswordHash 字段不应实现任何默认散列机制

【问题讨论】:

不,因为这是来自 Microsoft.AspNetCore.Identity.EntityFrameworkCore 的实现。 为什么要更改该类型? 您可以用自己的实现替换IPasswordHasher。我不确定我是否会建议这种做法,除非您这样做是为了与单独的服务集成。 您不能将散列的byte[] 表示为string 吗?与替代方案相比,它不会那么令人头疼。 只需使用Convert.ToBase64StringConvert.FromBase64String 将字符串val 存储在数据库中即可。然后你可以创建任何你想要的字节[]。 【参考方案1】:

我做了这样的事情

注册时

 private void CreatePasswordHash(string Password, out byte[] PasswordHash, out byte[] PasswordSalt)
    
        using (var hmac = new HMACSHA512())
        
            PasswordSalt = hmac.Key;
            PasswordHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(Password));
        
    

那么,

 public async Task<ServiceResponse<AspNetUsers>> AddUser(AddUserDto user)
    
        var ServiceResponse = new ServiceResponse<AspNetUsers>();
        AspNetUsers Users = _mapper.Map<AspNetUsers>(user);
        try
        
            if (await UserExist(Users.UserName))
            
                ServiceResponse.Success = false;
                ServiceResponse.Message = "User Already Exist";
                return ServiceResponse;
            
            CreatePasswordHash(Users.PasswordHash, out byte[] PasswordMade, out byte[] PasswordSalt);

            Users.Id = CommonCode.NewGUID();
            Users.SecurityStamp = CommonCode.NewGUID();
            Users.ConcurrencyStamp = CommonCode.NewGUID();
            Users.PasswordHash = Convert.ToBase64String(PasswordMade);
            Users.PasswordSalt = PasswordSalt;
            var AddUser = await _context.Users.AddAsync(Users);
            await _context.SaveChangesAsync();
            ServiceResponse.Data = await _context.Users.SingleAsync(x => x.Id == Users.Id);
            ServiceResponse.Success = true;
            ServiceResponse.Message = "User successfully added!";
        
        catch (Exception ex)
        
            ServiceResponse.Success = false;
            ServiceResponse.Message = ex.Message;
        
        return ServiceResponse;
    

在登录时,我做了这样的事情。

        private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
    
        using (var hmac = new HMACSHA512(passwordSalt))
        
            var computeHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(password));
            for (int i = 0; i < computeHash.Length; i++)
            
                if (computeHash[i] != passwordHash[i])
                
                    return false;
                
            
            return true;
        
    

那么,

        public async Task<ServiceResponse<string>> Login(LoginInformation Credentials)
        
        var ServiceResponse = new ServiceResponse<string>();
        try
        
            var User = await _context.Users.FirstOrDefaultAsync(x => x.Email.ToLower() == Credentials.Email.ToLower());
                            
            if(User == null)
            ServiceResponse.Success = false;
            ServiceResponse.Message = "User not found.";
            
            else
            if(!VerifyPasswordHash(Credentials.Password, Convert.FromBase64String(User.PasswordHash), User.PasswordSalt))
            
                ServiceResponse.Success = false;
                ServiceResponse.Message = "Username Or Password Is Incorrect";
            
            else
                ServiceResponse.Data = "Login success"; 
                ServiceResponse.Success = true;
                ServiceResponse.Message = "Login is Successfull!";
            
        
        catch (Exception ex)
        
            ServiceResponse.Data = string.Empty;
            ServiceResponse.Success = false;
            ServiceResponse.Message = ex.Message;
        
        return ServiceResponse;
    

【讨论】:

以上是关于有没有办法在 Asp.Net Core Identity 中将 PasswordHash 的数据类型从字符串更改为字节数组的主要内容,如果未能解决你的问题,请参考以下文章