C# WebAPI Token 生成与账号密码登录实现
此为一个简单的且完整的 C# WebAPI 实现,用于基于账号密码的 Token 生成和验证系统。这个实现使用 JWT (JSON Web Token) 作为认证机制。
1. 创建项目
首先创建一个 ASP.NET Core WebAPI 项目。
2. 安装必要 NuGet 包
Microsoft.AspNetCore.Authentication.JwtBearer
System.IdentityModel.Tokens.Jwt
Microsoft.EntityFrameworkCore (如果使用数据库)
Microsoft.EntityFrameworkCore.SqlServer (如果使用SQL Server)3. 完整实现代码
3.1 配置类 (appsettings.json)
{
"Jwt": {
"Key": "YourSuperSecretKeyHereAtLeast32CharactersLong",
"Issuer": "YourAppIssuer",
"Audience": "YourAppAudience",
"ExpireMinutes": 60
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}3.2 用户模型 (Models/User.cs)
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; } // 实际应用中应该存储哈希值
public string Role { get; set; } // 例如 "Admin", "User" 等
}3.3 Token 响应模型 (Models/TokenResponse.cs)
public class TokenResponse
{
public string Token { get; set; }
public DateTime Expiration { get; set; }
public string Username { get; set; }
public string Role { get; set; }
}3.4 登录请求模型 (Models/LoginRequest.cs)
public class LoginRequest
{
public string Username { get; set; }
public string Password { get; set; }
}3.5 JWT 服务 (Services/JwtService.cs)
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
public class JwtService
{
private readonly IConfiguration _configuration;
public JwtService(IConfiguration configuration)
{
_configuration = configuration;
}
public string GenerateToken(User user)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Username),
new Claim(ClaimTypes.Role, user.Role)
};
var token = new JwtSecurityToken(
_configuration["Jwt:Issuer"],
_configuration["Jwt:Audience"],
claims,
expires: DateTime.Now.AddMinutes(Convert.ToDouble(_configuration["Jwt:ExpireMinutes"])),
signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}3.6 用户服务 (Services/UserService.cs)
public class UserService
{
// 实际应用中应该从数据库获取用户
private readonly List<User> _users = new List<User>
{
new User { Id = 1, Username = "admin", Password = "admin123", Role = "Admin" },
new User { Id = 2, Username = "user", Password = "user123", Role = "User" }
};
public User Authenticate(string username, string password)
{
// 实际应用中应该验证密码哈希
var user = _users.SingleOrDefault(x => x.Username == username && x.Password == password);
// 如果用户不存在或密码错误返回null
if (user == null)
return null;
// 认证成功返回用户详情 (不包含密码)
return user;
}
}3.7 认证控制器 (Controllers/AuthController.cs)
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly UserService _userService;
private readonly JwtService _jwtService;
public AuthController(UserService userService, JwtService jwtService)
{
_userService = userService;
_jwtService = jwtService;
}
[HttpPost("login")]
public IActionResult Login([FromBody] LoginRequest request)
{
var user = _userService.Authenticate(request.Username, request.Password);
if (user == null)
return Unauthorized(new { message = "用户名或密码错误" });
var token = _jwtService.GenerateToken(user);
return Ok(new TokenResponse
{
Token = token,
Expiration = DateTime.Now.AddMinutes(Convert.ToDouble(_configuration["Jwt:ExpireMinutes"])),
Username = user.Username,
Role = user.Role
});
}
}3.8 受保护资源控制器 (Controllers/ProtectedController.cs)
using Microsoft.AspNetCore.Authorization;
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class ProtectedController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
// 可以从HttpContext.User获取用户信息
var username = User.Identity.Name;
var role = User.FindFirst(ClaimTypes.Role)?.Value;
return Ok(new {
Message = $"你好 {username}, 你的角色是 {role}",
Data = "这是受保护的数据"
});
}
[Authorize(Roles = "Admin")]
[HttpGet("admin")]
public IActionResult AdminOnly()
{
return Ok(new { Message = "只有管理员能看到这条消息" });
}
}3.9 Program.cs 配置
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// 添加服务到容器
builder.Services.AddControllers();
// 配置JWT认证
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
};
});
// 注册自定义服务
builder.Services.AddScoped<UserService>();
builder.Services.AddScoped<JwtService>();
var app = builder.Build();
// 配置HTTP请求管道
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
// 添加认证和授权中间件
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();4. 使用说明
4.1 获取Token
发送POST请求到 /api/auth/login,请求体为:
{
"username": "admin",
"password": "admin123"
}成功响应示例:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiration": "2023-05-01T12:00:00",
"username": "admin",
"role": "Admin"
}4.2 访问受保护资源
在请求头中添加:
Authorization: Bearer <your_token>然后访问 /api/protected
4.3 访问管理员资源
在请求头中添加:
Authorization: Bearer <your_token>然后访问 /api/protected/admin (需要管理员角色)
5. 安全建议
- 密码存储:实际应用中不要明文存储密码,应该使用密码哈希加盐
- HTTPS:确保所有认证请求都通过HTTPS
- Token过期:设置合理的Token过期时间
- 密钥保护:保护JWT密钥,不要硬编码在代码中
- 刷新Token:考虑实现刷新Token机制
6. 扩展功能
- 添加用户注册功能
- 实现密码重置
- 添加多因素认证
- 实现Token刷新机制
- 添加日志记录和监控