首页
学习
活动
专区
圈层
工具
发布

.Net Core2.0Web API使用Identity / JWT并让用户管理器与DI协同工作

.NET Core 2.0 Web API 使用 Identity 和 JWT 认证集成指南

基础概念

ASP.NET Core Identity

ASP.NET Core Identity 是一个成员资格系统,用于处理用户认证和授权。它提供了用户管理功能,包括注册、登录、密码重置等。

JWT (JSON Web Token)

JWT 是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为JSON对象。它通常用于身份验证和信息交换。

实现步骤

1. 安装必要 NuGet 包

代码语言:txt
复制
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package System.IdentityModel.Tokens.Jwt

2. 配置 Identity 和 JWT

Startup.cs 中配置:

代码语言:txt
复制
public void ConfigureServices(IServiceCollection services)
{
    // 添加DbContext
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    // 添加Identity
    services.AddIdentity<IdentityUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    // 配置JWT认证
    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 = Configuration["Jwt:Issuer"],
            ValidAudience = Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
        };
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_0);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // 其他中间件...

    app.UseAuthentication();
    app.UseMvc();
}

3. 创建 AccountController

代码语言:txt
复制
[Route("api/[controller]")]
[ApiController]
public class AccountController : ControllerBase
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly SignInManager<IdentityUser> _signInManager;
    private readonly IConfiguration _configuration;

    public AccountController(
        UserManager<IdentityUser> userManager,
        SignInManager<IdentityUser> signInManager,
        IConfiguration configuration)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _configuration = configuration;
    }

    [HttpPost("register")]
    public async Task<IActionResult> Register([FromBody] RegisterModel model)
    {
        var user = new IdentityUser { UserName = model.Email, Email = model.Email };
        var result = await _userManager.CreateAsync(user, model.Password);

        if (result.Succeeded)
        {
            return Ok(new { Message = "User created successfully" });
        }

        return BadRequest(result.Errors);
    }

    [HttpPost("login")]
    public async Task<IActionResult> Login([FromBody] LoginModel model)
    {
        var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, false, false);

        if (result.Succeeded)
        {
            var user = await _userManager.FindByEmailAsync(model.Email);
            var token = GenerateJwtToken(user);
            return Ok(new { Token = token });
        }

        return Unauthorized();
    }

    private string GenerateJwtToken(IdentityUser user)
    {
        var claims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Sub, user.Email),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim(ClaimTypes.NameIdentifier, user.Id)
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var expires = DateTime.Now.AddDays(Convert.ToDouble(_configuration["Jwt:ExpireDays"]));

        var token = new JwtSecurityToken(
            _configuration["Jwt:Issuer"],
            _configuration["Jwt:Audience"],
            claims,
            expires: expires,
            signingCredentials: creds
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}

public class RegisterModel
{
    [Required]
    [EmailAddress]
    public string Email { get; set; }

    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }
}

public class LoginModel
{
    [Required]
    [EmailAddress]
    public string Email { get; set; }

    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }
}

4. 保护 API 端点

使用 [Authorize] 属性保护需要认证的端点:

代码语言:txt
复制
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

常见问题及解决方案

1. UserManager 无法通过 DI 注入

原因: 可能没有正确配置 Identity 服务或没有在 Startup.cs 中调用 AddIdentity

解决方案: 确保在 ConfigureServices 方法中正确添加了 Identity 服务:

代码语言:txt
复制
services.AddIdentity<IdentityUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

2. JWT 认证无效

原因: 可能 TokenValidationParameters 配置不正确或密钥不匹配。

解决方案: 检查 appsettings.json 中的 JWT 配置:

代码语言:txt
复制
"Jwt": {
  "Key": "YourSecretKeyAtLeast16Characters",
  "Issuer": "YourIssuer",
  "Audience": "YourAudience",
  "ExpireDays": 7
}

3. 跨域问题 (CORS)

解决方案: 在 Startup.cs 中配置 CORS:

代码语言:txt
复制
services.AddCors(options =>
{
    options.AddPolicy("AllowAll",
        builder => builder.AllowAnyOrigin()
                         .AllowAnyMethod()
                         .AllowAnyHeader());
});

// 在 Configure 方法中
app.UseCors("AllowAll");

优势

  1. 安全性: JWT 是无状态的,不需要服务器端存储会话信息
  2. 可扩展性: 适用于分布式系统和微服务架构
  3. 灵活性: 可以包含自定义声明,传递额外用户信息
  4. 标准化: 遵循开放标准,易于与其他系统集成

应用场景

  1. 单页应用程序 (SPA) 认证
  2. 移动应用后端服务
  3. 微服务架构中的服务间认证
  4. 需要无状态认证的分布式系统

最佳实践

  1. 使用 HTTPS 保护 JWT 传输
  2. 设置合理的令牌过期时间
  3. 不要在 JWT 中存储敏感信息
  4. 实现令牌刷新机制
  5. 定期轮换签名密钥
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

没有搜到相关的文章

领券