// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!

using System.Security.Cryptography;

namespace Admin.NET.Core;

/// <summary>
/// 密码生成工具类
/// </summary>
public static class PasswordHelper
{
    /// <summary>
    /// 默认密码字符集
    /// </summary>
    private static readonly string LowercaseChars = "abcdefghijklmnopqrstuvwxyz";
    private static readonly string UppercaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static readonly string DigitChars = "0123456789";
    private static readonly string SpecialChars = "!@#$%^&*()_+-=[]{}|;:,.<>?";

    /// <summary>
    /// 密码生成选项
    /// </summary>
    public class PasswordOptions
    {
        /// <summary>
        /// 密码长度,默认12位
        /// </summary>
        public int Length { get; set; } = 12;

        /// <summary>
        /// 是否包含小写字母,默认true
        /// </summary>
        public bool IncludeLowercase { get; set; } = true;

        /// <summary>
        /// 是否包含大写字母,默认true
        /// </summary>
        public bool IncludeUppercase { get; set; } = true;

        /// <summary>
        /// 是否包含数字,默认true
        /// </summary>
        public bool IncludeDigits { get; set; } = true;

        /// <summary>
        /// 是否包含特殊字符,默认true
        /// </summary>
        public bool IncludeSpecialChars { get; set; } = true;

        /// <summary>
        /// 排除的字符,默认空
        /// </summary>
        public string ExcludeChars { get; set; } = string.Empty;

        /// <summary>
        /// 是否排除相似字符(如0、O、l、I等),默认false
        /// </summary>
        public bool ExcludeSimilarChars { get; set; } = false;

        /// <summary>
        /// 是否排除歧义字符,默认false
        /// </summary>
        public bool ExcludeAmbiguousChars { get; set; } = false;
    }

    /// <summary>
    /// 生成随机密码
    /// </summary>
    /// <param name="options">密码生成选项</param>
    /// <returns>生成的密码</returns>
    public static string GeneratePassword(PasswordOptions options = null)
    {
        options ??= new PasswordOptions();

        // 验证选项
        ValidateOptions(options);

        // 构建字符集
        var charSet = BuildCharSet(options);
        if (string.IsNullOrEmpty(charSet))
            throw new ArgumentException("至少需要包含一种字符类型");

        // 生成密码
        var password = new char[options.Length];
        var random = RandomNumberGenerator.Create();

        // 确保每种类型的字符至少出现一次
        var requiredChars = GetRequiredChars(options);
        for (int i = 0; i < requiredChars.Length; i++)
        {
            password[i] = requiredChars[i];
        }

        // 填充剩余位置
        for (int i = requiredChars.Length; i < options.Length; i++)
        {
            password[i] = GetRandomChar(charSet, random);
        }

        // 打乱密码字符顺序
        ShufflePassword(password, random);

        return new string(password);
    }

    /// <summary>
    /// 生成简单密码(仅数字)
    /// </summary>
    /// <param name="length">密码长度</param>
    /// <returns>生成的密码</returns>
    public static string GenerateSimplePassword(int length = 6)
    {
        var options = new PasswordOptions
        {
            Length = length,
            IncludeLowercase = false,
            IncludeUppercase = false,
            IncludeDigits = true,
            IncludeSpecialChars = false
        };
        return GeneratePassword(options);
    }

    /// <summary>
    /// 生成强密码
    /// </summary>
    /// <param name="length">密码长度,默认16位</param>
    /// <returns>生成的密码</returns>
    public static string GenerateStrongPassword(int length = 16)
    {
        var options = new PasswordOptions
        {
            Length = length,
            IncludeLowercase = true,
            IncludeUppercase = true,
            IncludeDigits = true,
            IncludeSpecialChars = true,
            ExcludeSimilarChars = true,
            ExcludeAmbiguousChars = true
        };
        return GeneratePassword(options);
    }

    /// <summary>
    /// 生成记忆密码(易读易记)
    /// </summary>
    /// <param name="length">密码长度,默认12位</param>
    /// <returns>生成的密码</returns>
    public static string GenerateMemorablePassword(int length = 12)
    {
        var options = new PasswordOptions
        {
            Length = length,
            IncludeLowercase = true,
            IncludeUppercase = true,
            IncludeDigits = true,
            IncludeSpecialChars = false,
            ExcludeSimilarChars = true,
            ExcludeAmbiguousChars = true
        };
        return GeneratePassword(options);
    }

    /// <summary>
    /// 验证密码强度
    /// </summary>
    /// <param name="password">要验证的密码</param>
    /// <returns>密码强度等级</returns>
    public static PasswordStrength ValidatePasswordStrength(string password)
    {
        if (string.IsNullOrEmpty(password))
            return PasswordStrength.VeryWeak;

        int score = 0;
        bool hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;

        foreach (char c in password)
        {
            if (char.IsLower(c)) hasLower = true;
            else if (char.IsUpper(c)) hasUpper = true;
            else if (char.IsDigit(c)) hasDigit = true;
            else if (IsSpecialChar(c)) hasSpecial = true;
        }

        // 长度评分
        if (password.Length >= 8) score += 1;
        if (password.Length >= 12) score += 1;
        if (password.Length >= 16) score += 1;

        // 字符类型评分
        if (hasLower) score += 1;
        if (hasUpper) score += 1;
        if (hasDigit) score += 1;
        if (hasSpecial) score += 1;

        // 复杂度评分
        if (password.Length >= 8 && hasLower && hasUpper && hasDigit) score += 1;
        if (password.Length >= 12 && hasLower && hasUpper && hasDigit && hasSpecial) score += 1;

        return score switch
        {
            <= 2 => PasswordStrength.VeryWeak,
            <= 4 => PasswordStrength.Weak,
            <= 6 => PasswordStrength.Medium,
            <= 8 => PasswordStrength.Strong,
            _ => PasswordStrength.VeryStrong
        };
    }

    /// <summary>
    /// 检查密码是否满足要求
    /// </summary>
    /// <param name="password">要检查的密码</param>
    /// <param name="minLength">最小长度</param>
    /// <param name="requireLowercase">是否需要小写字母</param>
    /// <param name="requireUppercase">是否需要大写字母</param>
    /// <param name="requireDigits">是否需要数字</param>
    /// <param name="requireSpecialChars">是否需要特殊字符</param>
    /// <returns>是否满足要求</returns>
    public static bool CheckPasswordRequirements(string password, int minLength = 8, 
        bool requireLowercase = true, bool requireUppercase = true, 
        bool requireDigits = true, bool requireSpecialChars = false)
    {
        if (string.IsNullOrEmpty(password) || password.Length < minLength)
            return false;

        bool hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;

        foreach (char c in password)
        {
            if (char.IsLower(c)) hasLower = true;
            else if (char.IsUpper(c)) hasUpper = true;
            else if (char.IsDigit(c)) hasDigit = true;
            else if (IsSpecialChar(c)) hasSpecial = true;
        }

        return (!requireLowercase || hasLower) &&
               (!requireUppercase || hasUpper) &&
               (!requireDigits || hasDigit) &&
               (!requireSpecialChars || hasSpecial);
    }

    /// <summary>
    /// 密码强度枚举
    /// </summary>
    public enum PasswordStrength
    {
        /// <summary>
        /// 非常弱
        /// </summary>
        VeryWeak,
        /// <summary>
        /// 弱
        /// </summary>
        Weak,
        /// <summary>
        /// 中等
        /// </summary>
        Medium,
        /// <summary>
        /// 强
        /// </summary>
        Strong,
        /// <summary>
        /// 非常强
        /// </summary>
        VeryStrong
    }

    #region 私有方法

    /// <summary>
    /// 验证密码生成选项
    /// </summary>
    private static void ValidateOptions(PasswordOptions options)
    {
        if (options.Length < 1)
            throw new ArgumentException("密码长度必须大于0", nameof(options.Length));

        if (options.Length > 128)
            throw new ArgumentException("密码长度不能超过128位", nameof(options.Length));

        if (!options.IncludeLowercase && !options.IncludeUppercase && 
            !options.IncludeDigits && !options.IncludeSpecialChars)
            throw new ArgumentException("至少需要包含一种字符类型");
    }

    /// <summary>
    /// 构建字符集
    /// </summary>
    private static string BuildCharSet(PasswordOptions options)
    {
        var charSet = string.Empty;

        if (options.IncludeLowercase)
            charSet += GetFilteredChars(LowercaseChars, options);

        if (options.IncludeUppercase)
            charSet += GetFilteredChars(UppercaseChars, options);

        if (options.IncludeDigits)
            charSet += GetFilteredChars(DigitChars, options);

        if (options.IncludeSpecialChars)
            charSet += GetFilteredChars(SpecialChars, options);

        return charSet;
    }

    /// <summary>
    /// 获取过滤后的字符
    /// </summary>
    private static string GetFilteredChars(string chars, PasswordOptions options)
    {
        var filteredChars = chars;

        // 排除指定字符
        if (!string.IsNullOrEmpty(options.ExcludeChars))
        {
            foreach (char c in options.ExcludeChars)
            {
                filteredChars = filteredChars.Replace(c.ToString(), "");
            }
        }

        // 排除相似字符
        if (options.ExcludeSimilarChars)
        {
            filteredChars = filteredChars.Replace("0", "").Replace("O", "").Replace("o", "")
                                        .Replace("1", "").Replace("l", "").Replace("I", "");
        }

        // 排除歧义字符
        if (options.ExcludeAmbiguousChars)
        {
            filteredChars = filteredChars.Replace("B", "").Replace("8", "")
                                        .Replace("G", "").Replace("6", "")
                                        .Replace("S", "").Replace("5", "");
        }

        return filteredChars;
    }

    /// <summary>
    /// 获取必需的字符
    /// </summary>
    private static char[] GetRequiredChars(PasswordOptions options)
    {
        var requiredChars = new List<char>();
        var random = RandomNumberGenerator.Create();

        if (options.IncludeLowercase)
        {
            var chars = GetFilteredChars(LowercaseChars, options);
            if (!string.IsNullOrEmpty(chars))
                requiredChars.Add(GetRandomChar(chars, random));
        }

        if (options.IncludeUppercase)
        {
            var chars = GetFilteredChars(UppercaseChars, options);
            if (!string.IsNullOrEmpty(chars))
                requiredChars.Add(GetRandomChar(chars, random));
        }

        if (options.IncludeDigits)
        {
            var chars = GetFilteredChars(DigitChars, options);
            if (!string.IsNullOrEmpty(chars))
                requiredChars.Add(GetRandomChar(chars, random));
        }

        if (options.IncludeSpecialChars)
        {
            var chars = GetFilteredChars(SpecialChars, options);
            if (!string.IsNullOrEmpty(chars))
                requiredChars.Add(GetRandomChar(chars, random));
        }

        return requiredChars.ToArray();
    }

    /// <summary>
    /// 获取随机字符
    /// </summary>
    private static char GetRandomChar(string charSet, RandomNumberGenerator random)
    {
        var randomBytes = new byte[4];
        random.GetBytes(randomBytes);
        var randomValue = Math.Abs(BitConverter.ToInt32(randomBytes, 0));
        return charSet[randomValue % charSet.Length];
    }

    /// <summary>
    /// 打乱密码字符顺序
    /// </summary>
    private static void ShufflePassword(char[] password, RandomNumberGenerator random)
    {
        for (int i = password.Length - 1; i > 0; i--)
        {
            var randomBytes = new byte[4];
            random.GetBytes(randomBytes);
            var randomValue = Math.Abs(BitConverter.ToInt32(randomBytes, 0));
            int j = randomValue % (i + 1);
            (password[i], password[j]) = (password[j], password[i]);
        }
    }

    /// <summary>
    /// 判断是否为特殊字符
    /// </summary>
    private static bool IsSpecialChar(char c)
    {
        return SpecialChars.Contains(c);
    }

    #endregion
}

使用方法:

// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。

//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!

namespace Admin.NET.Core;

/// <summary>
/// 密码生成工具类使用示例
/// </summary>
public static class PasswordHelperExample
{

/// &lt;summary&gt;
/// 使用示例
/// &lt;/summary&gt;
public static void UsageExamples()
{
    // 1. 生成默认密码(12位,包含大小写字母、数字、特殊字符)
    var defaultPassword = PasswordHelper.GeneratePassword(new PasswordHelper.PasswordOptions { Length = 8 });
    Console.WriteLine($"默认密码: {defaultPassword}");

    // 2. 生成简单密码(仅数字)
    var simplePassword = PasswordHelper.GenerateSimplePassword(8);
    Console.WriteLine($"简单密码: {simplePassword}");

    // 3. 生成强密码
    var strongPassword = PasswordHelper.GenerateStrongPassword(20);
    Console.WriteLine($"强密码: {strongPassword}");

    // 4. 生成记忆密码(易读易记)
    var memorablePassword = PasswordHelper.GenerateMemorablePassword(14);
    Console.WriteLine($"记忆密码: {memorablePassword}");

    // 5. 自定义密码生成选项
    var customOptions = new PasswordHelper.PasswordOptions
    {
        Length = 16,
        IncludeLowercase = true,
        IncludeUppercase = true,
        IncludeDigits = true,
        IncludeSpecialChars = true,
        ExcludeSimilarChars = true,  // 排除相似字符
        ExcludeAmbiguousChars = true, // 排除歧义字符
        ExcludeChars = "0O1lI"        // 排除指定字符
    };
    var customPassword = PasswordHelper.GeneratePassword(customOptions);
    Console.WriteLine($"自定义密码: {customPassword}");

    // 6. 验证密码强度
    var testPasswords = new[]
    {
        "123456",
        "password",
        "Password123",
        "MyStr0ng!P@ssw0rd",
        "VeryC0mpl3x&amp;P@ssw0rd!2024"
    };

    foreach (var pwd in testPasswords)
    {
        var strength = PasswordHelper.ValidatePasswordStrength(pwd);
        Console.WriteLine($"密码: {pwd} - 强度: {strength}");
    }

    // 7. 检查密码是否满足要求
    var testPassword = "MyPassword123!";
    var meetsRequirements = PasswordHelper.CheckPasswordRequirements(
        testPassword, 
        minLength: 8, 
        requireLowercase: true, 
        requireUppercase: true, 
        requireDigits: true, 
        requireSpecialChars: true
    );
    Console.WriteLine($"密码 '{testPassword}' 是否满足要求: {meetsRequirements}");

    // 8. 批量生成密码
    Console.WriteLine("\n批量生成密码:");
    for (int i = 1; i &lt;= 5; i++)
    {
        var batchPassword = PasswordHelper.GeneratePassword();
        var strength = PasswordHelper.ValidatePasswordStrength(batchPassword);
        Console.WriteLine($"密码 {i}: {batchPassword} (强度: {strength})");
    }
}

/// &lt;summary&gt;
/// 密码策略验证示例
/// &lt;/summary&gt;
public static void PasswordPolicyExample()
{
    // 企业级密码策略
    var enterprisePolicy = new PasswordHelper.PasswordOptions
    {
        Length = 12,
        IncludeLowercase = true,
        IncludeUppercase = true,
        IncludeDigits = true,
        IncludeSpecialChars = true,
        ExcludeSimilarChars = true,
        ExcludeAmbiguousChars = true
    };

    // 生成符合企业策略的密码
    var enterprisePassword = PasswordHelper.GeneratePassword(enterprisePolicy);
    Console.WriteLine($"企业级密码: {enterprisePassword}");

    // 验证密码强度
    var strength = PasswordHelper.ValidatePasswordStrength(enterprisePassword);
    Console.WriteLine($"密码强度: {strength}");

    // 检查是否满足企业要求
    var meetsEnterpriseRequirements = PasswordHelper.CheckPasswordRequirements(
        enterprisePassword,
        minLength: 12,
        requireLowercase: true,
        requireUppercase: true,
        requireDigits: true,
        requireSpecialChars: true
    );
    Console.WriteLine($"是否满足企业要求: {meetsEnterpriseRequirements}");
}

/// &lt;summary&gt;
/// 不同场景的密码生成示例
/// &lt;/summary&gt;
public static void DifferentScenariosExample()
{
    Console.WriteLine("=== 不同场景的密码生成 ===");

    // 1. 用户注册密码
    var userPassword = PasswordHelper.GenerateMemorablePassword(10);
    Console.WriteLine($"用户注册密码: {userPassword}");

    // 2. 管理员密码
    var adminPassword = PasswordHelper.GenerateStrongPassword(16);
    Console.WriteLine($"管理员密码: {adminPassword}");

    // 3. API密钥
    var apiKey = PasswordHelper.GeneratePassword(new PasswordHelper.PasswordOptions
    {
        Length = 32,
        IncludeLowercase = true,
        IncludeUppercase = true,
        IncludeDigits = true,
        IncludeSpecialChars = false,
        ExcludeSimilarChars = true
    });
    Console.WriteLine($"API密钥: {apiKey}");

    // 4. 临时密码
    var tempPassword = PasswordHelper.GenerateSimplePassword(8);
    Console.WriteLine($"临时密码: {tempPassword}");

    // 5. 数据库密码
    var dbPassword = PasswordHelper.GeneratePassword(new PasswordHelper.PasswordOptions
    {
        Length = 20,
        IncludeLowercase = true,
        IncludeUppercase = true,
        IncludeDigits = true,
        IncludeSpecialChars = true,
        ExcludeChars = "!@#$%^&amp;*()" // 排除可能引起问题的特殊字符
    });
    Console.WriteLine($"数据库密码: {dbPassword}");
}

}

发表评论