A:初版
This commit is contained in:
1 parent
237cbd8788
commit
ab3721912d
102 files changed
+7929
-20
No files matched your search
@@ -0,0 +1,219 @@
|
||||
using Sharp.NetServer.Attributes;
|
||||
using Sharp.NetServer.Controllers;
|
||||
using Sharp.NetServer.Models;
|
||||
using Sharp.NetServer.Abstractions;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace NetServer.Test.Examples.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 认证控制器示例
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/auth")]
|
||||
public class AuthController : BaseController
|
||||
{
|
||||
// 模拟用户数据库
|
||||
private static readonly Dictionary<string, string> UserCredentials = new()
|
||||
{
|
||||
{ "admin", "admin123" },
|
||||
{ "user", "user123" }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 用户登录
|
||||
/// POST /api/auth/login
|
||||
/// Body: { "username": "admin", "password": "admin123" }
|
||||
/// </summary>
|
||||
[AllowAnonymous]
|
||||
[RateLimit(10, RateLimitScope.Ip)] // 防止暴力破解
|
||||
[HttpPost("login")]
|
||||
public async Task LoginAsync(HttpContext context)
|
||||
{
|
||||
var loginData = await ReadJsonBodyAsync<Dictionary<string, string>>(context);
|
||||
|
||||
if (loginData == null ||
|
||||
!loginData.TryGetValue("username", out var username) ||
|
||||
!loginData.TryGetValue("password", out var password))
|
||||
{
|
||||
await BadRequestAsync(context, "用户名和密码不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证凭据
|
||||
if (UserCredentials.TryGetValue(username, out var correctPassword) &&
|
||||
correctPassword == password)
|
||||
{
|
||||
// 生成简单的 Token(实际应用中应使用 JWT)
|
||||
var token = GenerateSimpleToken(username);
|
||||
|
||||
// 设置 Cookie
|
||||
SetCookie(context, "auth_token", token, expiresInSeconds: 3600);
|
||||
|
||||
await WriteSuccessResponseAsync(context, new
|
||||
{
|
||||
token,
|
||||
username,
|
||||
role = username == "admin" ? "Admin" : "User",
|
||||
expiresIn = 3600
|
||||
}, "登录成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
await UnauthorizedAsync(context, "用户名或密码错误");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户登出
|
||||
/// POST /api/auth/logout
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[HttpPost("logout")]
|
||||
public async Task LogoutAsync(HttpContext context)
|
||||
{
|
||||
// 删除 Cookie
|
||||
DeleteCookie(context, "auth_token");
|
||||
|
||||
await WriteSuccessResponseAsync(context, new { }, "登出成功");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前用户信息
|
||||
/// GET /api/auth/me
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[HttpGet("me")]
|
||||
public async Task GetCurrentUserAsync(HttpContext context)
|
||||
{
|
||||
var username = context.User?.Identity?.Name ?? "Unknown";
|
||||
var roles = context.User?.Claims
|
||||
.Where(c => c.Type == ClaimTypes.Role)
|
||||
.Select(c => c.Value)
|
||||
.ToList() ?? new List<string>();
|
||||
|
||||
await WriteSuccessResponseAsync(context, new
|
||||
{
|
||||
username,
|
||||
roles,
|
||||
isAuthenticated = context.User?.Identity?.IsAuthenticated ?? false
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改密码
|
||||
/// POST /api/auth/change-password
|
||||
/// Body: { "oldPassword": "admin123", "newPassword": "newpass123" }
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[RateLimit(5, RateLimitScope.User)]
|
||||
[HttpPost("change-password")]
|
||||
public async Task ChangePasswordAsync(HttpContext context)
|
||||
{
|
||||
var username = context.User?.Identity?.Name;
|
||||
if (string.IsNullOrEmpty(username))
|
||||
{
|
||||
await UnauthorizedAsync(context);
|
||||
return;
|
||||
}
|
||||
|
||||
var passwordData = await ReadJsonBodyAsync<Dictionary<string, string>>(context);
|
||||
if (passwordData == null ||
|
||||
!passwordData.TryGetValue("oldPassword", out var oldPassword) ||
|
||||
!passwordData.TryGetValue("newPassword", out var newPassword))
|
||||
{
|
||||
await BadRequestAsync(context, "旧密码和新密码不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证旧密码
|
||||
if (!UserCredentials.TryGetValue(username, out var currentPassword) ||
|
||||
currentPassword != oldPassword)
|
||||
{
|
||||
await BadRequestAsync(context, "旧密码错误");
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新密码
|
||||
UserCredentials[username] = newPassword;
|
||||
|
||||
await WriteSuccessResponseAsync(context, new { }, "密码修改成功");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新 Token
|
||||
/// POST /api/auth/refresh
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[HttpPost("refresh")]
|
||||
public async Task RefreshTokenAsync(HttpContext context)
|
||||
{
|
||||
var username = context.User?.Identity?.Name;
|
||||
if (string.IsNullOrEmpty(username))
|
||||
{
|
||||
await UnauthorizedAsync(context);
|
||||
return;
|
||||
}
|
||||
|
||||
var newToken = GenerateSimpleToken(username);
|
||||
SetCookie(context, "auth_token", newToken, expiresInSeconds: 3600);
|
||||
|
||||
await WriteSuccessResponseAsync(context, new
|
||||
{
|
||||
token = newToken,
|
||||
expiresIn = 3600
|
||||
}, "Token 刷新成功");
|
||||
}
|
||||
|
||||
private static string GenerateSimpleToken(string username)
|
||||
{
|
||||
// 简单的 Token 生成(实际应用中应使用 JWT)
|
||||
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
var role = username == "admin" ? "Admin" : "User";
|
||||
return Convert.ToBase64String(
|
||||
System.Text.Encoding.UTF8.GetBytes($"{username}:{role}:{timestamp}")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 简单的认证提供者实现
|
||||
/// </summary>
|
||||
public class SimpleAuthenticationProvider : IAuthenticationProvider
|
||||
{
|
||||
public Task<ClaimsPrincipal?> AuthenticateAsync(string? token)
|
||||
{
|
||||
if (string.IsNullOrEmpty(token))
|
||||
return Task.FromResult<ClaimsPrincipal?>(null);
|
||||
|
||||
try
|
||||
{
|
||||
// 解析简单的 Token
|
||||
var decoded = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(token));
|
||||
var parts = decoded.Split(':');
|
||||
|
||||
if (parts.Length >= 2)
|
||||
{
|
||||
var username = parts[0];
|
||||
var role = parts[1];
|
||||
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim(ClaimTypes.Name, username),
|
||||
new Claim(ClaimTypes.Role, role)
|
||||
};
|
||||
|
||||
var identity = new ClaimsIdentity(claims, "SimpleAuth");
|
||||
var principal = new ClaimsPrincipal(identity);
|
||||
|
||||
return Task.FromResult<ClaimsPrincipal?>(principal);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Token 解析失败
|
||||
}
|
||||
|
||||
return Task.FromResult<ClaimsPrincipal?>(null);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user