C# ASP.NET成员资格提供程序-重置密码功能-电子邮件确认和密码更改

C# ASP.NET成员资格提供程序-重置密码功能-电子邮件确认和密码更改,c#,asp.net,asp.net-membership,forgot-password,password-recovery,C#,Asp.net,Asp.net Membership,Forgot Password,Password Recovery,是否有人有以下功能的解决方案(示例代码): 以加密方式创建随机GUID/GUID 强随机数 发送一个唯一的URL,其中包含 随机数发送到用户的电子邮件 地址 确认后,会询问用户 更改密码 “我的提供程序”当前以以下方式参数化: enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" applicationName="/" requiresUniqueEma

是否有人有以下功能的解决方案(示例代码):

  • 以加密方式创建随机GUID/GUID 强随机数
  • 发送一个唯一的URL,其中包含 随机数发送到用户的电子邮件 地址
  • 确认后,会询问用户 更改密码
“我的提供程序”当前以以下方式参数化:

enablePasswordRetrieval="false" 
enablePasswordReset="true" 
requiresQuestionAndAnswer="false" 
applicationName="/" 
requiresUniqueEmail="true" 
passwordFormat="Hashed" 
maxInvalidPasswordAttempts="5" 
minRequiredPasswordLength="5" 
minRequiredNonalphanumericCharacters="0" 
passwordAttemptWindow="10" 
passwordStrengthRegularExpression="" 
name="AspNetSqlMembershipProvider"

这种类型的过程的安全问题以前已经讨论过了。

Rui,几月前我也在一条类似的船上,之前没有与会员提供商有过太多接触,我努力让它正确地实现,因为我认为你必须实现和使用整个过程,或者什么都没有

我很快发现你只能使用它的一部分,而不是整个物体。例如,在我的应用程序中,我有自己的用户对象、密码和登录模块,但我需要让表单身份验证工作起来。所以我基本上只是使用会员资格提供者来完成这一部分。我没有重写任何方法或任何东西,只是将其用于FormsAuthentication,然后我使用自己的存储库来更改密码、验证用户名密码等

下面是我在MVC中登录代码的一个片段

   var authTicket =  new FormsAuthenticationTicket(1, user.UniqueName, DateTime.UtcNow, DateTime.UtcNow.AddHours(2), rememberMe, cookieValues);
    var encryptedTicket = FormsAuthentication.Encrypt(authTicket);
    var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket) { Expires = DateTime.UtcNow.AddDays(14) };

    httpResponseBase.Cookies.Add(authCookie);
这使我能够使用FormsAuthentication.SignOut();方法和成员资格提供程序提供的其他方法

关于您的问题,请重新创建一个随机GUID/加密强随机数,这里有一个很好的方法,您可以使用,我刚才找到了,很抱歉,我记不起在web上的什么位置

/// <summary>
/// A simple class which can be used to generate "unguessable" verifier values.
/// </summary>
public class UnguessableGenerator
{
    const string AllowableCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/^()";
    const string SimpleAllowableCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    /// <summary>
    /// Generates an unguessable string sequence of a certain length
    /// </summary>
    /// <param name="length">The length.</param>
    /// <param name="useSimpleCharacterSet">if set to <c>true</c> [use simple character set].</param>
    /// <returns></returns>
    public static string GenerateUnguessable(int length, bool useSimpleCharacterSet = false, string additionalCharacters = "")
    {
        var random = new Random();

        var chars = new char[length];

        var charsToUse = useSimpleCharacterSet ? SimpleAllowableCharacters : AllowableCharacters;
        charsToUse = string.Format("{0}{1}", charsToUse, additionalCharacters);

        var allowableLength = charsToUse.Length;

        for (var i = 0; i < length; i++)
        {
            chars[i] = charsToUse[random.Next(allowableLength)];
        }

        return new string(chars);
    }




    /// <summary>
    /// Generates an ungessable string, defaults the length to what google uses (24 characters)
    /// </summary>
    /// <returns></returns>
    public static string GenerateUnguessable()
    {
        return GenerateUnguessable(24);
    }
}
//
///一个简单的类,可用于生成“不可用”的验证器值。
/// 
公共类不可用生成器
{
const string AllowableCharacters=“abcdefghjjklmnopqrstuvwxyzabcdefghjjklmnopqrstuvwxyzo123456789/^()”;
常量字符串SimpleAllowableCharacters=“abcdefghijklmnopqrstuvxyz012456789”;
/// 
///生成特定长度的不可用字符串序列
/// 
///长度。
///如果设置为true[使用简单字符集]。
/// 
公共静态字符串GenerateUnguessable(int-length,bool-useSimpleCharacterSet=false,string-additionalCharacters=“”)
{
var random=新的random();
var chars=新字符[长度];
var charsToUse=useSimpleCharacterSet?SimpleAllowableCharacters:AllowableCharacters;
charsToUse=string.Format(“{0}{1}”,charsToUse,其他字符);
var allowableLength=charsToUse.Length;
对于(变量i=0;i
要将包含随机数的唯一URL发送到用户的电子邮件地址,您需要在用户表或任何表中存储随机id,然后在用户可用于验证的电子邮件中的精心编制的URL中使用该id

这将要求您创建一个接受该类型Url的Url,然后您必须从querystring中提取所需的部分并更新用户对象

因为当确认后,会要求用户更改密码,默认情况下,表中会有一个位标志,强制用户更改其密码,如果您需要强制用户更改密码,这也会在以后派上用场。然后,您的登录代码查看此位标志是否打开,如果打开,它将首先强制更改密码。一旦用户更改了密码,您将关闭此标志


希望这有帮助。

至少使用Guid类作为Guid。 您可以自定义结果

var guid = Guid.NewGuid();
。。。。。 发送链接

var msg = new MailMessage();
msg.From = new MailAddress("YOUR_ADDRESS");
msg.To.Add(new MailAddress("CLIENT_ADDRESS"));
msg.Subject = "YOUR SUBJECT";
msg.Body = @" SOME TXT.... http:\\resetPassword.aspx?guid=" + guid;
var smtpClient = new SmtpClient("SMTP_SERVER", 9990);
smtpClient.Send(msg);


在您只需执行resetPassword.aspx之类的网页并在页面中进行处理后,加载参数“guid”,该参数应链接到数据库中的用户

因线程滥用而被否决。在代码示例中睡眠-如果您想要真正的随机数据,请使用crypto rng提供程序。在此处,将其删除。一旦考虑到竞争条件,您就会意识到没有“真实”的随机数据。使用Guid,为什么要在保证Guid唯一的情况下遇到所有这些问题?请查看System.Security.Cryptography中的crypto rng提供程序以生成您的随机数,并使用简单的映射将其转换为字母数字字符-所有小写,跳过字母i、l和o以避免混淆(也可以跳过所有元音以避免讨厌的单词)。在数据库中存储电子邮件地址和随机密钥,创建简单页面,捕获新密码等,并使用密钥查找用户,然后调用user.ChangePassword(mu.ResetPassword(),password)更改密码。您可以在