浅谈ASP.NET Core 中jwt授权认证的流程原理

2025-05-29 0 24

1,快速实现授权验证

什么是 JWT ?为什么要用 JWTJWT 的组成?

这些百度可以直接找到,这里不再赘述。

实际上,只需要知道 JWT 认证模式是使用一段 Token 作为认证依据的手段。

我们看一下 Postman 设置 Token 的位置。

浅谈ASP.NET Core 中jwt授权认证的流程原理

那么,如何使用 C# 的 HttpClient 访问一个 JWT 认证的 WebAPI 呢?

浅谈ASP.NET Core 中jwt授权认证的流程原理

下面来创建一个 ASP.NET Core 项目,尝试添加 JWT 验证功能。

1.1 添加 JWT 服务配置

在 Startup.cs 的 ConfigureServices 方法中,添加一个服务

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27
// 设置验证方式为 Bearer Token

// 你也可以添加 using Microsoft.AspNetCore.Authentication.JwtBearer;

// 使用 JwtBearerDefaults.AuthenticationScheme 代替 字符串 "Brearer"

services.AddAuthentication("Bearer")

.AddJwtBearer(options =>

{

options.TokenValidationParameters = new TokenValidationParameters

{

ValidateIssuerSigningKey = true,

IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("abcdABCD1234abcdABCD1234")), // 加密解密Token的密钥

// 是否验证发布者

ValidateIssuer = true,

// 发布者名称

ValidIssuer = "server",

// 是否验证订阅者

// 订阅者名称

ValidateAudience = true,

ValidAudience = "client007",

// 是否验证令牌有效期

ValidateLifetime = true,

// 每次颁发令牌,令牌有效时间

ClockSkew = TimeSpan.FromMinutes(120)

};

});

修改 Configure 中的中间件

?

1

2

3

4
app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthentication(); // 注意这里

app.UseAuthorization();

就是这么简单,通过以上设置,要求验证请求是否有权限。

1.2 颁发 Token

颁发的 Token ,ASP.NET Core 不会保存。

ASP.NET Core 启用了 Token 认证,你随便将生成 Token 的代码放到不同程序的控制台,只要密钥和 Issuer 和 Audience 一致,生成的 Token 就可以登录这个 ASP.NET Core。

也就是说,可以随意创建控制台程序生成 Token,生成的 Token 完全可以登录 ASP.NET Core 程序。

至于原因,我们后面再说,

在 Program.cs 中,添加一个这样的方法

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25
static void ConsoleToke()

{

// 定义用户信息

var claims = new Claim[]

{

new Claim(ClaimTypes.Name, "痴者工良"),

new Claim(JwtRegisteredClaimNames.Email, "66666666666@qq.com"),

};

// 和 Startup 中的配置一致

SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("abcdABCD1234abcdABCD1234"));

JwtSecurityToken token = new JwtSecurityToken(

issuer: "server",

audience: "client007",

claims: claims,

notBefore: DateTime.Now,

expires: DateTime.Now.AddMinutes(30),

signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)

);

string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);

Console.WriteLine(jwtToken);

}

Main() 中,调用此方法

?

1

2

3

4

5
public static void Main(string[] args)

{

ConsoleToke();

CreateHostBuilder(args).Build().Run();

}

1.3 添加 API访问

我们添加一个 API。

[Authorize] 特性用于标识此 Controller 或 Action 需要使用合规的 Token 才能登录。

?

1

2

3

4

5

6

7

8

9

10

11
[Authorize]

[Route("api/[controller]")]

[ApiController]

public class HomeController : ControllerBase

{

public string Get()

{

Console.WriteLine(User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Name));

return "访问成功";

}

}

然后启动 ASP.NET Core,在 Postman 测试 访问 https://localhost/api/home。

浅谈ASP.NET Core 中jwt授权认证的流程原理

发现报 401 (无权限)状态码,这是因为请求时不携带令牌,会导致不能访问 API。

从控制台终端复制生成的 Token 码,复制到 Postman 中,再次访问,发现响应状态码为 200,响应成功。

浅谈ASP.NET Core 中jwt授权认证的流程原理

ASP.NET Core 自带 jwt 认证大概就是这样。

那么,ASP.NET Core 内部是如何实现的呢?又有哪些特性哪些坑呢?请往下看~

2,探究授权认证中间件

在上面的操作中,我们在管道配置了两个中间件。

?

1

2
app.UseAuthentication();

app.UseAuthorization();

app.UseAuthentication(); 的作用是通过 ASP.NET Core 中配置的授权认证,读取客户端中的身份标识(Cookie,Token等)并解析出来,存储到 context.User 中。

app.UseAuthorization(); 的作用是判断当前访问 Endpoint (Controller或Action)是否使用了 [Authorize]以及配置角色或策略,然后校验 Cookie 或 Token 是否有效。

使用特性设置相应通过认证才能访问,一般有以下情况。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32
// 不适用特性,可以直接访问

public class AController : ControllerBase

{

public string Get() { return "666"; }

}

/// <summary>

/// 整个控制器都需要授权才能访问

/// </summary>

[Authorize]

public class BController : ControllerBase

{

public string Get() { return "666"; }

}

public class CController : ControllerBase

{

// 只有 Get 需要授权

[Authorize]

public string Get() { return "666"; }

public string GetB() { return "666"; }

}

/// <summary>

/// 整个控制器都需要授权,但 Get 不需要

/// </summary>

[Authorize]

public class DController : ControllerBase

{

[AllowAnonymous]

public string Get() { return "666"; }

}

2.1 实现 Token 解析

至于 ASP.NET Core 中,app.UseAuthentication();app.UseAuthorization(); 的源代码各种使用了一个项目来写,代码比较多。要理解这两个中间件的作用,我们不妨来手动实现他们的功能。

解析出的 Token 是一个 ClaimsPrincipal 对象,将此对象给 context.User 赋值,然后在 API 中可以使用 User 实例来获取用户的信息。

在中间件中,使用下面的代码可以获取客户端请求的 Token 解析。

?

1
context.RequestServices.GetRequiredService<IAuthenticationService>().AuthenticateAsync(context, JwtBearerDefaults.AuthenticationScheme);

那么,我们如何手工从原生的 Http 请求中,解析出来呢?且看我慢慢来分解步骤。

首先创建一个 TestMiddleware 文件,作为中间件使用。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22
public class TestMiddleware

{

private readonly RequestDelegate _next;

jwtSecurityTokenHandler = new JwtSecurityTokenHandler();

public TestMiddleware(RequestDelegate next)

{

_next = next;

}

public async Task Invoke(HttpContext context)

{

if (context == null)

{

throw new ArgumentNullException(nameof(context));

}

// 我们写代码的区域

// 我们写代码的区域

await _next(context);

}

}

2.1.1 从 Http 中获取 Token

下面代码可以中 http 请求中,取得头部的 Token 。

当然,客户端可能没有携带 Token,可能获取结果为 null ,自己加个判断。

贴到代码区域。

?

1
string tokenStr = context.Request.Headers["Authorization"].ToString();

Header 的 Authorization 键,是由 Breaer {Token}组成的字符串。

2.1.2 判断是否为有效令牌

拿到 Token 后,还需要判断这个 Token 是否有效。

因为 Authorization 是由 Breaer {Token}组成,所以我们需要去掉前面的 Brear 才能获取 Token。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16
/// <summary>

/// Token是否是符合要求的标准 Json Web 令牌

/// </summary>

/// <param name="tokenStr"></param>

/// <returns></returns>

public bool IsCanReadToken(ref string tokenStr)

{

if (string.IsNullOrWhiteSpace(tokenStr) || tokenStr.Length < 7)

return false;

if (!tokenStr.Substring(0, 6).Equals(Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme))

return false;

tokenStr = tokenStr.Substring(7);

bool isCan = jwtSecurityTokenHandler.CanReadToken(tokenStr);

return isCan;

}

获得 Token 后,通过 JwtSecurityTokenHandler.CanReadToken(tokenStr); 来判断 Token 是否符合协议规范。

将下面判断贴到代码区域。

?

1

2
if (!IsCanReadToken(ref tokenStr))

return ;

2.1.3 解析 Token

下面代码可以将 Header 的 Authorization 内容转为 JwtSecurityToken 对象。

(截取字符串的方式很多种,喜欢哪个就哪个。。。)

?

1

2

3

4

5

6

7

8

9

10
/// <summary>

/// 从Token解密出JwtSecurityToken,JwtSecurityToken : SecurityToken

/// </summary>

/// <param name="tokenStr"></param>

/// <returns></returns>

public JwtSecurityToken GetJwtSecurityToken(string tokenStr)

{

var jwt = jwtSecurityTokenHandler.ReadJwtToken(tokenStr);

return jwt;

}

不过这个 GetJwtSecurityToken 不是我们关注的内容,我们是要获取 Claim。

JwtSecurityToken.Claims

将下面代码贴到代码区域

?

1

2
JwtSecurityToken jst = GetJwtSecurityToken(tokenStr);

IEnumerable<Claim> claims = jst.Claims;

2.1.4 生成 context.User

context.User 是一个 ClaimsPrincipal 类型,我们通过解析出的 Claim,生成 ClaimsPrincipal。

?

1

2

3

4

5
JwtSecurityToken jst = GetJwtSecurityToken(tokenStr);

IEnumerable<Claim> claims = jst.Claims;

List<ClaimsIdentity> ci = new List<ClaimsIdentity>() { new ClaimsIdentity(claims) };

context.User = new ClaimsPrincipal(ci);

最终的代码块是这样的

?

1

2

3

4

5

6

7

8

9

10

11

12
// 我们写代码的区域

string tokenStr = context.Request.Headers["Authorization"].ToString();

string requestUrl = context.Request.Path.Value;

if (!IsCanReadToken(ref tokenStr))

return;

JwtSecurityToken jst = GetJwtSecurityToken(tokenStr);

IEnumerable<Claim> claims = jst.Claims;

List<ClaimsIdentity> ci = new List<ClaimsIdentity>() { new ClaimsIdentity(claims) };

context.User = new ClaimsPrincipal(ci);

var x = new ClaimsPrincipal(ci);

// 我们写代码的区域

2.2 实现校验认证

app.UseAuthentication(); 的大概实现过程已经做出了说明,现在我们来继续实现 app.UseAuthorization(); 中的功能。

继续使用上面的中间件,在原代码块区域添加新的区域。

?

1

2

3
// 我们写代码的区域

// 我们写的代码块

22.2.1 Endpoint

Endpoint 标识了一个 http 请求所访问的路由信息和 Controller 、Action 及其特性等信息。

[Authorize] 特性继承了 IAuthorizeData[AllowAnonymous] 特性继承了 IAllowAnonymous

以下代码可以获取所访问的节点信息。

?

1
var endpoint = context.GetEndpoint();

那么如何判断所访问的 Controller 和 Action 是否使用了认证相关的特性?

?

1
var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>() ?? Array.Empty<IAuthorizeData>();

Metadata 是一个 ASP.NET Core 实现的集合对象,GetOrderedMetadata<T> 可以找出需要的特性信息。

这个集合不会区分是 Contrller 还是 Action 的 [Authorize] 特性。

那么判断 是否有 [AllowAnonymous] 特性,可以这样使用。

?

1

2

3

4

5
if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null)

{

await _next(context);

return;

}

到此这篇关于浅谈ASP.NET Core 中jwt授权认证的流程原理的文章就介绍到这了,更多相关ASP.NET Core jwt授权认证内容请搜索快网idc以前的文章或继续浏览下面的相关文章希望大家以后多多支持快网idc!

原文链接:https://www.cnblogs.com/whuanle/p/12497614.html

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 浅谈ASP.NET Core 中jwt授权认证的流程原理 https://www.kuaiidc.com/98217.html

相关文章

发表评论
暂无评论