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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/812317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机组成原理总结(笔记)

计算机组成原理总结 第一章 计算机系统概论 第二章 计算机的发展及应用 第三章 系统总线 第四章 存储器 第五章 输入输出系统 第六章 计算机的运算方法 第七章 指令系统 第八章 CPU 的结构与功能 第九章 控制单元的功能 第十章 控制单元的设计

SQLite 在Android安装与定制方案(十七)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite超详细的编译时选项&#xff08;十六&#xff09; 下一篇&#xff1a;SQLite Android 绑定&#xff08;十八&#xff09; 安装 有三种方法可以将 SQLite Android 绑定添加到应用程序&#xff1a; 1、通过…

探索Python库的奇妙世界

探索Python库的奇妙世界 Python作为一种流行的编程语言&#xff0c;因其简洁的语法、强大的库支持和广泛的应用场景而备受开发者青睐。在这篇文章中&#xff0c;我们将深入探讨Python库的世界&#xff0c;了解它们如何帮助我们更高效地编写代码&#xff0c;并展示一些最有用的…

C++的stack和queue类(三):适配所有容器的反向迭代器

目录 前言 list的反向迭代器 list.h文件 ReverseIterator.h文件 test.cpp文件 前言 迭代器按性质分类&#xff1a; 单向&#xff1a;forward_list双向&#xff1a;list随机&#xff1a;vector / deque 迭代器按功能分类&#xff1a; 正向反向const list的反向迭代器…

深入理解Apache ZooKeeper与Kafka的协同工作原理

目录 引言 一、ZooKeeper基础概念 &#xff08;一&#xff09;ZooKeeper简介 &#xff08;二&#xff09;ZooKeeper数据结构 &#xff08;三&#xff09;ZooKeeper特点 &#xff08;四&#xff09;应用场景 二、ZooKeeper工作模式 &#xff08;一&#xff09;工作机制 …

请求分发场景下的鉴权问题

说明&#xff1a;记录一次对请求分发&#xff0c;无法登录系统的问题。 场景 如下&#xff0c;在此结构下&#xff0c;如何判断该用户是已登录的用户&#xff1b; 常规操作&#xff0c;用户登录后给用户发Token&#xff0c;同时将发放的Token存入到Redis中。要求用户后续请求…

在 Vue 3 中使用 Axios 发送 POST 请求

在 Vue 3 中使用 Axios 发送 POST 请求需要首先安装 Axios&#xff0c;然后在 Vue 组件或 Vuex 中使用它。以下是一个简单的安装和使用案例&#xff1a; 安装 Axios 你可以使用 npm 或 yarn 来安装 Axios&#xff1a; npm install axios # 或者 yarn add axios 使用 Axios…

架构设计-订单系统之订单系统的架构进化

1、单数据库架构 产品初期&#xff0c;技术团队的核心目标是&#xff1a;“快速实现产品需求&#xff0c;尽早对外提供服务”。 彼时的专车服务都连同一个 SQLServer 数据库&#xff0c;服务层已经按照业务领域做了一定程度的拆分。 这种架构非常简单&#xff0c;团队可以分开…

单片机方案 发声毛绒小黄鸭

随着科技的不断进步&#xff0c;智能早教已经成为了新时代儿童教育的趋势。智能早教玩具&#xff0c;一款集互动陪伴、启蒙教育、情感培养于一身的高科技产品。它不仅能陪伴孩子成长&#xff0c;还能在游戏中启迪智慧&#xff0c;是家长和孩子的理想选择。 酷得电子方案开发特…

股票价格预测 | Python使用GRU预测股票价格

文章目录 效果一览文章概述代码设计效果一览 文章概述 Python使用GRU预测股票价格 代码设计 import pandas as pd import matplotlib.pyplot as plt import numpy as np import tensorflow as tf from numpy

Python 正则表达式模块使用

目录 1、匹配单个字符 2、匹配多个字符 3、匹配开头结尾 4、匹配分组 说明&#xff1a;在Python中需要通过正则表达式对字符串进行匹配的时候&#xff0c;可以使用re模块 表达式&#xff1a;re.match(正则表达式&#xff0c; 要匹配的字符串) 有返回值说明匹配成功&#x…

13-pyspark的共享变量用法总结

目录 前言广播变量广播变量的作用 广播变量的使用方式 累加器累加器的作用累加器的优缺点累加器的使用方式 PySpark实战笔记系列第四篇 10-用PySpark建立第一个Spark RDD(PySpark实战笔记系列第一篇)11-pyspark的RDD的变换与动作算子总结(PySpark实战笔记系列第二篇))12-pysp…

Springboot+Vue项目-基于Java+MySQL的课程作业管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

秀米、135、蚂蚁编辑器如何为推文添加附件

秀米、135、蚂蚁编辑器作为第三方的公众号图文排版工具&#xff0c;给从事运营和编辑工作的同学提供了更多的排版选择。不同于公众号自家的编辑器&#xff0c;这些第三方编辑器脱离了微信的直接支持&#xff0c;在很多排版操作上&#xff0c;还是有很多操作不一样的地方。 公众…

通过 Vue 3 组合式 API 优化 Uni-app 基础页面功能

Uni-app 是一个跨平台的应用开发框架&#xff0c;支持同时开发小程序、App 和 H5 等多个平台。而 Vue 3 的组合式 API 则是 Vue 3 新增的特性之一&#xff0c;它可以让我们更好地组织和复用组件逻辑。本文将结合 Vue 3 的组合式 API&#xff0c;来优化 Uni-app 中基础页面的功能…

自动化运维(二十三)Ansible 实战动态库存插件和回调插件

Ansible 支持多种类型的插件&#xff0c;这些插件可以帮助你扩展和定制 Ansible 的功能。每种插件类型都有其特定的用途和应用场景。今天我们一起学习动态库存插件和回调插件。 一、动态库存插件 Ansible 动态库存插件允许从各种外部数据源动态获取库存信息&#xff0c;包括主…

AndroidAutomotive模块介绍(一)整体介绍

前言 Android Automotive 是一个基本 Android 平台&#xff0c;可运行 IVI 系统中预安装的 Android 应用以及可选的第二方和第三方 Android 应用。 本系列文档将会系统的介绍 Android Automotive 的功能、架构、逻辑等。模块逻辑将从 应用api接口、系统服务、底层服务&#x…

软件设计师:11-结构化开发与UML

结构化开发&#xff08;3-4分&#xff09; 一、模块化 二、耦合&#xff08;背&#xff09; 三、内聚&#xff08;背&#xff09; 四、设计原则&#xff08;背&#xff09; 五、系统文档 六、数据流图 数据流的起点或终点必须有一个是加工 判断依据&#xff1a; 1、…

Vivado Design Suite中route_design命令脚本示例

本文详细介绍了四个route_design命令的示例脚本&#xff0c;这些脚本需要添加到工程的约束文件.xdc中&#xff0c;结果保存在工程文件中的runs\impl_1中的runme.log文件。 一、示例脚本1 route_design write_checkpoint -force $outputDir/post_route report_timing_summary …

img使用 :src 动态绑定图片地址,图片不成功

使用vue cli 创建的vue2项目&#xff0c;项目中想实现轮播效果。 出现的问题&#xff1a; 使用 :src 动态绑定图片地址&#xff0c;图片没有出现 <el-carousel :interval"3000" arrow"always"><el-carousel-item v-for"(item,index) in sw…