.NET应用(尤其MAUI)必须用Identity做认证吗?还是仅为最佳实践?
.NET MAUI + Web API 认证授权方案梳理
先明确几个核心疑问
1. AspNetCore Identity 是什么?和Microsoft Entra的关系?
AspNetCore Identity是.NET官方提供的认证授权基础框架,帮你快速实现用户注册、登录、密码管理、角色权限等核心功能,默认支持对接SQL Server等数据库存储用户数据。
Microsoft Entra(原Azure AD)是微软的云身份服务,属于可选的扩展方案——文档提及它是给你提供「托管式身份管理」的选项,不是强制要求。如果你想自己维护用户数据库(存在私有SQL里),完全可以只用AspNetCore Identity,不需要依赖Entra。
2. 你的场景(MAUI + Web API)的完整登录流程
因为MAUI不能直接操作数据库,所有认证逻辑必须由Web API承接,流程如下:
- MAUI端:展示登录界面,收集用户名/密码,通过HTTPS请求发送给Web API的登录接口
- Web API端:
- 用AspNetCore Identity的
UserManager验证用户名和密码的合法性 - 验证通过后,生成JWT令牌(包含用户ID、角色等非敏感信息)
- 将JWT返回给MAUI
- 用AspNetCore Identity的
- 后续请求:MAUI将JWT放在HTTP请求头的
Authorization: Bearer {token}字段中,Web API验证令牌有效性后,再处理业务请求
密码安全的核心保障
AspNetCore Identity默认会自动处理密码的安全存储:
- 不会存储明文密码,而是用PBKDF2+HMAC-SHA256算法对密码进行哈希,同时自动生成随机盐值
- 你只需要调用框架提供的
UserManager.CreateAsync创建用户,UserManager.CheckPasswordAsync验证密码,完全不用自己写加密逻辑,避免手动实现带来的安全漏洞
防止恶意绕过的关键措施
- 绝对不在MAUI端做认证逻辑:所有用户身份验证、权限判断必须在Web API端执行,MAUI只负责UI展示和数据传递
- 强制HTTPS通信:MAUI和Web API的所有请求必须走HTTPS,防止密码、令牌被窃听或篡改
- 安全存储令牌:MAUI端将JWT存入平台安全存储(用MAUI的
SecureStorageAPI),不要存在明文本地文件或普通存储中 - JWT配置规范:
- 设置合理的过期时间(比如15-30分钟)
- 用强密钥签名(避免硬编码,从配置文件读取)
- 不要在JWT的Payload中存放敏感信息(Payload是Base64编码,可被解码)
- API接口防护:用
[Authorize]属性标记需要授权的接口,未携带有效令牌的请求直接拒绝 - 基础防暴力破解:给登录接口加速率限制,避免恶意用户反复尝试密码;登录时可加入验证码验证
快速集成AspNetCore Identity到Web API的步骤
- 安装NuGet包:
Microsoft.AspNetCore.Identity.EntityFrameworkCore、Microsoft.AspNetCore.Authentication.JwtBearer - 定义自定义用户类(可扩展字段):
public class ApplicationUser : IdentityUser { // 可添加自定义字段,比如客户昵称、所属机构ID等 public string? NickName { get; set; } }
- 创建继承自
IdentityDbContext的数据库上下文:
public class AppDbContext : IdentityDbContext<ApplicationUser> { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } }
- 在Program.cs中配置Identity和JWT认证:
// 配置Identity builder.Services.AddIdentityCore<ApplicationUser>(options => { // 可配置密码规则,比如长度、复杂度要求 options.Password.RequireDigit = true; options.Password.RequireLowercase = true; }) .AddEntityFrameworkStores<AppDbContext>(); // 配置JWT认证 builder.Services.AddAuthentication(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"])) }; }); // 启用认证和授权中间件 app.UseAuthentication(); app.UseAuthorization();
- 编写登录接口:
[ApiController] [Route("api/auth")] public class AuthController : ControllerBase { private readonly UserManager<ApplicationUser> _userManager; private readonly IConfiguration _configuration; public AuthController(UserManager<ApplicationUser> userManager, IConfiguration configuration) { _userManager = userManager; _configuration = configuration; } [HttpPost("login")] public async Task<IActionResult> Login([FromBody] LoginRequest request) { var user = await _userManager.FindByNameAsync(request.UserName); if (user == null || !await _userManager.CheckPasswordAsync(user, request.Password)) { return Unauthorized("用户名或密码错误"); } // 生成JWT令牌 var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, user.Id), new Claim(ClaimTypes.Name, user.UserName) }), Expires = DateTime.UtcNow.AddMinutes(30), Issuer = _configuration["Jwt:Issuer"], Audience = _configuration["Jwt:Audience"], SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; var token = tokenHandler.CreateToken(tokenDescriptor); return Ok(new { Token = tokenHandler.WriteToken(token) }); } } public class LoginRequest { public string UserName { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; }
总结最佳实践
- 始终遵循「认证逻辑全在服务端」的原则,移动端只做UI和数据传递
- 依赖AspNetCore Identity的内置安全能力,不要自己实现密码加密、用户管理等逻辑
- 所有通信强制HTTPS,令牌存储在安全区域
- 用JWT实现无状态认证,搭配Refresh Token机制优化长期登录体验(可选)
- 基础防护不可少:速率限制、验证码、接口授权校验
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

