1. ASP.NET Core 身份验证与授权深度解析
在构建现代Web应用时,安全始终是首要考虑因素。作为.NET开发者,理解ASP.NET Core的身份验证(Authentication)与授权(Authorization)机制至关重要。这两个概念虽然经常被一起提及,但它们解决的是完全不同层面的安全问题。
身份验证解决的是"你是谁"的问题。想象一下进入公司大楼的场景:保安要求你出示工牌(验证身份),这就是身份验证的过程。在ASP.NET Core中,这个过程可能通过以下方式实现:
- Cookie认证(传统Web应用)
- JWT Bearer令牌(API场景)
- OAuth/OpenID Connect(第三方登录)
而授权解决的是"你能做什么"的问题。即使你通过了保安检查(身份验证),但如果没有研发部门的门禁权限(授权),依然无法进入特定区域。ASP.NET Core提供了多种授权方式:
csharp复制// 基于角色的授权
[Authorize(Roles = "Admin")]
// 基于策略的授权
[Authorize(Policy = "CanEdit")]
实际开发中常见误区是将两者混淆。我曾见过有开发者只在登录时检查一次权限,之后就不再验证,这会导致严重的越权漏洞。正确的做法是:每次请求都要同时进行身份验证和授权检查。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. ASP.NET Core Identity 实战配置
ASP.NET Core Identity是一个功能完备的身份管理框架,它提供了用户管理、角色管理、外部登录等开箱即用的功能。但在实际项目中,如何正确配置Identity往往是第一个挑战。
2.1 基础配置步骤
首先通过NuGet添加必要的包:
bash复制dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
然后在Program.cs中进行配置:
csharp复制services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
这段代码做了三件事:
- 注册了Identity服务,使用默认的IdentityUser和IdentityRole
- 配置Entity Framework Core作为存储后端
- 添加了默认的令牌提供程序(用于密码重置等场景)
2.2 自定义用户和角色
实际项目中,我们通常需要扩展默认的用户类:
csharp复制public class ApplicationUser : IdentityUser
{
public string FullName { get; set; }
public DateTime BirthDate { get; set; }
// 其他自定义属性
}
对应的配置也需要调整:
csharp复制services.AddIdentity<ApplicationUser, IdentityRole>()
// 其余配置保持不变
重要提示:如果项目已经运行后再修改用户类,需要创建并应用新的数据库迁移,这会导致现有用户数据需要迁移处理。
2.3 密码策略配置
安全密码策略是系统安全的基础。Identity提供了丰富的配置选项:
csharp复制services.Configure<IdentityOptions>(options =>
{
// 密码复杂度要求
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
// 账户锁定设置
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
});
3. JWT Bearer认证深度剖析
对于现代API开发,JWT(JSON Web Token)已经成为事实标准。但很多开发者只是简单复制配置,并不真正理解其工作原理。
3.1 JWT结构解析
一个典型的JWT由三部分组成:
- Header:指定令牌类型和签名算法
- Payload:包含声明(claims)
- Signature:用于验证令牌完整性的签名
示例配置:
csharp复制services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "your-issuer",
ValidAudience = "your-audience",
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("your-secret-key-at-least-32-characters"))
};
});
3.2 安全注意事项
- 密钥长度:HS256算法至少需要32字符的密钥
- 令牌有效期:通常设置为15-30分钟
- 敏感数据:不要在JWT中存储敏感信息,因为payload只是Base64编码
- 密钥轮换:定期更换签名密钥
我曾遇到一个案例:开发者将用户权限直接放在JWT中,但忘记在后端实现权限变更时使旧令牌失效,导致权限提升漏洞。
3.3 令牌生成示例
csharp复制public string GenerateJwtToken(ApplicationUser user)
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Id),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.Name, user.UserName),
new Claim("full_name", user.FullName)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
