14

我使用网站作为前端,所有用户都通过标准 ASP.NET Membership-Provider 进行身份验证。密码以“散列”形式保存在 SQL 数据库中。

现在我想编写一个具有管理功能的桌面客户端。除其他外,应该有一种方法可以重置用户密码。我可以使用保存的会员数据访问数据库,但是如何手动创建密码盐和哈希?使用 System.Web.Membership 命名空间似乎不合适,所以我需要知道如何手动创建新密码的 salt 和 hash。

专家站出来!:)

4

4 回答 4

17

我使用反射器来查看 .NET-Framework 内部使用的那些方法。也许有可用的公共方法,但我没有找到它们 - 如果您知道如何以用户身份查询这些内部方法,请留下评论!:)

这是没有不必要条件的简化源代码,因为我只想将密码编码为 SHA1-Hash:

private string GenerateSalt() {
  var buf = new byte[16];
  (new RNGCryptoServiceProvider()).GetBytes(buf);
  return Convert.ToBase64String(buf);
}

private string EncodePassword(string pass, string salt) {
    byte[] bytes = Encoding.Unicode.GetBytes(pass);
    byte[] src = Convert.FromBase64String(salt);
    byte[] dst = new byte[src.Length + bytes.Length];
    byte[] inArray = null;
    Buffer.BlockCopy(src, 0, dst, 0, src.Length);
    Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
    HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
    inArray = algorithm.ComputeHash(dst);
    return Convert.ToBase64String(inArray);
}
于 2010-03-31T09:24:06.323 回答
13

您绝对可以System.Web.Security在控制台或 winforms 应用程序中使用。

这是一个简单的控制台应用程序:

static void Main(string[] args)
{
    MembershipProvider provider = Membership.Provider;

    MembershipUser myUser = provider.GetUser("myUser", false);

    if( myUser != null ) provider.DeleteUser("myUser", true);

    MembershipCreateStatus status;

    myUser = provider.CreateUser("myUser", "password", "user@example.com", null, null, true, null, out status);

    if (status != MembershipCreateStatus.Success)
    {
        Console.WriteLine("Could not create user.  Reason: " + status.ToString());
        Console.ReadLine();
        return;
    }

    Console.WriteLine("Authenticating with \"password\": " + provider.ValidateUser("myUser", "password").ToString());

    string newPassword = myUser.ResetPassword();

    Console.WriteLine("Authenticating with \"password\": " + provider.ValidateUser("myUser", "password").ToString());
    Console.WriteLine("Authenticating with new password: " + provider.ValidateUser("myUser", newPassword).ToString());

    Console.ReadLine();
}

和 app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <connectionStrings>
        <add name="MyConnectionString" connectionString="Data Source=localhost;Initial Catalog=MyDatabase;Integrated Security=True" providerName="System.Data.SqlClient" />
    </connectionStrings>
    <system.web>
        <membership defaultProvider="MyMembershipProvider">
            <providers>
                <clear />
                <add name="MyMembershipProvider"
                     type="System.Web.Security.SqlMembershipProvider"
                     connectionStringName="MyConnectionString"
                     applicationName="MyApplication"
                     minRequiredPasswordLength="5"
                     minRequiredNonalphanumericCharacters="0"
                     requiresQuestionAndAnswer="false" />
            </providers>
        </membership>
    </system.web>
</configuration>
于 2010-03-31T20:18:46.237 回答
1

快速脏方法

Public Shared Function GetSaltKey() As String
            Dim saltBytes() As Byte
            Dim minSaltSize As Integer = 4
            Dim maxSaltSize As Integer = 8

            ' Generate a random number for the size of the salt.
            Dim random As Random
            random = New Random()

            Dim saltSize As Integer
            saltSize = random.Next(minSaltSize, maxSaltSize)

            ' Allocate a byte array, which will hold the salt.
            saltBytes = New Byte(saltSize - 1) {}

            ' Initialize a random number generator.
            Dim rng As RNGCryptoServiceProvider
            rng = New RNGCryptoServiceProvider()

            ' Fill the salt with cryptographically strong byte values.
            rng.GetNonZeroBytes(saltBytes)

            ' Convert plain text into a byte array.
            Return Convert.ToBase64String(saltBytes)
        End Function

        Public Shared Function ComputeHash(ByVal password As String, ByVal salt As String) As String

            Return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(salt & password, _
                System.Web.Configuration.FormsAuthPasswordFormat.SHA1.ToString)
        End Function

虽然,成员名称空间也为此内置了一些东西,如被遗忘的分号所述

于 2010-03-30T18:24:58.033 回答
1

自从我修改 ASP.Net 成员资格以来已经有一段时间了,但请记住处理与它有点相关的事情(由于现有的用户数据库需要自定义事情)。在这项工作中,我覆盖了这些方法(现有用户 db 具有 md5 散列密码)。

所以在同样的“思路”中:

通过您的桌面应用程序可以引用的 Web 服务公开 Membership API。这样,您不是在“重新创建”事物,而是在重新使用它们。您不必覆盖任何内容,您只需通过 Web 服务为您的桌面应用程序公开现有方法。

不用说,你必须保护这个端点......

如果以上内容对您来说太粗略了,这里有一个指向 asp.net 论坛的链接,其中涉及一些重新创建散列的尝试……我无法确认准确性,但应该很容易测试出来:

http://forums.asp.net/p/1336657/2899172.aspx

于 2010-03-31T00:35:30.753 回答