您的密码不仅仅是字符串:为什么 C# 中的认证需要特殊方法
\n\n想象一下:您编写了一个完美的 C# 应用程序——拥有漂亮的界面、快速的查询和清晰的架构。但如果其中的认证存在漏洞,所有工作都将付诸东流。黑客不会破门而入——他们会配钥匙。在当今世界,C# 安全认证不是一种选择,而是代码的基本卫生。
\n\n在本文中,我们将讨论的不仅仅是理论,而是实际的保护方法:从正确的密码哈希到 JWT 和 OAuth 的集成。您将了解为什么没有加盐的 SHA256 是邪恶的,如何避免暴力攻击的陷阱,以及当您的项目已经超出“初级”认证方法时该怎么做。让我们开始吧!
\n\n安全的三大支柱:哈希、加盐和慢速算法
\n\n新手最常见的反模式是以明文形式存储密码或使用普通的 MD5。即使您只有“一个学习项目”,这种习惯也会根深蒂固。C# 安全认证始于三条规则:
\n\n- \n
- 切勿以纯文本形式存储密码。即使在本地数据库中也不行。 \n
- 使用盐值 (salt)——为每个用户生成一个随机字符串。 \n
- 选择慢速算法——BCrypt、PBKDF2、Argon2。 \n
为什么是“慢速”?因为黑客需要每秒尝试数十亿种组合。如果哈希过程需要 0.1 秒,攻击在经济上就变得不可行。
\n\n以 BCrypt 为例,在 C# 中正确进行密码哈希
\n\nBCrypt 是 .NET 开发人员的黄金标准。它会自动生成盐值并将其嵌入哈希中。您无需单独存储盐值。
\n\n通过 NuGet 安装包:
\nInstall-Package BCrypt.Net-Next\n\n现在是一个用户注册示例:
\n\nusing BCrypt.Net;\n\npublic class AuthService\n{\n public string HashPassword(string plainPassword)\n {\n // Work factor = 12 — 速度和安全性之间的最佳平衡\n return BCrypt.HashPassword(plainPassword, workFactor: 12);\n }\n\n public bool VerifyPassword(string plainPassword, string hashedPassword)\n {\n return BCrypt.Verify(plainPassword, hashedPassword);\n }\n}\n\n// 使用:\nvar auth = new AuthService();\nstring hash = auth.HashPassword("MyS3cur3P@ss!");\nbool isValid = auth.VerifyPassword("MyS3cur3P@ss!", hash); // true\n\n请注意:workFactor(成本因子)决定了将执行多少次哈希迭代。对于 2024 年来说,12 是一个很好的值。如果您的服务器性能强大,可以提高到 13-14。
PBKDF2 — .NET 内置工具
\n\n如果您不想使用第三方库,请使用 Rfc2898DeriveBytes——这是 .NET 中 PBKDF2 的内置实现。示例:
using System.Security.Cryptography;\n\npublic static string HashWithPBKDF2(string password, byte[] salt, int iterations = 100_000)\n{\n using var deriveBytes = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA256);\n byte[] hash = deriveBytes.GetBytes(32); // 32 字节 = 256 位\n return Convert.ToBase64String(salt) + ":" + Convert.ToBase64String(hash);\n}\n\n// 生成盐值(16 字节)\nbyte[] salt = RandomNumberGenerator.GetBytes(16);\nstring result = HashWithPBKDF2("userPassword", salt);\n\n重要提示:不要使用少于 100,000 次迭代。现代 GPU 每秒可以轻松处理数百万个哈希值。
\n\nJWT — 无会话的现代认证
\n\n当您的 C# 应用程序扩展到微服务或 SPA(React、Vue)时,在服务器上存储会话变得不方便。这时 JSON Web Tokens (JWT) 就派上了用场——紧凑、自包含的访问令牌。
\n\n使用 JWT 的 C# 安全认证 基于三个原则:
\n- \n
- 令牌