.NET JWT入坑

2024-04-13 08:20
文章标签 jwt net 入坑

本文主要是介绍.NET JWT入坑,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

JWT (JSON Web Token) 是一种安全传输信息的开放标准,由Header、Payload和Signature三部分组成。它主要用于身份验证、信息交换和授权。JWT可验证用户身份,确保访问权限,实现单点登录,并在客户端和服务器之间安全地交换信息。因其简单、安全和便捷,JWT在现代Web应用中广泛使用。

用JWT有多个原因:

  1. 无状态的身份验证:JWT允许服务器无需保存用户的会话信息,因为所有必要的信息都存储在令牌本身中。这降低了服务器的存储需求,并提高了系统的可扩展性。

  2. 跨域身份验证:由于JWT是自我包含的,并且可以被轻松传递,因此它非常适合跨域身份验证。用户可以在一个服务上验证身份,然后使用相同的令牌访问另一个服务,从而实现单点登录(SSO)。

  3. 安全性:JWT可以通过使用强大的加密算法(如HS256, RS256等)进行签名,以确保其完整性和真实性。服务器可以使用公钥验证令牌的签名,从而确保它没有被篡改,并且确实是由受信任的颁发者签发的。

  4. 减少数据库查询:由于用户的身份信息都存储在JWT中,服务器无需每次都去数据库中查询用户的身份信息,从而减少了数据库的压力和查询时间。

  5. 可定制性:JWT的Payload部分可以包含自定义的信息,如用户角色、权限等,这使得JWT非常灵活,并可以根据具体需求进行定制。

  6. 易于分发和共享:JWT可以轻松地通过网络传输,并且可以在多个服务和客户端之间共享,这使得它在微服务架构和分布式系统中非常有用。

  7. 标准化和互操作性:JWT是一个开放标准(RFC 7519),这意味着不同的系统和语言都可以使用相同的方式生成和验证JWT,从而提高了系统的互操作性。

环境 Win10  VS2022  .NET8 

✨ 建立项目jwttest

1.创建TestJwtController

2.下载JWT 

3.建实体类

/// <summary>
/// 用户信息类
/// </summary>
public class LoginRs
{/// <summary>/// 用户ID/// </summary>public string UserId { get; set; }/// <summary>/// 用户密码/// </summary>public string PasswordMD5 { get; set; }
}
/// <summary>
/// 用户登录信息类
/// </summary>
public class LoginInfo
{/// <summary>/// 用户信息/// </summary>public string UserId { get; set; }/// <summary>/// 检验时间/// </summary>public DateTime Expires { get; set; }
}
/// <summary>
/// rsmodel
/// </summary>
public class RsModel
{/// <summary>/// 是否成功/// </summary>public bool isOk { get; set; }/// <summary>/// 返回值/// </summary>public int code { get; set; }/// <summary>/// 返回消息/// </summary>public string msg { get; set; }/// <summary>/// 返回数据  /// </summary>public object rsData { get; set; }}

4.添加post login

      // POST api/<ValuesController>[HttpPost]public string Login([FromBody] LoginRs loginRequest){if (loginRequest == null) return JsonConvert.SerializeObject(new RsModel() { code = 0, isOk = false, msg = "登录信息为空!" });#region  判断userid pwdif (loginRequest.UserId != "admin" || loginRequest.PasswordMD5 != "admin"){return JsonConvert.SerializeObject(new RsModel() { code = 0, isOk = false, msg = "用户名和密码不正确!" });}#endregionLoginInfo Info = new LoginInfo(){UserId = loginRequest.UserId,Expires = DateTime.Now.AddDays(1)};const string secretKey = "myseckey";//口令加密秘钥byte[] key = Encoding.UTF8.GetBytes(secretKey);IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//加密方式IJsonSerializer serializer = new JsonNetSerializer();//序列化JsonIBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//base64加解密IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);//JWT编码var token = encoder.Encode(Info, key);//生成令牌return JsonConvert.SerializeObject(new RsModel() { code = 1, isOk = true, rsData = token, msg = "登录成功!" });}

5.登录验证

这里使用swagger方便检验    👉    .NET MVC API Swagger入坑

6.测试没问题,写个JwtHelper

 public static class JwtHelper{private static readonly string JwtKey = "mysecret";/// <summary>/// 获取加密解密/// </summary>/// <returns></returns>private static IJwtEncoder GetEncoder(){IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//加密方式IJsonSerializer serializer = new JsonNetSerializer();//序列化JsonIBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//base64加解密IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);//JWT编码return encoder;}/// <summary>/// 获取解密密钥/// </summary>/// <returns></returns>private static IJwtDecoder GetDecoder(){IJsonSerializer serializer = new JsonNetSerializer();IDateTimeProvider provider = new UtcDateTimeProvider();IJwtValidator validator = new JwtValidator(serializer, provider);IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();IJwtAlgorithm algorithm = new HMACSHA256Algorithm();IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);return decoder;}/// <summary>/// 加密/// </summary>public static string Encode(object payload){var encoder = GetEncoder();var token = encoder.Encode(payload, JwtKey);return token;}/// <summary>/// 解密/// </summary>public static T Decode<T>(string token){var decoder = GetDecoder();var data = decoder.Decode(token, JwtKey);var res = JsonConvert.DeserializeObject<T>(data);return res;}/// <summary>/// 解密,只返回Json文本/// </summary>/// <param name="token"></param>/// <returns></returns>public static string Decode(string token){var decoder = GetDecoder();var data = decoder.Decode(token, JwtKey);return data;}}

把中间的加密算法替换成helper的Encode

   var token = JwtHelper.Encode(Info);

7.添加token加密类

调用Decode方法 解密token

8.测试JWT

{"isOk":true,"code":1,"msg":"登录成功!","rsData":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySWQiOiJhZG1pbiIsIkV4cGlyZXMiOiIyMDI0LTA0LTEwVDAxOjUxOjUwLjk5NDgxNzQrMDA6MDAifQ.eYJovquJFezVhfdLp-Hro2vnMoQsUwgXLkYcZSYEy7U"}

测试解密

解密成功

⭐️JwtBearer

9、添加NuGet包Microsoft.AspNetCore.Authentication.JwtBearer

10、在appsettings.json中添加JWT配置节点

  "JWT": {"SecKey": "im6666666!#@$%@%^^&*(~Czmjklneafguvioszb%yuv&*6WVDf5dw#5dfw6f5w6faW%FW^f5wa65f^AWf56", //密钥"Issuer": "im666", //发行者"ExpireSeconds": 7200 //过期时间 2h},

11.添加jwt类

using Microsoft.IdentityModel.Tokens;using System.Diagnostics;using System.IdentityModel.Tokens.Jwt;using System.Security.Claims;using System.Text;namespace webapijwttest.Models
{/// <summary>/// 授权JWT类/// </summary>public class JwtHelper2{private readonly IConfiguration _configuration;/// <summary>/// Token配置/// </summary>/// <param name="configuration"></param>public JwtHelper2(IConfiguration configuration){_configuration = configuration;}/// <summary>/// 创建Token 这里面可以保存自己想要的信息/// </summary>/// <param name="username"></param>/// <param name="mobile"></param>/// <returns></returns>public string CreateToken(string username, string mobile){try{// 1. 定义需要使用到的Claimsvar claims = new[]{new Claim("username", username),new Claim("mobile", mobile),/* 可以保存自己想要信息,传参进来即可new Claim("sex", "sex"),new Claim("limit", "limit"),new Claim("head_url", "xxxxx")*/};// 2. 从 appsettings.json 中读取SecretKeyvar secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecKey"]));// 3. 选择加密算法var algorithm = SecurityAlgorithms.HmacSha256;// 4. 生成Credentialsvar signingCredentials = new SigningCredentials(secretKey, algorithm);// 5. 根据以上,生成tokenvar jwtSecurityToken = new JwtSecurityToken(_configuration["Jwt:Issuer"],    //Issuer_configuration["Jwt:ExpireSeconds"],  //ExpireSecondsclaims,                          //Claims,DateTime.Now,                    //notBeforeDateTime.Now.AddSeconds(30),     //expiressigningCredentials               //Credentials);// 6. 将token变为stringvar token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);return token;}catch (Exception){throw;}}/// <summary>/// 获取信息/// </summary>/// <param name="jwt"></param>/// <returns></returns>public static string ReaderToken(string jwt){var str = string.Empty;try{//获取Token的三种方式//第一种直接用JwtSecurityTokenHandler提供的read方法var jwtHander = new JwtSecurityTokenHandler();JwtSecurityToken jwtSecurityToken = jwtHander.ReadJwtToken(jwt);str = jwtSecurityToken.ToString();}catch (Exception ex){Debug.WriteLine(ex.Message);}return str;}/// <summary>/// 解密jwt/// </summary>/// <param name="jwt"></param>/// <returns></returns>public string JwtDecrypt(string jwt){StringBuilder sb = new StringBuilder();try{JwtSecurityTokenHandler tokenHandler = new();TokenValidationParameters valParam = new();var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecKey"]));valParam.IssuerSigningKey = securityKey;valParam.ValidateIssuer = false;valParam.ValidateAudience = false;//解密ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(jwt,valParam, out SecurityToken secToken);foreach (var claim in claimsPrincipal.Claims){sb.Append($"{claim.Type}={claim.Value}");}}catch (Exception ex){Debug.WriteLine(ex.Message);}return sb.ToString();}}
}

12.Program.cs注册JWT服务

#region JWT服务
// 注册JWT服务
builder.Services.AddSingleton(new JwtHelper2(builder.Configuration));
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{options.TokenValidationParameters = new TokenValidationParameters(){ValidateIssuer = true, //是否验证IssuerValidIssuer = builder.Configuration["Jwt:Issuer"], //发行人IssuerValidateAudience = false, //是否验证Audience      ValidateIssuerSigningKey = true, //是否验证SecurityKeyIssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecKey"])), //SecurityKeyValidateLifetime = true, //是否验证失效时间ClockSkew = TimeSpan.FromSeconds(30), //过期时间容错值,解决服务器端时间不同步问题(秒)RequireExpirationTime = true,};
}
);
#endregion

添加swagger authorization


builder.Services.AddSwaggerGen(c =>
{c.SwaggerDoc("v1", new OpenApiInfo { Title = "Web API", Version = "v1" });//开启注释var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);//需要 生成 目录生成XMLc.IncludeXmlComments(xmlPath, true);// 配置 JWT Bearer 授权c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme{Description = "JWT Authorization header using the Bearer scheme",Name = "Authorization",In = ParameterLocation.Header,Type = SecuritySchemeType.Http,Scheme = "bearer"});var securityScheme = new OpenApiSecurityScheme{Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }};var securityRequirement = new OpenApiSecurityRequirement { { securityScheme, new string[] { } } };c.AddSecurityRequirement(securityRequirement);});var app = builder.Build();//启用验证中间件
app.UseAuthentication();
app.UseAuthorization();

13.添加jwt测试api

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity.Data;
using Microsoft.AspNetCore.Mvc;
using webapijwttest.Models;// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860namespace webapijwttest.Controllers
{[Route("api/[controller]/[action]")][ApiController]public class Jwt2Controller : ControllerBase{private readonly JwtHelper2 _jwt;/// <summary>/// 初始化/// </summary>/// <param name="jwtHelper"></param>public Jwt2Controller(JwtHelper2 jwtHelper){_jwt = jwtHelper;}/// <summary>/// 获取Token/// </summary>/// <returns></returns>[HttpPost]public IActionResult GetToken(LoginRs user){//参数验证等等....if (string.IsNullOrEmpty(user.UserId)){return Ok("参数异常!");}//这里可以连接mysql数据库做账号密码验证//这里可以做Redis缓存验证等等//这里获取Token,当然,这里也可以选择传结构体过去var token = _jwt.CreateToken(user.UserId, user.PasswordMD5);//解密后的Tokenvar PWToken = _jwt.JwtDecrypt(token);return Ok(token + "解密后:" + PWToken);}/// <summary>/// 获取自己的详细信息,其中 [Authorize] 就表示要带Token才行/// </summary>/// <returns></returns>[HttpPost][Authorize]public IActionResult GetSelfInfo(){//执行到这里,就表示已经验证授权通过了/** 这里返回个人信息有两种方式* 第一种:从Header中的Token信息反向解析出用户账号,再从数据库中查找返回* 第二种:从Header中的Token信息反向解析出用户账号信息直接返回,当然,在前面创建        Token时,要保存进使用到的Claims中。*/return Ok("授权通过了!");}}
}

调用

检测控制器

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using webapijwttest.Models;// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860namespace webapijwttest.Controllers
{[Route("api/[controller]")][ApiController]public class AuthController : ControllerBase{private ILogger<AuthController> _logger = null;private JwtHelper2 _iJWTService = null;private readonly IConfiguration _configuration;public AuthController(ILogger<AuthController> logger, JwtHelper2 jWTService, IConfiguration configuration){this._logger = logger;_iJWTService = jWTService;_configuration = configuration;}[Route("Get")][HttpGet]public IEnumerable<int> Get(){//未加授权认证return new List<int>() { 1, 3, 5, 7, 9 };}[Route("GetData")][HttpGet][Authorize]public List<object> GetData(){//添加了授权认证,需要使用tokenreturn new List<object>() { new { userName = "123", remark = "1234" } };}[Route("Login")][HttpGet]public string Login(string name, string password){if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(password)){string token = this._iJWTService.CreateToken(name,password);return JsonConvert.SerializeObject(new { result = true, token });}else{return JsonConvert.SerializeObject(new { result = false, token = "" });}}}
}

调用

把token放进 

测试GetData

当超过时间调用则GetData失败

END🐟🐟🐟

这篇关于.NET JWT入坑的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/899618

相关文章

.NET利用C#字节流动态操作Excel文件

《.NET利用C#字节流动态操作Excel文件》在.NET开发中,通过字节流动态操作Excel文件提供了一种高效且灵活的方式处理数据,本文将演示如何在.NET平台使用C#通过字节流创建,读取,编辑及保... 目录用C#创建并保存Excel工作簿为字节流用C#通过字节流直接读取Excel文件数据用C#通过字节

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

2、PF-Net点云补全

2、PF-Net 点云补全 PF-Net论文链接:PF-Net PF-Net (Point Fractal Network for 3D Point Cloud Completion)是一种专门为三维点云补全设计的深度学习模型。点云补全实际上和图片补全是一个逻辑,都是采用GAN模型的思想来进行补全,在图片补全中,将部分像素点删除并且标记,然后卷积特征提取预测、判别器判别,来训练模型,生成的像

.NET 自定义过滤器 - ActionFilterAttribute

这个代码片段定义了一个自定义的 ASP.NET Core 过滤器(GuardModelStateAttribute),用于在控制器动作执行之前验证模型状态(ModelState)。如果模型状态无效,则构造一个 ProblemDetails 对象来描述错误,并返回一个 BadRequest 响应。 代码片段: /// <summary>/// 验证 ModelState 是否有效/// </

.Net Mvc-导出PDF-思路方案

效果图: 导语:     在我们做项目的过程中,经常会遇到一些服务性的需求,感到特别困扰,明明实用的价值不高,但是还是得实现;     因此小客在这里整理一下自己导出PDF的一些思路,供大家参考。     网上有很多导出PDF运用到的插件,大家也可以看看其他插件的使用,学习学习; 提要:     这里我使用的是-iTextSharp,供大家参考参考,借鉴方案,完善思路,补充自己,一起学习

.net MVC 导出Word--思路详解

序言:          一般在项目的开发过程中,总会接收到一个个需求,其中将数据转换成Work来下载,是一个很常见的需求;          那么,我们改如何处理这种需求,并输出实现呢?          在做的过程中,去思考 1、第一步:首先确认,Work的存在位置,并创建字符输出路:             //在的项目中创建一个存储work的文件夹             string

asp.net 中GridView的使用方法

可以看看,学习学习 https://blog.csdn.net/zou15093087438/article/details/79637042

ASP.NET状态管理的总结

由于HTTP协议的无状态特性,导致在ASP.NET编程中,每个请求都会在服务端从头到执行一次管线过程, 对于ASP.NET页面来说,Page对象都会重新创建,所有控件以及内容都会重新生成, 因此,如果希望上一次的页面状态能够在后续页面中保留,则必需引入状态管理功能。   ASP.NET为了实现状态管理功能,提供了8种方法,可帮助我们在页面之间或者整个用户会话期间保留状态数据。 这些方法分为二类:

ASP.NET手动触发页面验证控件事件

开发环境:.NET Framework 3.5.1 sp1 参考文章: http://www.codeproject.com/KB/aspnet/JavascriptValidation.aspx http://msdn.microsoft.com/zh-cn/library/aa479045.aspx http://www.cnblogs.com/minsentinel/archive/