更改机器密钥时维护ASP.Net成员资格密码

3
有没有一种工具或代码示例,可以使用旧密钥解密,然后使用新密钥加密ASP.Net成员用户的密码?
3个回答

2

我尝试了所有提到的解决方法都不起作用。我的解决方案如下:首先以明文形式存储密码,然后再使用新的MachineKey重新加密。

更改MachineKey


1

这是我对解决方案的最佳猜测,但我还没有机会进行测试。它依赖于您当前提供商的以下设置:

enablePasswordRetrieval="true" requiresQuestionAndAnswer="false" passwordFormat="Encrypted"

它还假设新的machinekey已经在配置文件中。

创建以下类(感谢mootinator为此提供的起点)

using System.Reflection;
using System.Web.Configuration;
using System.Web.Security;
namespace MyNamespace
{
    public class MySqlMembershipProvider : SqlMembershipProvider
    {
        protected override byte[] DecryptPassword(byte[] encodedPassword)
        {
            MachineKeySection section = (MachineKeySection)WebConfigurationManager.GetSection("system.web/machineKey");
            section.DecryptionKey = "oldkey"; // TODO: Set your old key here

            MethodInfo method = typeof(MachineKeySection).GetMethod("EncryptOrDecryptData", BindingFlags.Instance | BindingFlags.NonPublic);

            return (byte[])method.Invoke(section, new object[] { encodedPassword, null, 0, encodedPassword.Length, 0, false, false });
        }
    }
}

在你的web.config文件中:
<membership defaultProvider="DefaultSqlMembershipProvider">
  <providers>
    <clear/>
    <add name="DefaultSqlMembershipProvider" connectionStringName="MembershipConnectionString" enablePasswordRetrieval="true" requiresQuestionAndAnswer="false" applicationName="TODO" passwordFormat="Encrypted" type="System.Web.Security.SqlMembershipProvider"/>
    <add name="MySqlMembershipProvider" connectionStringName="MembershipConnectionString" enablePasswordRetrieval="true" requiresQuestionAndAnswer="false" applicationName="TODO" passwordFormat="Encrypted" type="MyNamespace.MySqlMembershipProvider"/>
  </providers>
</membership>

用以下代码更改密码:

MembershipProvider retrievePasswordProvider = Membership.Providers["MySqlMembershipProvider"];

foreach (MembershipUser user in Membership.GetAllUsers())
{
    MembershipUser retrievePassworedUser = retrievePasswordProvider.GetUser(user.UserName, false);
    string password = retrievePassworedUser.GetPassword(); // get password using old key

    user.ChangePassword(password, password); // change password to same password using new key
}

如果这对你有用,请告诉我。


很好,如果这样可以避免写入中间位置,那就太好了。我会测试一下。 - ScottS
section.DecryptionKey = "oldkey"; 是只读的,不能被设置。除非有一种方法可以覆盖它,否则我最终是先检索/解密,然后保存到文件中,然后更改密钥并更新密码。 - Jack0fshad0ws
看起来很有前途,但是 typeof(MachineKeySection).GetMethod() 返回 null。 - Jonathan Wood
你可能需要在你的配置文件中添加一个MachineKey部分。我不是很确定。 - Greg

0

我认为你可以通过即时设置密钥来实现这一点:

你可能需要扩展SqlMembershipProvider(或者你使用的任何其他提供程序),以便访问protected DecryptPassword方法。

    MachineKeySection section = (MachineKeySection)WebConfigurationManager.GetSection("system.web/machineKey");

section.DecryptionKey = "old";
// Read old password
section.DecryptionKey = "new";
// Store new password

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接