[特殊字符]C# ASP.NET Core 前后端分离终极实战:JWT 身份认证与授权全流程(登录 + 鉴权 + 避坑)

目录

    • [一、先搞懂:JWT 到底是什么?(生活类比秒懂)](#一、先搞懂:JWT 到底是什么?(生活类比秒懂))
      • [1.1 JWT 官方定义](#1.1 JWT 官方定义)
      • [1.2 生活类比:酒店入住](#1.2 生活类比:酒店入住)
      • [1.3 JWT 认证完整流程(流程图)](#1.3 JWT 认证完整流程(流程图))
    • [二、环境准备:项目创建 + 依赖安装](#二、环境准备:项目创建 + 依赖安装)
      • [2.1 创建项目](#2.1 创建项目)
      • [2.2 安装 JWT 必需 NuGet 包](#2.2 安装 JWT 必需 NuGet 包)
    • [三、第一步:后端配置 JWT(appsettings.json + Program.cs)](#三、第一步:后端配置 JWT(appsettings.json + Program.cs))
      • [3.1 配置 JWT 参数(appsettings.json)](#3.1 配置 JWT 参数(appsettings.json))
      • [3.2 注册 JWT 认证服务(Program.cs)](#3.2 注册 JWT 认证服务(Program.cs))
    • [四、第二步:编写登录接口 + 生成 JWT Token](#四、第二步:编写登录接口 + 生成 JWT Token)
      • [4.1 创建用户登录模型(LoginDto.cs)](#4.1 创建用户登录模型(LoginDto.cs))
      • [4.2 创建登录控制器(LoginController.cs)](#4.2 创建登录控制器(LoginController.cs))
    • [五、第三步:测试接口 + 前端携带 Token 访问](#五、第三步:测试接口 + 前端携带 Token 访问)
      • [5.1 测试登录接口](#5.1 测试登录接口)
      • [5.2 创建需要登录才能访问的接口](#5.2 创建需要登录才能访问的接口)
      • [5.3 前端携带 Token 请求格式](#5.3 前端携带 Token 请求格式)
    • [六、JWT 授权:区分角色权限(Admin/User)](#六、JWT 授权:区分角色权限(Admin/User))
    • [七、新手必踩的 10 大深坑(90% 的人都栽过)](#七、新手必踩的 10 大深坑(90% 的人都栽过))
      • [7.1 代码 / 配置类坑](#7.1 代码 / 配置类坑)
      • [7.2 前后端交互坑](#7.2 前后端交互坑)
      • [7.3 安全 / 业务坑](#7.3 安全 / 业务坑)
    • 八、完整跨域配置(前后端分离必备)
    • 九、总结
    • 留言互动

前后端分离项目里,前端(Vue/React/ 小程序)和后端(API)是分家的,不能像传统项目用 Session/Cookie 存登录状态,JWT 就是前后端之间的 "安全通行证",今天从 0 到 1 写代码、讲流程、踩坑全避坑,新手也能直接 CV 跑通!

一、先搞懂:JWT 到底是什么?(生活类比秒懂)

1.1 JWT 官方定义

JWT 全称JSON Web Token ,是一种轻量级、自包含的令牌,用于在前后端之间安全传输身份信息,前后端分离认证的首选方案。

1.2 生活类比:酒店入住

  • 你去酒店前台 = 前端调用登录接口
  • 出示身份证、密码 = 提交用户名 + 密码
  • 前台核对无误给你房卡 = 后端生成 JWT 令牌
  • 进房间、刷电梯 = 前端携带 Token 访问需要登录的接口
  • 房卡过期、伪造房卡打不开门 = Token 过期 / 无效 ,后端拒绝访问
    核心逻辑 :JWT 就是后端给前端发的一次性合法房卡,前端随身携带,后端只认卡不认人,简单高效!

1.3 JWT 认证完整流程(流程图)





前端:用户输入账号密码
后端:登录接口验证账号密码
验证成功?
后端生成JWT Token返回前端
返回登录失败提示
前端存储Token:LocalStorage/Cookie
前端请求接口:请求头携带 Authorization: Bearer Token
后端:JWT中间件验证Token有效性
验证通过?
放行请求,返回业务数据
返回401未授权/403权限不足

二、环境准备:项目创建 + 依赖安装

2.1 创建项目

打开 Visual Studio/Rider,创建ASP.NET Core Web API项目(.NET 6/7/8 通用)。

2.2 安装 JWT 必需 NuGet 包

打开包管理器控制台执行:

bash 复制代码
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer

这个包是.NET 官方 JWT 认证核心包,必须安装!

三、第一步:后端配置 JWT(appsettings.json + Program.cs)

3.1 配置 JWT 参数(appsettings.json)

把 JWT 的密钥、过期时间、签发者等配置写在这里,方便后期修改:

json 复制代码
"JwtSettings": {
  "SecretKey": "YourSecretKey@1234567890!@#$%^&*()", // 密钥(越长越安全)
  "Issuer": "MyBackendServer", // 令牌签发者(后端服务名)
  "Audience": "MyFrontendClient", // 令牌接收者(前端客户端)
  "ExpiresMinutes": 60 // Token过期时间(分钟)
}

3.2 注册 JWT 认证服务(Program.cs)

这是核心配置,告诉后端用 JWT 做身份认证:

csharp 复制代码
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// 1. 读取appsettings中的JWT配置
var jwtSettings = builder.Configuration.GetSection("JwtSettings");
var secretKey = Encoding.UTF8.GetBytes(jwtSettings["SecretKey"]);

// 2. 注册JWT认证服务
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        // 验证配置
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true, // 验证签发者
            ValidateAudience = true, // 验证接收者
            ValidateLifetime = true, // 验证过期时间
            ValidateIssuerSigningKey = true, // 验证签名密钥
            ValidIssuer = jwtSettings["Issuer"], // 签发者赋值
            ValidAudience = jwtSettings["Audience"], // 接收者赋值
            IssuerSigningKey = new SymmetricSecurityKey(secretKey) // 密钥赋值
        };
    });

// 3. 添加控制器支持
builder.Services.AddControllers();

var app = builder.Build();

// 4. 启用认证、授权中间件(顺序不能错!)
app.UseAuthentication(); // 先认证(判断你是谁)
app.UseAuthorization(); // 后授权(判断你能做什么)

app.MapControllers();
app.Run();

四、第二步:编写登录接口 + 生成 JWT Token

4.1 创建用户登录模型(LoginDto.cs)

用于接收前端传递的账号密码:

csharp 复制代码
/// <summary>
/// 登录参数接收类
/// </summary>
public class LoginDto
{
    public string UserName { get; set; } // 用户名
    public string Password { get; set; } // 密码
}

4.2 创建登录控制器(LoginController.cs)

核心:验证账号密码→生成 Token→返回给前端:

csharp 复制代码
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

[ApiController]
[Route("api/[controller]")]
public class LoginController : ControllerBase
{
    private readonly IConfiguration _configuration;

    // 注入配置类
    public LoginController(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    /// <summary>
    /// 用户登录接口
    /// </summary>
    [HttpPost]
    public IActionResult Login([FromBody] LoginDto loginDto)
    {
        // 1. 模拟验证账号密码(真实项目替换为数据库查询)
        if (loginDto.UserName != "admin" || loginDto.Password != "123456")
        {
            return Ok(new { code = 400, msg = "账号或密码错误" });
        }

        // 2. 创建JWT令牌的核心信息(可以存用户ID、角色、权限等)
        var claims = new[]
        {
            new Claim(ClaimTypes.Name, loginDto.UserName), // 用户名
            new Claim(ClaimTypes.Role, "Admin"), // 用户角色(用于授权)
            new Claim("UserId", "1001") // 自定义用户ID
        };

        // 3. 获取密钥
        var secretKey = Encoding.UTF8.GetBytes(_configuration["JwtSettings:SecretKey"]);
        var securityKey = new SymmetricSecurityKey(secretKey);

        // 4. 生成签名(加密方式)
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        // 5. 生成JWT Token
        var token = new JwtSecurityToken(
            issuer: _configuration["JwtSettings:Issuer"],
            audience: _configuration["JwtSettings:Audience"],
            claims: claims,
            expires: DateTime.Now.AddMinutes(Convert.ToDouble(_configuration["JwtSettings:ExpiresMinutes"])),
            signingCredentials: credentials
        );

        // 6. 生成最终的Token字符串
        var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);

        // 7. 返回给前端
        return Ok(new
        {
            code = 200,
            msg = "登录成功",
            data = new { token = tokenStr }
        });
    }
}

五、第三步:测试接口 + 前端携带 Token 访问

5.1 测试登录接口

用 Postman/Swagger 调用:POST https://localhost:7045/api/Login

请求体:

json 复制代码
{
    "UserName": "admin",
    "Password": "123456"
}

返回结果:

json 复制代码
{
    "code": 200,
    "msg": "登录成功",
    "data": {
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
    }
}

5.2 创建需要登录才能访问的接口

新建测试控制器,加上[Authorize]特性:

csharp 复制代码
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
[Authorize] // 关键:加此特性表示接口需要登录才能访问
public class TestController : ControllerBase
{
    [HttpGet("info")]
    public IActionResult GetUserInfo()
    {
        // 获取当前登录用户的信息
        var userName = User.Identity?.Name;
        var userId = User.FindFirst("UserId")?.Value;
        
        return Ok(new
        {
            code = 200,
            msg = "获取用户信息成功",
            data = new { userName, userId }
        });
    }
}

5.3 前端携带 Token 请求格式

前端请求必须在请求头中携带:

http 复制代码
Authorization: Bearer 你的Token值

⚠️注意:Bearer和 Token 之间必须有一个空格!

六、JWT 授权:区分角色权限(Admin/User)

JWT 不只能认证登录,还能做权限控制,比如:

  • 普通用户只能查数据
  • 管理员能增删改数据
    用法:给接口 / 控制器加角色限制:
csharp 复制代码
// 只有Admin角色能访问
[Authorize(Roles = "Admin")]
[HttpGet("admin")]
public IActionResult AdminApi()
{
    return Ok("管理员专属接口");
}

// 普通用户和管理员都能访问
[Authorize(Roles = "Admin,User")]
[HttpGet("user")]
public IActionResult UserApi()
{
    return Ok("普通用户接口");
}

七、新手必踩的 10 大深坑(90% 的人都栽过)

7.1 代码 / 配置类坑

  1. 中间件顺序错误: UseAuthentication必须在UseAuthorization之前,否则永远 401
  2. 密钥太短 / 太简单: 密钥长度不足会报错,必须≥16 位
  3. Token 生成时过期时间写反: 写成DateTime.Now.AddMinutes(-60),直接过期
  4. 请求头格式错误: Bearer后没空格、写成bearer小写、少写Authorization

7.2 前后端交互坑

  1. 前端跨域问题: 前后端分离必须配置跨域,否则请求被浏览器拦截
  2. Token 存储错误: 前端把 Token 存在 Session,刷新页面丢失
  3. Token 过期无处理: 前端没做过期拦截,用户一直卡在登录态

7.3 安全 / 业务坑

  1. 明文传输密码: 登录接口必须用 HTTPS,否则密码被抓包
  2. 密钥写死在代码里: 必须放在配置文件,方便环境切换
  3. JWT 存敏感信息: Token 可解码,不能存密码、身份证号

八、完整跨域配置(前后端分离必备)

新手最容易忘的一步,前端调用后端报跨域错误,直接加这段代码(Program.cs):

csharp 复制代码
// 注册跨域服务
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAll", policy =>
    {
        policy.AllowAnyOrigin() // 允许所有地址
              .AllowAnyHeader() // 允许所有请求头
              .AllowAnyMethod(); // 允许所有请求方式
    });
});

var app = builder.Build();

// 启用跨域(放在认证之前)
app.UseCors("AllowAll");

九、总结

  1. JWT 本质: 前后端分离的安全通行证,替代 Session/Cookie
  2. 核心流程: 登录验证→生成 Token→前端存储→请求头携带→后端鉴权
  3. 核心代码: JWT 注册配置、登录生成 Token、[Authorize]鉴权
  4. 关键避坑: 中间件顺序、请求头格式、跨域配置、Token 不存敏感信息

留言互动

大家在做 JWT 认证时还遇到过什么奇葩问题?评论区打出来,我一一解答!

原创不易,觉得有用的话点赞 + 收藏 + 关注,下期干货继续!

相关推荐
weixin_5375904513 小时前
《C程序设计语言》练习答案(练习1-13)
c语言·开发语言·c#
a177988771213 小时前
小程序上传图像失败
小程序·c#
JosieBook14 小时前
【C#】C# 所有关键字总结
开发语言·算法·c#
我是唐青枫15 小时前
C#.NET ConcurrentStack<T> 深入解析:无锁栈原理、LIFO 语义与使用边界
网络·c#·.net
黑棠会长15 小时前
ABP框架09.数据安全与合规:审计日志与实体变更追踪
分布式·安全·架构·c#·abp
JMchen12316 小时前
Android NDK开发从入门到实战:解锁应用性能的终极武器
android·开发语言·c++·python·c#·android studio·ndk开发
IT小哥哥呀17 小时前
基于windows的个人/团队的时间管理工具
windows·c#·wpf·时间管理
前端不太难18 小时前
OpenClaw:AI 权限治理的核心问题
人工智能·状态模式
JosieBook18 小时前
【C#】C# 访问修饰符与类修饰符总结大全
前端·javascript·c#