外部应用匹配DNN数据库密码遇错:找不到存储过程dbo.aspnet_Membership_GetPasswordWithFormat
解决DNN数据库外部系统登录的密码匹配与存储过程问题
首先,咱们一步步拆解你遇到的两个核心问题:找不到存储过程,以及TripleDES密码匹配的实现思路。
一、先解决dbo.aspnet_Membership_GetPasswordWithFormat找不到的问题
DNN并没有使用ASP.NET默认的会员存储过程,它有自己定制的一套,前缀通常是dnn_(如果你的DNN实例设置了对象限定符,前缀会是你设置的内容,比如myDnn_)。你完全可以跳过调用存储过程,直接查询DNN的会员表来获取所需数据:
-- 替换dnn_为你的实例对象限定符(如果有的话) SELECT Password, PasswordFormat, PasswordSalt FROM dnn_Membership WHERE UserId = (SELECT UserId FROM dnn_Users WHERE Username = @Username)
这条SQL会直接返回对应用户的加密密码、密码格式(你已经知道是2,对应TripleDES加密),以及密码盐(如果有的话,不过加密格式下通常用不到)。
二、实现TripleDES密码匹配(无需解密)
你不想解密密码的思路是对的——咱们只需要把用户输入的明文密码,用和DNN完全相同的加密规则处理,再和数据库里的加密密码对比即可。关键是要拿到DNN的加密密钥,以及匹配正确的加密逻辑:
1. 获取DNN的TripleDES密钥
登录到DNN所在服务器,找到网站根目录下的web.config文件,定位到<machineKey>节点:
<machineKey validationKey="..." decryptionKey="你的TripleDES密钥(十六进制字符串)" decryption="3DES" validation="SHA1" />
你需要的是decryptionKey的值,这个就是DNN用来加密密码的TripleDES密钥,必须和DNN使用的完全一致,否则加密结果无法匹配。
2. 编写密码匹配逻辑
用和DNN相同的加密规则处理用户输入的密码,再对比数据库中的存储值。这里给你一个C#的示例(其他语言逻辑类似):
using System.Security.Cryptography; using System.Text; public bool ValidateDnnPassword(string inputPassword, string storedEncryptedPassword, string dnnDecryptionKey) { // 将十六进制密钥转为字节数组 byte[] key = HexToByteArray(dnnDecryptionKey); using (TripleDES des = TripleDES.Create()) { des.Key = key; // 严格匹配ASP.NET/DNN的TripleDES参数:CBC模式、PKCS7填充,IV取密钥前8字节 des.Mode = CipherMode.CBC; des.Padding = PaddingMode.PKCS7; des.IV = key.Take(8).ToArray(); // 加密用户输入的密码(DNN用Unicode编码) byte[] inputBytes = Encoding.Unicode.GetBytes(inputPassword); using (ICryptoTransform encryptor = des.CreateEncryptor()) { byte[] encryptedInput = encryptor.TransformFinalBlock(inputBytes, 0, inputBytes.Length); // 转为Base64字符串(DNN存储的加密密码是Base64格式) string encryptedInputStr = Convert.ToBase64String(encryptedInput); // 对比是否一致 return encryptedInputStr.Equals(storedEncryptedPassword, StringComparison.Ordinal); } } } // 辅助方法:十六进制字符串转字节数组 private byte[] HexToByteArray(string hexStr) { int byteCount = hexStr.Length / 2; byte[] result = new byte[byteCount]; for (int i = 0; i < byteCount; i++) { result[i] = Convert.ToByte(hexStr.Substring(i * 2, 2), 16); } return result; }
3. 注意事项
- 确保编码一致:DNN用Unicode(UTF-16)处理密码,所以加密时必须用
Encoding.Unicode,不能用UTF-8。 - 密钥安全:拿到密钥后务必妥善保管,不要泄露——虽然你只用来加密匹配,但它确实可以用来解密所有用户的密码,存在安全风险。
- 如果DNN的
machineKey里decryptionKey是AutoGenerate,IsolateApps,那你无法获取固定密钥,这种情况只能联系DNN管理员修改为固定密钥,或者通过DNN的API来完成登录验证。
内容的提问来源于stack exchange,提问作者Lenrice
相关产品推荐
相关产品推荐

