You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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端:
    1. 用AspNetCore Identity的UserManager验证用户名和密码的合法性
    2. 验证通过后,生成JWT令牌(包含用户ID、角色等非敏感信息)
    3. 将JWT返回给MAUI
  • 后续请求: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的SecureStorage API),不要存在明文本地文件或普通存储中
  • JWT配置规范:
    • 设置合理的过期时间(比如15-30分钟)
    • 用强密钥签名(避免硬编码,从配置文件读取)
    • 不要在JWT的Payload中存放敏感信息(Payload是Base64编码,可被解码)
  • API接口防护:用[Authorize]属性标记需要授权的接口,未携带有效令牌的请求直接拒绝
  • 基础防暴力破解:给登录接口加速率限制,避免恶意用户反复尝试密码;登录时可加入验证码验证

快速集成AspNetCore Identity到Web API的步骤

  1. 安装NuGet包:Microsoft.AspNetCore.Identity.EntityFrameworkCore、Microsoft.AspNetCore.Authentication.JwtBearer
  2. 定义自定义用户类(可扩展字段):
public class ApplicationUser : IdentityUser
{
    // 可添加自定义字段,比如客户昵称、所属机构ID等
    public string? NickName { get; set; }
}
  1. 创建继承自IdentityDbContext的数据库上下文:
public class AppDbContext : IdentityDbContext<ApplicationUser>
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
}
  1. 在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();
  1. 编写登录接口:
[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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:44:55