服务器部署测试~~~
This commit is contained in:
207
UserService/UserService.cs
Normal file
207
UserService/UserService.cs
Normal file
@@ -0,0 +1,207 @@
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using SimpleTodoApiWithPg.Data;
|
||||
using SimpleTodoApiWithPg.Models;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace SimpleTodoApiWithPg.UserService
|
||||
{
|
||||
// Services/UserService.cs
|
||||
public class UserServices
|
||||
{
|
||||
private readonly AppDbContext _dbContext;
|
||||
private readonly ILogger<UserServices> _logger; // 在服务构造函数中注入
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public UserServices(AppDbContext dbContext, IConfiguration configuration, ILogger<UserServices> logger)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_logger = logger;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
|
||||
//前更新用户接口,暂时未使用
|
||||
public async Task<Results<Ok<User>, BadRequest<string>>> PatchUserAsync(User user)
|
||||
{
|
||||
_logger.LogInformation("Attempting to patch user in UserService: {Username}", user.Username);
|
||||
|
||||
var existingUser = await _dbContext.Users.FirstOrDefaultAsync(u => u.Username == user.Username);
|
||||
if (existingUser == null)
|
||||
{
|
||||
_logger.LogWarning("User '{Username}' not found during patch.", user.Username);
|
||||
return TypedResults.BadRequest("用户名不存在,登录失败!。");
|
||||
}
|
||||
|
||||
if (!BCrypt.Net.BCrypt.Verify(user.PasswordHash, existingUser.PasswordHash, true))
|
||||
{
|
||||
_logger.LogWarning("Incorrect password for user '{Username}' during patch.", user.Username);
|
||||
return TypedResults.BadRequest("密码错误,请重新输入。");
|
||||
}
|
||||
|
||||
// 假设这里执行更新逻辑
|
||||
// existingUser.SomeProperty = user.SomeProperty;
|
||||
// await _dbContext.SaveChangesAsync();
|
||||
|
||||
_logger.LogInformation("User '{Username}' patched successfully.", user.Username);
|
||||
return TypedResults.Ok(existingUser);
|
||||
}
|
||||
|
||||
//获取所有用户接口
|
||||
public async Task<Results<Ok<List<User>>, BadRequest<string>>> GetUsersAsync()
|
||||
{
|
||||
var users = await _dbContext.Users.ToListAsync();
|
||||
return TypedResults.Ok(users);
|
||||
}
|
||||
|
||||
//根据id获取对应用户接口
|
||||
public async Task<Results<Ok<User>, NotFound<string>>> GetoneUserAsync(Guid id)
|
||||
{
|
||||
var user = await _dbContext.Users.FindAsync(id);
|
||||
if (user == null) { return TypedResults.NotFound($"要查询的id:{id}不存在"); }
|
||||
return TypedResults.Ok(user);
|
||||
}
|
||||
|
||||
//用户注册接口
|
||||
public async Task<ApiResponse<RegisterResponse>> RegisterAsync(RegisterRequest request)
|
||||
{
|
||||
var exuser = await _dbContext.Users.AnyAsync(u => u.Username == request.Username);
|
||||
if (exuser) { return ApiResponse.Fail<RegisterResponse>($"用户名:{request.Username}已存在,注册失败!", 400); };
|
||||
//if (request.Username.Length <5 || request.Email.Length < 5 ) { return ApiResponse.Fail<RegisterResponse>($"用户名或邮箱不符合规范,注册失败!", 400);};
|
||||
|
||||
var password = RandomNumberGenerator.GetString("0123456789",15);
|
||||
var user = new User();
|
||||
user.Username = request.Username;
|
||||
user.Email = request.Email;
|
||||
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(password, 10, true);
|
||||
_dbContext.Users.Add(user);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return ApiResponse.Ok<RegisterResponse>(new RegisterResponse
|
||||
{
|
||||
Username = user.Username,
|
||||
Email = user.Email,
|
||||
Password = password,
|
||||
UserId = user.Id
|
||||
});
|
||||
}
|
||||
|
||||
//更新用户接口
|
||||
public async Task<Results<Ok<User>, NotFound<string>>> UpdateUserAsync(int id, UpdateUserRequest updateUser)
|
||||
{
|
||||
var existingUser = await _dbContext.Users.FindAsync(id);
|
||||
if (existingUser == null) { return TypedResults.NotFound($"要更新的用户id:{id}不存在!"); };
|
||||
|
||||
if (updateUser.Username != null)
|
||||
{
|
||||
existingUser.Username = updateUser.Username;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(updateUser.NewPassword))
|
||||
{
|
||||
existingUser.PasswordHash = BCrypt.Net.BCrypt.HashPassword(updateUser.NewPassword,10,true);
|
||||
}
|
||||
if (updateUser.Email != null)
|
||||
{
|
||||
existingUser.Email = updateUser.Email;
|
||||
}
|
||||
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
return TypedResults.Ok(existingUser);
|
||||
}
|
||||
|
||||
//删除指定用户接口
|
||||
public async Task<Results<Ok<string>, NotFound<string>>> DeleteUserAsync(Guid id)
|
||||
{
|
||||
var existingUser = await _dbContext.Users.FindAsync(id);
|
||||
if (existingUser == null)
|
||||
{
|
||||
return TypedResults.NotFound($"指定要删除的用户:{id}不存在!");
|
||||
}
|
||||
_dbContext.Users.Remove(existingUser);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return TypedResults.Ok($"指定的用户:{existingUser.Username}删除成功!");
|
||||
}
|
||||
|
||||
//登录认证接口
|
||||
public async Task<ApiResponse<AuthResponse>> LoginAuthAsync(LoginRequest loginRequest)
|
||||
{
|
||||
var existingUser = await _dbContext.Users.FirstOrDefaultAsync(u => u.Username == loginRequest.Username);
|
||||
if (existingUser == null || !BCrypt.Net.BCrypt.Verify(loginRequest.Password, existingUser.PasswordHash, true))
|
||||
{
|
||||
_logger.LogError("用户登录失败!{request}"," ---用户名: "+loginRequest.Username+" ---密码: "+loginRequest.Password);
|
||||
return ApiResponse.Fail<AuthResponse>("用户名或密码错误!",400);
|
||||
}
|
||||
// 1. 生成 JWT (Access Token)
|
||||
var accessTokenExpiration = DateTime.UtcNow.AddMinutes(1); // 访问令牌有效期15分钟
|
||||
var accessToken = GenerateJwtToken(existingUser, accessTokenExpiration);
|
||||
|
||||
// 2. 生成刷新令牌
|
||||
var refreshToken = GenerateRefreshToken();
|
||||
refreshToken.UserId = existingUser.Id;
|
||||
await _dbContext.RefreshTokens.AddAsync(refreshToken);
|
||||
|
||||
// (可选但推荐) 清理该用户旧的、无效的刷新令牌
|
||||
var oldRefreshTokens = await _dbContext.RefreshTokens
|
||||
.Where(rt => rt.UserId == existingUser.Id && (rt.Revoked != null || rt.Expires <= DateTime.UtcNow))
|
||||
.ToListAsync();
|
||||
_dbContext.RefreshTokens.RemoveRange(oldRefreshTokens);
|
||||
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
// 3. 返回令牌对
|
||||
return ApiResponse.Ok(new AuthResponse
|
||||
{
|
||||
AccessToken = accessToken,
|
||||
RefreshToken = refreshToken.Token,
|
||||
AccessTokenExpiration = accessTokenExpiration
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//创建令牌接口
|
||||
public string GenerateJwtToken(User user, DateTime expires)
|
||||
{
|
||||
// 加载证书以获取私钥进行签名
|
||||
var certPath = _configuration["Jwt:CertificatePath"]!;
|
||||
var certPassword = _configuration["Jwt:CertificatePassword"]!;
|
||||
var certificate = X509CertificateLoader.LoadPkcs12FromFile(certPath, certPassword,X509KeyStorageFlags.EphemeralKeySet);
|
||||
|
||||
var claims = new[]
|
||||
{
|
||||
new Claim(JwtRegisteredClaimNames.Sub, user.Username),
|
||||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
||||
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())
|
||||
};
|
||||
|
||||
var token = new JwtSecurityToken(
|
||||
issuer: _configuration["Jwt:Issuer"],
|
||||
audience: _configuration["Jwt:Audience"],
|
||||
claims: claims,
|
||||
expires: expires,
|
||||
// 使用证书的私钥通过 ECDSA-SHA256 算法进行签名
|
||||
signingCredentials: new SigningCredentials(new ECDsaSecurityKey(certificate.GetECDsaPrivateKey()!), SecurityAlgorithms.EcdsaSha256)
|
||||
);
|
||||
|
||||
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||
}
|
||||
|
||||
//创建刷新令牌接口
|
||||
public RefreshToken GenerateRefreshToken()
|
||||
{
|
||||
var randomNumber = new byte[64];
|
||||
using var rng = RandomNumberGenerator.Create();
|
||||
rng.GetBytes(randomNumber);
|
||||
|
||||
return new RefreshToken
|
||||
{
|
||||
Token = Convert.ToBase64String(randomNumber),
|
||||
Expires = DateTime.UtcNow.AddDays(1), // 刷新令牌有效期7天
|
||||
Created = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user