修改接口

This commit is contained in:
2025-10-16 15:21:52 +08:00
parent 82220ce0b8
commit dd398c1c32
274 changed files with 22777 additions and 22905 deletions

View File

@@ -1,97 +0,0 @@
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using FutureMailAPI.Models;
namespace FutureMailAPI.Helpers
{
public interface IJwtHelper
{
string GenerateToken(User user);
string GenerateToken(int userId, string username, string email);
ClaimsPrincipal? ValidateToken(string token);
}
public class JwtHelper : IJwtHelper
{
private readonly IConfiguration _configuration;
public JwtHelper(IConfiguration configuration)
{
_configuration = configuration;
}
public string GenerateToken(User user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Key"]!);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Username),
new Claim(ClaimTypes.Email, user.Email)
}),
Expires = DateTime.UtcNow.AddDays(7),
Issuer = _configuration["Jwt:Issuer"],
Audience = _configuration["Jwt:Audience"],
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
public string GenerateToken(int userId, string username, string email)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Key"]!);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.NameIdentifier, userId.ToString()),
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.Email, email)
}),
Expires = DateTime.UtcNow.AddDays(7),
Issuer = _configuration["Jwt:Issuer"],
Audience = _configuration["Jwt:Audience"],
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
public ClaimsPrincipal? ValidateToken(string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Key"]!);
var validationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = true,
ValidIssuer = _configuration["Jwt:Issuer"],
ValidateAudience = true,
ValidAudience = _configuration["Jwt:Audience"],
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
return principal;
}
catch
{
return null;
}
}
}
}

View File

@@ -7,6 +7,7 @@ namespace FutureMailAPI.Helpers
{
string HashPassword(string password);
bool VerifyPassword(string password, string hash);
bool VerifyPassword(string password, string hash, string salt);
string HashPassword(string password, string salt);
string GenerateSalt();
}
@@ -59,23 +60,55 @@ namespace FutureMailAPI.Helpers
{
try
{
// 从存储的哈希中提取盐值
// 检查哈希长度判断是完整哈希36字节还是纯哈希20字节
byte[] hashBytes = Convert.FromBase64String(hash);
byte[] salt = new byte[16];
Array.Copy(hashBytes, 0, salt, 0, 16);
// 使用相同的盐值计算密码的哈希
var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000);
byte[] computedHash = pbkdf2.GetBytes(20);
// 比较两个哈希值
for (int i = 0; i < 20; i++)
if (hashBytes.Length == 36)
{
if (hashBytes[i + 16] != computedHash[i])
return false;
// 完整哈希格式:盐值(16字节) + 哈希值(20字节)
byte[] salt = new byte[16];
Array.Copy(hashBytes, 0, salt, 0, 16);
// 使用相同的盐值计算密码的哈希
var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000);
byte[] computedHash = pbkdf2.GetBytes(20);
// 比较两个哈希值
for (int i = 0; i < 20; i++)
{
if (hashBytes[i + 16] != computedHash[i])
return false;
}
return true;
}
return true;
else if (hashBytes.Length == 20)
{
// 纯哈希格式:只有哈希值(20字节)
// 这种情况下,我们需要从数据库中获取盐值
// 但由于VerifyPassword方法没有盐值参数我们无法验证这种格式
// 返回false表示验证失败
return false;
}
else
{
// 未知的哈希格式
return false;
}
}
catch
{
return false;
}
}
public bool VerifyPassword(string password, string hash, string salt)
{
try
{
// 使用提供的盐值计算密码的哈希
var computedHash = HashPassword(password, salt);
return hash == computedHash;
}
catch
{