首页 > 其他分享 >.net 8 实现【JWT】 十分钟领略【无状态设计】

.net 8 实现【JWT】 十分钟领略【无状态设计】

时间:2024-11-13 22:58:22浏览次数:1  
标签:Authorize api JWT audience token 十分钟 new net options

    本文主要分为两个部分:

    1、概念

    2、.net 8 demo

    第一部分主要描述所有与 JWT 相关的概念以及词汇,及其原理;第二部分是代码示例。

 

 

1、概念

JWT

json web token 是一种开放标准(RFC 7519),是指定一种数据格式(json) 和数据结构 (header, payload, signature) ,

用于网络应用间信息传输,一般是用于客户端与服务器之间的安全校验

authentication

鉴权;可以为用户创建 token,可以校验 token 有效性

authorization

批准 / 授权;是一种配置,约束访问条件,例如:

[Authorize(Roles = "Admin")] // 管理员才可访问

[Authorize(Policy = "EmployeeWithDepartment")] // 符合特定策略才可访问

bearer

持票人,使用场景在于请求时,header 的格式

例如请求头部的参数 "Authorization" : "Bearer tokenString"

 

一个 token 由 3 个部分组成,并且以实心句号 . 分割,以下为一个 token 示例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidXNlcjEyMyIsIm5iZiI6MTczMTM5MzYzNiwiZXhwIjoxNzMxMzk3MjM2LCJpYXQiOjE3MzEzOTM2MzYsImlzcyI6InlvdXJkb21haW4uY29tIiwiYXVkIjoieW91ci1hcGktYXVkaWVuY2UifQ.q2zUeZ3RAVIxg5CVNI2Pjq9Nfvue3_tCQagDRJmStYI

 

 

token part

decode (by base64)

remark

header

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

{ "alg" : "HS256", "typ" : "JWT" }

token metadata

说明用于加密的算法类型

payload

(有效载荷)

eyJuYW1lIjoidXNlcjEyMyIsIm5iZiI6MTczMTM5MzYzNiwiZXhwIjoxNzMxMzk3MjM2LCJpYXQiOjE3MzEzOTM2MzYsImlzcyI6InlvdXJkb21haW4uY29tIiwiYXVkIjoieW91ci1hcGktYXVkaWVuY2UifQ

{

    "name": "user123",

    "nbf": 1731393636,

    "exp": 1731397236,

    "iat": 1731393636,

    "iss": "yourdomain.com",

    "aud": "your-api-audience"

}

自定义的用户信息(claims),

以及一些必要信息:

nbf : not before, token 生效时间

exp : expiration time, token 过期时间

iat : issued at 签发时间

iss : issuer of the token 签发者(比如服务端名字)

aud : audience,该 token 的受众,可以是服务名称 或者 api 名称等等

signature

q2zUeZ3RAVIxg5CVNI2Pjq9Nfvue3_tCQagDRJmStYI

N/A

signature:是根据 header 中指定的算法以及在服务端密钥,对 payload 加密得到的哈希值;

用于服务端校验 token 是否签发自服务端。

 

(请求时 token 的 payload 与解密 signature 后得到的payload 需要一致,所以擅改 payload 会导致token 无效)

 

无状态(stateless):指服务端不需要存储任何关于用户会话的信息。

signature 的设计保证了 token 的安全性,所以不再需要另外存储用户会话状态,以此减少服务端压力和复杂性,做到“无状态”化。

* base64 transfer online : Base64编码_base64在线解码_base64加密在线转换

 

 

 

2、.net 8 demo

2.1 Authentication

包引用

using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

创建 token 的方法

 1 public string GenerateJwtToken(string userName)
 2 {
 3 
 4     var tokenHander = new JwtSecurityTokenHandler();
 5     var key = Encoding.ASCII.GetBytes("your secret key");
 6     var tokenDescriptor = new SecurityTokenDescriptor
 7     {
 8         // configure the custome information in the Claim instance
 9         Subject = new System.Security.Claims.ClaimsIdentity(new[] { new Claim("name", userName) }),
10 
11         // configure the expiration time
12         Expires = DateTime.UtcNow.AddHours(1),
13 
14         // issuer could be your service name or other, and it will be the [iss] of the token
15         Issuer = "xx Servicing",
16 
17         // audience could be the audience of your service, and it will be the [aud] of the token
18         Audience = "your api audience",
19 
20         // configure secret algorithm and secret key for signature part
21         SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
22 
23     };
24 
25     var token = tokenHander.CreateToken(tokenDescriptor);
26     return tokenHander.WriteToken(token);
27 }

 

验证 token 的配置

 1 builder.Services.AddAuthentication(options =>
 2 {
 3     options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
 4     options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
 5 })
 6 .AddJwtBearer(options =>
 7 {
 8     options.TokenValidationParameters = new TokenValidationParameters
 9     {
10         // validate the token expiration
11         ValidateLifetime = true, 
12 
13         // validate signature
14         ValidateIssuerSigningKey = true,
15 
16         // need to sure the issuer/audience value here is same with the issuer/audience while token generating
17         ValidateIssuer = true,
18         ValidateAudience = true,
19         ValidIssuer = "yourdomain.com",
20         ValidAudience = "your-api-audience",
21 
22         //ValidateIssuer = false, // Skip issuer validation
23         //ValidateAudience = false, // Skip audience validation
24 
25         IssuerSigningKey = new SymmetricSecurityKey("your secret key"),
26         ClockSkew = TimeSpan.FromMinutes(5) // Allow for clock skew
27 
28     };
29 
30 });

 

开启 authentication 和 authorization

1 app.UseAuthentication();
2 app.UseAuthorization();

 

!注意:

1、此处的 Authentication,Authorization 都是 Miscroft.AspNetCore 自带的中间件。

2、Authentication 是鉴权,Authorization 是授权 / 批准,这两个中间件的位置不能错,必须是:鉴权在前。

Authentication 中间件主要负责验证 token ,比如检查签名是否正确,检查 token 有效期。

当 Authentication 中间件成功验证令牌后,它会将 token 中的用户信息(像是用户ID、角色等)写入到 httpContext,再传递给 Authorization 中间件。此时,Authorization 会拿到有效的 httpContext.User 属性,这是一个 ClaimsPrincipal 对象,包含了用户信息声明(claims);

若绕开了 Authentication 中间件,httpContext 直接到 Authorization ,此时会找不到合法的 httpContext.User,所以返回 401 Unauthorized 错误。

 

 

2.2 Authorization

2.2.1 Authorize

1     // 标注 Authorize 后访问该api时会验证token
2     [Authorize]
3     [HttpGet("GetList")]
4     public IEnumerable<WeatherForecast> GetList()
5     {
6         ..
7     }

 

2.2.2 Policy 策略

 1     // 在 Startup.cs 中配置策略
 2     services.AddAuthorization(options =>
 3     {  
 4         options.AddPolicy("Over18", policy =>
 5             policy.RequireClaim("Age", "18"));  // 验证 token 中的 age 参数是否等于 18
 6     });
 7 
 8     // 在 Controller 中使用策略
 9     [Authorize(Policy = "Over18")]
10     public IActionResult RestrictedContent()
11     {
12        ..
13     }

 

 1     // 验证 token 中的 role 参数是否 ("Admin", "Manager")中的成员,注:大小写敏感
 2     services.AddAuthorization(options =>
 3     {
 4         options.AddPolicy("AdminOrManager", policy =>
 5             policy.RequireRole("Admin", "Manager"));
 6     });
 7 
 8     // 多个“并且”条件的声明
 9     services.AddAuthorization(options =>
10     {
11 
12         options.AddPolicy("EmployeeWithDepartment", policy =>
13             policy.RequireClaim("EmployeeNumber")
14                   .RequireClaim("Department", "HR", "IT"));
15     });

 

2.2.3 AllowAnonymous

 [Authorize] 可以修饰在 controller 上,这意味着该 controller 下的所有 api 都需要验证token,此时可以通过修饰 [AllowAnonymous] 特别指定某一个 api 不需要 token 验证。

 1 [Authorize]
 2 public class AccountController : Controller
 3 {
 4 
 5     [AllowAnonymous]
 6     public IActionResult Login()
 7     {
 8         ..
 9     }
10 
11 
12     public IActionResult Logout()
13     {
14         ..
15     }
16 
17 }

 

 

 

博客园的编辑器也太难用了吧!!

2024-11-13

 

标签:Authorize,api,JWT,audience,token,十分钟,new,net,options
From: https://www.cnblogs.com/carmen-019/p/18544948

相关文章

  • nfs服务器之间实现目录共享_netapp nfs挂载共享目录某个文件夹给服务器
    title:nfs服务器之间实现目录共享date:2022-11-0522:41:54tags:[nfs,文件共享]categories:linux在使用airflow的时候,scheduler和worker之间的dag文件需要保持一致,而airflow没有解决这个问题,所以,需要我们自己解决dag文件的同步问题。第一个解决方案就是云服务商提供的nas......
  • GAN, Generative Adversarial Networks(生成式对抗网络)
    深度学习中最有趣的领域–GAN,GenerativeAdversarialNetworks(生成式对抗网络)GAN的基础概念GAN被“卷积网络之父”YannLeCun(杨立昆)誉为「过去十年计算机科学领域最有趣的想法之一」,是近年来火遍全网,AI研究者最为关注的深度学习技术方向之一。生成式对抗网络,简称G......
  • 泷羽sec专题课笔记-- Windows--补充Telnet连接Linux
    本笔记为泷羽sec《红队全栈课程》学习笔记,课程请可自行前往B站学习,课程/笔记主要涉及网络安全相关知识、系统以及工具的介绍等,请使用该课程、本笔记以及课程和笔记中提及工具的读者,遵守网络安全相关法律法规,切勿进行违法违规违纪的操作。写在最前面的话,我们为什么要学习......
  • dotnet core微服务框架Jimu ~ 浏览和发布新闻微服务
    提供新闻浏览和发布服务有3个需要授权公开的api:GetAllNews获取所有新闻PostNews发布新闻,具有admin角色的会员才能发布新闻GetNews根据id获取指定的新闻1声明接口,创建基于.NetCore6.0的类库项目,命名为News.IServices1.1添加jimu引用Install-P......
  • .NET Core 泛型底层原理浅谈
    .NETCore泛型底层原理浅谈 简介泛型参考资料烂大街,基本资料不再赘述,比如泛型接口/委托/方法的使用,逆变与协变。泛型好处有如下几点代码重用算法重用,只需要预先定义好算法,排序,搜索,交换,比较等。任何类型都可以用同一套逻辑类型安全编译器保证不会将int传给string简单清......
  • .NET 9使用Scalar替代Swagger
    .NET9使用Scalar替代Swagger 背景.NET9刚刚正式发布了,如果你创建一个空的Asp.NetCore9.0的WebAPI项目,启动之后,你会惊讶地发现陪伴你多年的Swagger没有了!——这是因为ASP.NETCore项目组已经将Swashbuckle.AspNetCore从.NET9里移除了,详情看这里 [github]Announcement:......
  • 【自动驾驶-感知】CenterNet与CenterFusion融合目标检测的目标检测模型实战代码-基于P
    【自动驾驶-感知】CenterNet与CenterFusion融合目标检测的目标检测模型实战代码一.CenterNet目标检测模型1.中心点热力图2.物体尺寸回归3.分类任务4.损失函数二、融合目标检测CenterFusion算法原理三.实现案例与代码数据集与实验环境数据预处理与增强模型定义......
  • libcurl.net入门使用
    libcurl.net入门使用关于libcurl.net一个引用libcurl.dll并封装为.NET使用的Curl库,方便在.NET应用程序里面执行Curl命令,没有其他库依赖,只是对libcurl.dll的封装和引用。在大多数情况下,我们可以或者比较容易获取Web请求的Curl格式的请求内容,因此该库可以比较方便地对已知Curl命......
  • 【阅读文献笔记】TransXNet: Learning Both Global and LocalDynamics with a Dual Dy
    从经典的ViTs说起,即基于MHSA构建远距离建模实现全局感受野的覆盖,但缺乏像CNNs般的归纳偏差能力。因此在泛化能力上相对较弱,需要大量的训练样本和数据增强策略来弥补。针对这个问题,SwinTransformer率先引入了移位窗口自注意力来引入归纳偏差并减少计算成本。然而,作者......
  • .net动态类ExpandoObject及使用场景
    它位于System.Dynamic命名空间中。与普通的C#类型不同,ExpandoObject允许在运行时动态地添加、删除或修改其成员(属性或方法)。这使得它在一些需要高度灵活性和动态性的数据结构场景中非常有用。ExpandoObject的基本特性动态成员访问:可以在运行时添加或移除属性和方法。弱类型......