将内部身份验证迁移到ASP.NET Core Identity

时间:2017-07-21 16:42:19

标签: asp.net-core asp.net-core-identity

我正在努力将非常旧网站从经典ASP升级到ASP.NET Core。部分原因是将用户(其密码以明文形式存储)自然地迁移到Identity中。我们正在使用单元测试项目来处理迁移,但该项目无法访问Identity,这是可以理解的。

这里最好的选择是什么?我看到的主要问题是将密码设置为正确的格式,但我认为我可以查看ASP.NET身份的来源并模仿正确散列迁移中的所有内容的功能。还有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

ASP.NET Identity 3使用的哈希算法是here。但是,除非您将其依赖项复制到项目中,否则在ASP.NET Idetity之外运行并不是 easy

HashPasswordV3

private static byte[] HashPasswordV3(string password, 
   RandomNumberGenerator rng, KeyDerivationPrf prf, 
   int iterCount, int saltSize, int numBytesRequested)
    {
    // Produce a version 3 (see comment above) text hash.
    byte[] salt = new byte[saltSize];
    rng.GetBytes(salt);
    byte[] subkey = KeyDerivation.Pbkdf2(
        password, salt, prf, iterCount, numBytesRequested);

    var outputBytes = new byte[13 + salt.Length + subkey.Length];
    outputBytes[0] = 0x01; // format marker
    WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
    WriteNetworkByteOrder(outputBytes, 5, (uint)iterCount);
    WriteNetworkByteOrder(outputBytes, 9, (uint)saltSize);
    Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
    Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
    return outputBytes;
}

VerifyHashedPasswordV3

private static bool VerifyHashedPasswordV3(byte[] hashedPassword, string password, out int iterCount)
{
    iterCount = default(int);

    try
    {
        // Read header information
        KeyDerivationPrf prf = (KeyDerivationPrf)ReadNetworkByteOrder(hashedPassword, 1);
        iterCount = (int)ReadNetworkByteOrder(hashedPassword, 5);
        int saltLength = (int)ReadNetworkByteOrder(hashedPassword, 9);

        // Read the salt: must be >= 128 bits
        if (saltLength < 128 / 8)
        {
            return false;
        }
        byte[] salt = new byte[saltLength];
        Buffer.BlockCopy(hashedPassword, 13, salt, 0, salt.Length);

        // Read the subkey (the rest of the payload): must be >= 128 bits
        int subkeyLength = hashedPassword.Length - 13 - salt.Length;
        if (subkeyLength < 128 / 8)
        {
            return false;
        }
        byte[] expectedSubkey = new byte[subkeyLength];
        Buffer.BlockCopy(hashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);

        // Hash the incoming password and verify it
        byte[] actualSubkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, subkeyLength);
        return ByteArraysEqual(actualSubkey, expectedSubkey);
    }
    catch
    {
        // This should never occur except in the case of a malformed payload, where
        // we might go off the end of the array. Regardless, a malformed payload
        // implies verification failed.
        return false;
    }
}

答案 1 :(得分:0)

密码是纯文本的,因此您只需从当前数据库加载每个用户,并使用Identity中的UserManager类将它们添加到新数据库。

UserManager类有CreateAsync方法,它接受密码并为您处理散列。

示例:

var user = new IdentityUser // or whatever your user class is
{
    UserName = userName,
    Email = email,
    // set other required properties
};

var result = await userManager.CreateAsync(user, password);

我建议在单独的程序中手动运行它作为一次性任务。您不希望此过程存在于新应用中。