在 .NET Core 中,基于声明的身份验证(Claims-based Authentication) 是一种将用户身份信息抽象为一系列可验证的声明(Claims)的认证模型。与传统基于角色的身份验证相比,它提供了更细粒度的权限控制和灵活性。
1. 基于声明的身份验证(Claims-based Authentication)
核心概念
- 声明(Claim):一个键值对,描述用户的某个属性(如
Email = "user@example.com"或Role = "Admin")。 - 身份(Identity):由一组声明构成,代表一个用户的身份(如
ClaimsIdentity)。 - 主体(Principal):包含一个或多个身份的对象(如
ClaimsPrincipal),表示当前请求的上下文用户。
工作流程
- 用户登录时,系统验证凭证(如用户名密码)。
- 验证成功后,生成一组声明(如用户ID、角色、邮箱等)。
- 声明被封装到
ClaimsPrincipal中,附加到当前请求的HttpContext.User。 - 后续请求通过检查声明来授权访问。
示例代码:创建声明
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, "Alice"),
new Claim(ClaimTypes.Email, "alice@example.com"),
new Claim("Department", "HR")
};
var identity = new ClaimsIdentity(claims, "CustomAuth");
var principal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync("CookieAuthScheme", principal);
2. 存储用户信息的方式
在 .NET Core 中,用户信息通常通过以下方式存储:
方式 1:使用 ASP.NET Core Identity
ASP.NET Core Identity 是官方提供的用户管理系统,内置用户信息存储、密码哈希、角色管理等功能。
步骤
- 安装 NuGet 包:
Install-Package Microsoft.AspNetCore.Identity.EntityFrameworkCore
- 定义用户模型(可扩展):
public class ApplicationUser : IdentityUser
{
public string CustomProperty { get; set; }
}
- 配置数据库上下文:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options) { }
}
- 注册 Identity 服务(在
Startup.cs):
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
- 迁移数据库:
dotnet ef migrations add InitialCreate
dotnet ef database update
方式 2:自定义存储
如果不想使用 Identity,可以直接操作声明或使用其他存储方式(如数据库、外部 API)。
示例:手动存储声明到 Cookie
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, "Bob"),
new Claim("UserAge", "30")
};
var claimsIdentity = new ClaimsIdentity(claims, "CustomAuthType");
var authProperties = new AuthenticationProperties
{
IsPersistent = true // 持久化 Cookie
};
await HttpContext.SignInAsync(
"CustomScheme",
new ClaimsPrincipal(claimsIdentity),
authProperties
);
示例:从数据库加载用户信息
public async Task<ClaimsPrincipal> CreatePrincipalAsync(string username)
{
var user = await _userRepository.FindByUsernameAsync(username);
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Username),
new Claim(ClaimTypes.Email, user.Email)
};
return new ClaimsPrincipal(new ClaimsIdentity(claims, "CustomAuth"));
}
方式 3:使用 JWT(用于 API)
在 Web API 中,用户信息可通过 JWT(JSON Web Token)存储并在请求头中传递。
- 生成 JWT:
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-secret-key"));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, "user1"),
new Claim(JwtRegisteredClaimNames.Email, "user1@example.com")
};
var token = new JwtSecurityToken(
issuer: "your-issuer",
audience: "your-audience",
claims: claims,
expires: DateTime.Now.AddHours(1),
signingCredentials: credentials
);
var jwt = new JwtSecurityTokenHandler().WriteToken(token);
- 验证 JWT(在
Startup.cs):
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = "your-issuer",
ValidAudience = "your-audience",
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("your-secret-key"))
};
});
3. 关键注意事项
- 敏感数据:避免在声明中存储密码等敏感信息。
- 加密:使用 HTTPS 保护 Cookie 或 JWT。
- 声明大小:Cookie 有大小限制(通常 4096 字节),JWT 适合存储精简信息。
通过合理选择存储方式,可以灵活管理用户信息并实现安全的身份验证。
1201

被折叠的 条评论
为什么被折叠?



