
在 ASP.NET Core Minimal API 项目中,认证是几乎所有业务系统都绕不开的问题。 很多文章会把 JWT、Cookie、Session 放在一起比较,甚至直接称为“三种认证方式”。这种说法并不严谨。 从 ASP.NET Core 的认证体系来看,Cookie Authentication 和 JWT Bearer Authentication 才属于典型的 Authentication Scheme(认证方案);而 Session 本质上是服务器端状态管理机制,可以参与登录状态管理,但它本身不是一个独立的认证方案。 本文从 ASP.NET Core 的实际机制出发,说明 Minimal API 中认证、Cookie、JWT 和 Session 的正确关系,并给出最常用的代码示例以及实际项目中的选型建议。
如果只记住一件事情,可以记住下面这张表:
技术 | 本质 | 是否属于 ASP.NET Core 认证方案 | 主要用途 |
|---|---|---|---|
Cookie Authentication | 认证方案 | ✅ | 浏览器 Web 应用 |
JWT Bearer | 认证方案 | ✅ | 前后端分离、App、桌面端、API |
Session | 服务器端状态管理 | ❌ | 保存临时服务器端状态 |
Refresh Token | Token 刷新机制 | ❌ | 获取新的 Access Token |
Redis | 分布式存储 | ❌ | 保存 Session、Token 状态等 |
OAuth 2.0 | 授权框架 | ❌/视具体实现 | 第三方授权 |
OpenID Connect | 身份认证协议 | 通常通过认证 Handler 实现 | 企业 SSO、OIDC 登录 |
所以:
不要说“Minimal API 有 JWT、Cookie、Session 三种认证方式”。
更准确的说法是:
ASP.NET Core Minimal API 可以使用多种认证方案,其中最常见的是 Cookie Authentication 和 JWT Bearer Authentication;Session 则是服务器端状态管理机制,可以与认证系统配合使用。
ASP.NET Core 的认证核心目标非常简单:
确定当前 HTTP 请求对应的用户身份。
例如用户请求:
GET /api/profile服务器需要知道:
这个请求是谁发的?
UserId = 1001
Name = admin
Role = Admin认证系统最终会构造:
HttpContext.User也就是:
HttpContext.User.Identity
HttpContext.User.Claims例如:
app.MapGet("/api/profile", (HttpContext context) =>
{
var userId = context.User.FindFirst(
ClaimTypes.NameIdentifier)?.Value;
var name = context.User.Identity?.Name;
return Results.Ok(new
{
userId,
name
});
})
.RequireAuthorization();这里真正被授权系统使用的是:
HttpContext.User这是 ASP.NET Core 中非常重要的两个概念。
解决:
你是谁?
例如:
用户名 + 密码
↓
验证成功
↓
UserId = 1001解决:
你能做什么?
例如:
UserId = 1001
Role = Admin访问:
DELETE /api/users/1002授权系统判断:
Admin
↓
允许所以完整流程:
请求
↓
Authentication
↓
确定用户身份
↓
HttpContext.User
↓
Authorization
↓
判断权限
↓
执行 EndpointASP.NET Core 中真正的“认证方式”更准确地说应该叫:
Authentication Scheme(认证方案)
例如:
builder.Services
.AddAuthentication()
.AddCookie();
builder.Services
.AddAuthentication()
.AddJwtBearer();这里:
Cookie
JWT Bearer就是认证方案。
不同认证方案负责:
如何获取凭证
↓
如何验证凭证
↓
如何创建 ClaimsPrincipal
↓
如何设置 HttpContext.UserCookie Authentication 是 ASP.NET Core 最经典的认证方案之一。
它的核心流程:
用户登录
↓
服务器验证用户名密码
↓
创建 ClaimsPrincipal
↓
SignInAsync()
↓
ASP.NET Core 生成认证 Cookie
↓
浏览器保存 Cookie
↓
后续请求自动携带 Cookie
↓
Cookie Authentication Handler 验证
↓
HttpContext.User注意:
这里的 Cookie 不是简单意义上的“保存一个字符串”。
ASP.NET Core 的 Cookie Authentication 会对认证信息进行保护,并由 Cookie Authentication Handler 负责读取和验证。
首先配置认证:
using Microsoft.AspNetCore.Authentication.Cookies;
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddAuthentication(
CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.Name = "MyAuth";
options.ExpireTimeSpan =
TimeSpan.FromHours(8);
options.SlidingExpiration = true;
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();登录成功后:
app.MapPost("/api/login",
async (
LoginRequest request,
HttpContext context) =>
{
// 实际项目中应该查询数据库验证密码
if (request.Username != "admin" ||
request.Password != "123456")
{
return Results.Unauthorized();
}
var claims = new[]
{
new Claim(
ClaimTypes.NameIdentifier,
"1001"),
new Claim(
ClaimTypes.Name,
"admin"),
new Claim(
ClaimTypes.Role,
"Admin")
};
var identity = new ClaimsIdentity(
claims,
CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);
await context.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
principal);
return Results.Ok();
});之后:
app.MapGet("/api/profile",
(HttpContext context) =>
{
return Results.Ok(new
{
ClaimTypes.NameIdentifier)?.Value,UserId = context.User.FindFirst(
Name = context.User.Identity?.Name
});
})
.RequireAuthorization();浏览器会自动携带认证 Cookie。
Cookie Authentication 最适合:
浏览器
↓
Web 应用
↓
ASP.NET Core例如:
如果你的系统主要是:
浏览器 → ASP.NET CoreCookie Authentication 往往是非常自然的选择。
JWT Bearer 是 API 系统中非常常见的认证方案。
它的核心思想是:
登录
↓
服务器生成 Access Token
↓
客户端保存 Token
↓
请求 API
↓
Authorization: Bearer xxx
↓
JWT Bearer Authentication
↓
验证 Token
↓
HttpContext.User这里需要注意一个概念:
JWT 是一种 Token 格式,而 JWT Bearer 是 ASP.NET Core 中用于验证 Bearer Token 的认证方案。
因此严格来说:
JWT和:
JWT Bearer Authentication不是完全相同的概念。
安装:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer配置:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
var key = Encoding.UTF8.GetBytes(
"ThisIsADevelopmentSecretKey123456789");
builder.Services
.AddAuthentication(
JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters =
new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "MyApi",
ValidAudience = "MyClient",
IssuerSigningKey =
new SymmetricSecurityKey(key)
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();登录接口:
app.MapPost("/api/login",
(LoginRequest request) =>
{
if (request.Username != "admin" ||
request.Password != "123456")
{
return Results.Unauthorized();
}
var claims = new[]
{
new Claim(
ClaimTypes.NameIdentifier,
"1001"),
new Claim(
ClaimTypes.Name,
"admin"),
new Claim(
ClaimTypes.Role,
"Admin")
};
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(
"ThisIsADevelopmentSecretKey123456789"));
var credentials = new SigningCredentials(
key,
SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "MyApi",
audience: "MyClient",
claims: claims,
expires: DateTime.UtcNow.AddMinutes(30),
signingCredentials: credentials);
var accessToken =
new JwtSecurityTokenHandler()
.WriteToken(token);
return Results.Ok(new
{
accessToken
});
});客户端之后发送:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...JWT Bearer 特别适合:
Vue
React
Avalonia
WPF
WinForms
Android
iOS
第三方客户端例如:
┌─────────────┐
│ Minimal API │
└──────┬──────┘
│
┌─────────┼─────────┐
│ │ │
▼ ▼ ▼
Vue Avalonia Mobile
│ │ │
└─────────┼─────────┘
│
JWT所有客户端都可以按照统一的 Bearer Token 方式调用 API。
因此:
如果你的 Minimal API 是一个真正的 API 服务,并且存在多个不同类型的客户端,JWT Bearer 通常是最合适的默认选择。
JWT 的一个特点是:
服务器签发 JWT
↓
Token 在有效期内
↓
服务器通常可以直接验证 Token这意味着如果:
Token 有效期 = 2 小时用户在:
第 10 分钟被管理员禁用,之前签发的 JWT 默认仍然可能有效。
所以实际项目通常不会简单地使用:
一个长期 JWT而是:
Access Token
+
Refresh Token典型设计:
Access Token
↓
15~30 分钟
Refresh Token
↓
7~30 天Access Token 过期:
Refresh Token
↓
服务器验证
↓
重新签发 Access Token如果用户退出登录、账号被禁用或者 Refresh Token 被撤销:
Refresh Token
↓
无法继续刷新这样比单纯使用一个长期 JWT 更适合生产系统。
现在回到本文最容易混淆的地方:
Session 到底是不是认证方式?
严格来说:
不是。
ASP.NET Core Session 是:
服务器端状态管理机制。
它的核心目的不是:
验证“你是谁”而是:
保存“服务器需要暂时记住什么”例如:
Session
├── UserId
├── ShoppingCart
├── SearchCondition
└── TemporaryStateSession 通常可以理解为:
浏览器
│
│ Session ID
▼
ASP.NET Core
│
▼
Session Store
│
├── UserId = 1001
└── Other State浏览器保存的是 Session ID。
服务器根据 Session ID 找到服务器端保存的数据。
因此:
Cookie Authentication和:
Session虽然都可能涉及 Cookie,但它们不是同一个东西。
这是最容易搞错的地方。
目标:
认证用户身份最终形成:
HttpContext.User目标:
保存服务器端状态通过:
HttpContext.Session访问。
所以:
HttpContext.User和:
HttpContext.Session是两个完全不同的概念。
可以同时存在:
HttpContext
│
├── User
│ └── Authentication
│
└── Session
└── Server-side state可以。
例如:
app.MapPost("/api/login",
(HttpContext context) =>
{
context.Session.SetInt32(
"UserId",
1001);
return Results.Ok();
});然后:
app.MapGet("/api/profile",
(HttpContext context) =>
{
var userId =
context.Session.GetInt32("UserId");
if (userId == null)
{
return Results.Unauthorized();
}
return Results.Ok(new
{
UserId = userId
});
});从业务效果来看:
登录
↓
Session 保存 UserId
↓
后续请求读取 UserId
↓
认为用户已登录确实能够实现登录状态。
但是这不意味着:
Session 本身就是 ASP.NET Core Authentication Scheme。
它只是你可以用来自行维护登录状态的一种服务器端状态机制。
如果希望真正接入 ASP.NET Core 标准认证授权体系,通常应该使用 Cookie Authentication 或 JWT Bearer 等认证方案。
Session 更适合:
临时状态例如:
购物车
多步骤表单
临时查询条件
验证码流程
临时用户操作状态而不是把它作为现代 API 项目的默认认证机制。
特别是在:
Vue
+
Minimal API
+
Avalonia
+
Mobile这样的多客户端系统中,Session 通常不是最佳选择。
如果是现代前后端分离项目:
Vue / React / Avalonia / Mobile
│
▼
ASP.NET Core
Minimal API
│
▼
Authentication
│
┌─────┴─────┐
│ │
JWT Cookie
│ │
API客户端 浏览器然后:
Authorization
↓
Policies / Roles / Claims可以直接按照客户端类型选择。
浏览器
↓
ASP.NET Core推荐:
Cookie Authentication
例如:
企业管理系统
后台管理系统
Razor Pages
MVC
浏览器业务系统如果 Vue 是一个纯前后端分离 SPA:
Vue
↓
Minimal API有两种合理选择。
如果系统本质上就是一个浏览器 Web 应用:
Cookie Authentication 很合适。
如果 API 未来还需要支持:
App
桌面客户端
第三方客户端那么:
JWT Bearer 更合适。
推荐:
JWT Bearer
典型结构:
Avalonia
↓
Login
↓
Minimal API
↓
Access Token
↓
Authorization: Bearer xxx例如:
Vue 管理后台
Avalonia 客户端
移动端
第三方 API推荐:
JWT Bearer + Refresh Token
这是非常典型的 API 架构。
生产项目不要把所有东西都塞进 JWT。
推荐:
登录
│
▼
用户名 / 密码
│
▼
Minimal API
│
┌───────┴────────┐
│ │
▼ ▼
Access Token Refresh Token
短期有效 长期有效
│ │
▼ ▼
客户端 服务器状态调用 API:
Authorization:
Bearer AccessTokenAccess Token 过期:
Refresh Token
↓
服务器验证
↓
生成新的 Access Token注销:
撤销 Refresh Token账号禁用:
禁止 Refresh这样就形成比较完整的登录体系。
无论最终选择 Cookie 还是 JWT,都应该理解下面这几个组件:
builder.Services
.AddAuthentication();
builder.Services
.AddAuthorization();然后:
app.UseAuthentication();
app.UseAuthorization();接口:
app.MapGet("/api/profile", ...)
.RequireAuthorization();角色:
app.MapGet("/api/admin", ...)
.RequireAuthorization("Admin");最终:
Authentication
↓
HttpContext.User
↓
Authorization
↓
RequireAuthorization()
↓
Endpoint这才是 Minimal API 认证授权体系的核心。
最重要的是不要把几个概念混在一起。
正确理解应该是:
ASP.NET Core Authentication
│
├── Cookie Authentication
│
├── JWT Bearer Authentication
│
├── OAuth / OpenID Connect
│
└── 其他 Authentication Scheme而:
Session
│
└── 服务器端状态管理两者不是同一层级。
项目类型 | 推荐方案 |
|---|---|
Razor Pages / MVC | Cookie Authentication |
纯浏览器 Web 系统 | Cookie Authentication |
Vue + Minimal API | Cookie 或 JWT,取决于客户端形态 |
移动 App + API | JWT Bearer |
Avalonia + API | JWT Bearer |
WPF + API | JWT Bearer |
多客户端 API | JWT Bearer |
第三方 API | JWT Bearer / OAuth 2.0 |
临时服务器端状态 | Session |
JWT 长期登录 | Access Token + Refresh Token |
高安全要求 API | JWT + Refresh Token + 服务端会话/撤销机制 |
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。