ASP.NET Web API登录触发System.FormatException Base64格式错误如何解决
问题根因
你遇到的Base64格式错误直接由Convert.FromBase64String(user.Salt)触发,说明从数据库取出的user.Salt不是合法的Base64字符串,常见原因如下:
- 数据库
TblUser表的Salt字段长度设置不足:16字节的盐经过Base64编码后长度固定为24位,如果字段类型设置为varchar(n)且n<24,存储时盐会被截断,导致读取时无法正常解码。 - 实体映射异常:EF Core读取数据时
Salt字段映射错误,取到空值或无关内容。 - 历史测试数据问题:之前插入过非Base64格式的Salt测试数据,或者旧注册数据因为字段长度不够被截断。
修复方案
- 修正数据库字段长度
将TblUser表的字段长度调整为:
Salt字段:至少varchar(32),预留足够空间存储Base64编码后的盐值Password字段:至少varchar(64),SHA256哈希转Base64后固定为44位,预留冗余空间
清理历史数据,重新注册测试
删除数据库中已有的异常用户数据,调整字段后重新走注册流程生成合法的盐和密码哈希再测试登录。增加防御性校验与兼容性优化
修改登录逻辑,增加空值校验,同时将密码编码从ASCII改为UTF8,支持中文、特殊符号密码:
if (dbContext.TblUsers.Any(user => user.UserName.Equals(value.UserName))) { TblUser user = dbContext.TblUsers.Where(u => u.UserName.Equals(value.UserName)).First(); // 新增Salt合法性校验 if (string.IsNullOrWhiteSpace(user.Salt)) { return JsonConvert.SerializeObject("用户数据异常,请联系管理员"); } byte[] saltBytes; try { saltBytes = Convert.FromBase64String(user.Salt); } catch (FormatException) { return JsonConvert.SerializeObject("用户数据异常,请联系管理员"); } // 把ASCII改为UTF8,兼容非ASCII密码 var client_post_hash_password = Convert.ToBase64String( common.SaltHashPassword( Encoding.UTF8.GetBytes(value.Password), saltBytes)); if (client_post_hash_password.Equals(user.Password)) return JsonConvert.SerializeObject(user); else return JsonConvert.SerializeObject("密码错误"); }
同时把注册逻辑里的Encoding.ASCII.GetBytes(value.Password)也同步改成Encoding.UTF8.GetBytes(value.Password),保持编解码逻辑一致。
可选优化
RNGCryptoServiceProvider在.NET Core 2.0+版本已经被标记为过时,建议改用RandomNumberGenerator静态方法生成盐,代码更简洁性能更好:
public static byte[] GetRandomSalt(int length) { byte[] salt = new byte[length]; RandomNumberGenerator.GetBytes(salt); return salt; }
内容的提问来源于stack exchange,提问作者partizal
相关产品推荐
相关产品推荐

