feat: strengthen P0 security and operations

This commit is contained in:
2026-08-01 11:20:02 +08:00
parent f776056834
commit 84c2b0b21d
77 changed files with 24185 additions and 355 deletions

View File

@@ -171,6 +171,79 @@ public sealed class BrowserAuthController(
return NoContent();
}
[AllowAnonymous]
[EnableRateLimiting(AuthRateLimitPolicies.Sms)]
[HttpPost("password/reset/sms/send")]
[EndpointSummary("发送浏览器密码重置短信验证码")]
public async Task<ActionResult<SmsSendResult>> SendPasswordResetCode(
PasswordResetSmsSendDto request,
CancellationToken cancellationToken)
{
EnsureTrustedOrigin();
var tenantId = await ResolveTenantIdAsync(AuthRealm.Tenant, request.TenantCode, cancellationToken)
?? throw new RequiredFieldException("tenantCode is required for password reset.");
var result = await authService.RequestPasswordResetAsync(
new PasswordResetCodeRequest(
tenantId,
request.Phone,
HttpContext.Connection.RemoteIpAddress?.ToString(),
Request.Headers.UserAgent.ToString(),
request.DeviceId),
cancellationToken);
return Accepted(result);
}
[AllowAnonymous]
[EnableRateLimiting(AuthRateLimitPolicies.Password)]
[HttpPost("password/reset")]
[EndpointSummary("使用短信验证码重置浏览器账号密码")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<IActionResult> ResetPassword(
PasswordResetDto request,
CancellationToken cancellationToken)
{
EnsureTrustedOrigin();
var tenantId = await ResolveTenantIdAsync(AuthRealm.Tenant, request.TenantCode, cancellationToken)
?? throw new RequiredFieldException("tenantCode is required for password reset.");
await authService.ResetPasswordAsync(
new PasswordResetRequest(
tenantId,
request.Phone,
request.Code,
request.NewPassword,
HttpContext.Connection.RemoteIpAddress?.ToString(),
Request.Headers.UserAgent.ToString()),
cancellationToken);
ClearCookies();
return NoContent();
}
[Authorize]
[EnableRateLimiting(AuthRateLimitPolicies.Password)]
[HttpPost("password/change")]
[EndpointSummary("浏览器已登录用户修改密码")]
public async Task<ActionResult<object>> ChangePassword(
AuthenticatedPasswordChangeDto request,
CancellationToken cancellationToken)
{
EnsureTrustedOrigin();
if (currentUser.UserId is not { } userId || currentUser.SessionId is not { } sessionId)
{
return Unauthorized();
}
var result = await authService.ChangePasswordAsync(
new AuthenticatedPasswordChangeRequest(
userId,
sessionId,
request.CurrentPassword,
request.NewPassword,
HttpContext.Connection.RemoteIpAddress?.ToString(),
Request.Headers.UserAgent.ToString()),
cancellationToken);
return Ok(WriteResult(result));
}
private object WriteResult(AuthenticationResult result)
{
if (result.User?.Tokens is { } tokens)