You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

直接插入aspnet_membership用户后登录失败及密码显示乱码问题求助

aspnet_membership用户后登录失败及密码显示乱码问题求助

兄弟,我帮你捋捋你遇到的两个问题:密码显示乱码和登录失败,其实根源都是没完全匹配SqlMembershipProvider的密码哈希逻辑,咱们一步步解决:

先说说密码显示乱码的原因

你看,aspnet_Membership表的Password字段类型是NVARCHAR(128),不是VARBINARY!你直接把HASHBYTES生成的二进制哈希值插进去,SQL Server会自动把二进制数据转成字符串,但这个转换过程因为编码不匹配就出现了中文乱码——这其实只是显示层面的问题,核心还是登录失败的逻辑错误,咱们重点解决这个。

登录失败的核心原因

SqlMembershipProvider的密码哈希逻辑不是简单的SHA2_256(密码+salt字符串),它的标准流程是这样的:

  1. 把salt转成字节数组(通常是Base64编码字符串对应的字节)
  2. 把密码转成Unicode(UTF-16LE)字节数组
  3. 按顺序拼接salt字节数组和密码字节数组
  4. 用配置的哈希算法(默认是SHA1,如果你改了是SHA2_256就用这个)计算哈希
  5. 把哈希结果转成Base64字符串存在Password字段;salt的Base64字符串存在PasswordSalt字段

你的代码犯了两个关键错误:

  • 直接把二进制哈希值插入NVARCHAR的Password字段,而不是转成Provider期望的Base64字符串
  • 哈希过程是拼接字符串再哈希,而不是拼接字节数组再哈希,这会导致哈希结果和Provider验证时的结果完全不一致

解决方法

方法一:最稳妥的方式——用.NET代码创建用户

直接在你的应用里调用Membership.CreateUser()方法,这会自动帮你完成所有哈希和表插入操作,完全符合Provider逻辑,不会出问题。比如:

MembershipCreateStatus status;
MembershipUser user = Membership.CreateUser("admin", "P@ssw0rd123", "admin@example.com", null, null, true, out status);

方法二:必须用SQL手动插入的话,模拟Provider逻辑

下面是符合标准流程的SQL代码,替换成你的应用名和用户名就能用:

DECLARE @ApplicationName NVARCHAR(256) = '你的应用名称'; -- 替换成实际的ApplicationName
DECLARE @UserName NVARCHAR(256) = 'admin'; -- 要创建的用户名
DECLARE @Password NVARCHAR(128) = 'P@ssw0rd123';

-- 获取对应的ApplicationId
DECLARE @ApplicationId UNIQUEIDENTIFIER = (SELECT ApplicationId FROM aspnet_Applications WHERE ApplicationName = @ApplicationName);

-- 生成随机salt:转成字节数组再转Base64字符串(和Provider逻辑一致)
DECLARE @SaltBytes VARBINARY(16) = CAST(NEWID() AS VARBINARY(16));
DECLARE @Salt NVARCHAR(24) = sys.fn_varbintobase64(@SaltBytes);

-- 把密码转成Unicode字节数组
DECLARE @PasswordBytes VARBINARY(MAX) = CAST(@Password AS VARBINARY(MAX));

-- 拼接salt字节 + 密码字节
DECLARE @CombinedBytes VARBINARY(MAX) = @SaltBytes + @PasswordBytes;

-- 计算SHA2_256哈希(如果你的Provider配置的是SHA1,就改成'SHA1')
DECLARE @HashedBytes VARBINARY(64) = HASHBYTES('SHA2_256', @CombinedBytes);

-- 把哈希结果转成Base64字符串,存入Password字段
DECLARE @HashedPassword NVARCHAR(88) = sys.fn_varbintobase64(@HashedBytes);

-- 生成唯一UserId
DECLARE @UserId UNIQUEIDENTIFIER = NEWID();

-- 别忘了先插入aspnet_Users表!Membership表依赖这个表的UserId
INSERT INTO aspnet_Users (ApplicationId, UserId, UserName, LoweredUserName, IsAnonymous, LastActivityDate)
VALUES (@ApplicationId, @UserId, @UserName, LOWER(@UserName), 0, GETDATE());

-- 插入aspnet_Membership表
INSERT INTO aspnet_Membership (
    ApplicationId, 
    UserId, 
    Password, 
    PasswordSalt, 
    IsApproved, 
    IsLockedOut, 
    CreateDate, 
    LastLoginDate, 
    LastPasswordChangedDate, 
    LastLockoutDate, 
    FailedPasswordAttemptCount, 
    FailedPasswordAttemptWindowStart, 
    FailedPasswordAnswerAttemptCount, 
    FailedPasswordAnswerAttemptWindowStart
)
VALUES (
    @ApplicationId, 
    @UserId, 
    @HashedPassword, 
    @Salt, 
    1, 
    0, 
    GETDATE(), 
    GETDATE(), 
    GETDATE(), 
    '17540101', 
    0, 
    GETDATE(), 
    0, 
    GETDATE()
);

执行完这个代码后,你再查询aspnet_Membership表,Password字段会显示正常的Base64字符串,不会乱码,而且登录时也能正确验证了。

另外提醒下:如果你的MembershipProvider配置里的哈希算法不是SHA2_256(默认是SHA1),记得把代码里的HASHBYTES('SHA2_256', ...)改成对应的算法名称。

备注:内容来源于stack exchange,提问作者Mahmoud Ashraf

火山引擎 最新活动