.NET JWT入坑

embedded/2024/9/23 11:19:58/

目录

✨ 建立项目jwttest

1.创建TestJwtController

2.下载JWT 

3.建实体类

4.添加post login

5.登录验证

6.测试没问题,写个JwtHelper

7.添加token加密类

8.测试JWT

⭐️JwtBearer

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

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

11.添加jwt类

12.Program.cs注册JWT服务

13.添加jwt测试api


前言

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🐟🐟🐟


http://www.ppmy.cn/embedded/4317.html

相关文章

Elasticsearch(2)

目录 121.ES查询中match和term的区别? 122.Es查询中should和must的区别? 123.ES查询中match,match_phrase和match_phase_prefix有什么区别? 124.ES查询中什么是复合查询?有哪些复合查询方式?

Rust常见陷阱 | 线程间传递消息导致主线程无法结束

在多线程编程中,线程之间的通信是一个不可或缺的话题。尤其是在Rust语言中,由于其特有的所有权机制,线程通信需要更加仔细地处理。本文将深入讨论使用Rust标准库中的消息通道时如何避免主线程被阻塞的问题,并提供详尽的代码示例来辅助理解。 问题描述 当我们在Rust中使用…

基于springboot实现教学辅助平台系统项目【项目源码+论文说明】

基于springboot实现教学辅助平台系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了教学辅助平台的开发全过程。通过分析教学辅助平台管理的不足&#xff0c;创建了一个计算机管理教学辅助平台的方案。文…

有没有批量调节音乐播放速度的方法?调节音频的播放速度

一&#xff0c;引言​ 调节音乐播放的速度是一种有趣而富有创造性的方式&#xff0c;可以改变我们对音乐的感知和体验。通过调整音乐的速度&#xff0c;我们可以创造出全新的听觉效果&#xff0c;让音乐呈现出不同的情感和氛围。二&#xff0c;调节音乐速度的效果 调节音乐速…

【C++】哈希结构

目录 一&#xff0c;哈希结构的认识 1-1&#xff0c;哈希思想 1-2&#xff0c;哈希函数 1-3&#xff0c;哈希冲突 1-3-1&#xff0c;闭散列 1-3-2&#xff0c;开散列 二&#xff0c;哈希结构的封装实现 2-1&#xff0c;闭散列封装实现 ​编辑 2-2&#xff0c;开散列封…

QQ怎么远程控制自己的电脑

QQ怎么远程控制自己的电脑 在日常生活和工作中&#xff0c;我们有时可能需要在不同的地点远程控制自己的电脑。QQ作为一款广受欢迎的即时通讯软件&#xff0c;提供了远程桌面功能&#xff0c;使得用户可以轻松实现对自己电脑的远程控制。下面就来介绍一下如何使用QQ远程控制自…

CentOS 7 文件权限管理详解

CentOS 7 文件权限管理详解 在 CentOS 7 系统中,文件权限管理是一项至关重要的任务,它确保了系统安全、数据完整性和用户隐私。本文将详细介绍 CentOS 7 中的文件权限管理,包括相关文件和命令的使用。 一、文件权限基础 在 Linux 系统中,每个文件和目录都有与之关联的权…

AVM 环视拼接方法介绍

0. 简介 关于车辆的全景环视系统网上已经有很多的资料&#xff0c;然而几乎没有可供参考的代码&#xff0c;这一点对入门的新人来说非常不友好。全景环视系统&#xff0c;又称AVM。在自动驾驶领域&#xff0c;AVM属于自动泊车系统的一部分&#xff0c;是一种实用性极高、可大幅…