session 共享、Nginx session 共享、Token、Json web Token 【JWT】等认证

.NET JWT

JWT 》》Json Web Token
header . payload . Signature 三部分组成
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

JWT 在线生成

》》 https://jwt.io/
》》https://tooltt.com/jwt-encode/

》》解码工具

https://tool.box3.cn/jwt.html

在这里插入图片描述

JWT 特点

  1. 无状态
    JWT不需要在服务端存储任何状态,客户端可以携带JWT来访问服务端,从而使服务端变得无状态。
    这样,服务端可以更轻松实现扩展(分布式扩展)和负载均衡
  2. 可自定义
    JWT的载荷payload 有标准载荷和自定义载荷。可以存储任何JSON格式的数据。
  3. 扩展性强
    JWT 有一套标准规范,因此很容易在不同平台和语言之间共享和解析。此外,开发人员可以更加需要自定义声明Claims。
    标准载荷和自定义载荷
  4. 调试性好
    JWT 的内容是以Base64编码的字符串形式存在的。
  5. 安全性取决于密钥管理
    JWT的安全性却决于密钥的管理。密钥只要服务端才知道的,客户端是不能知道的。
  6. 无法撤销
    JWT是无状态的,一旦JWT签发,就无法撤销。
    如果用户在使用JWT认证期间被注销或禁用,那么服务端就无法阻止改用户继续使用之前的签发的JWT,因此,开发人员需要设计额外的
    机制来撤销JWT,例如通过使用黑名单,这就使JWT不是无状态了。跟传统的Session差不多了。
  7. 需要缓存到客户端
    JWT包含了用户信息和授权信息,一般需要客户端缓存,这意味着JWT有被窃取的风险。
  8. 载荷大小有限制
    JWT是服务端签发,传输到客户端的,因此载荷大小也有限制的。一般不建议载荷超过1KB,会影响性能

JWT优缺点

》》》 优点

  1. 无状态: JWT本身不需要存储在服务器上,因为可以实现无状态的身份验证和授权
  2. 可扩展性:JWT载荷可以自定义,因此可以根据需要添加任意信息,推荐不要添加敏感信息
  3. 可靠性:JWT使用数字签名来保证安全性,因此具有可靠性
  4. 跨平台性:JWT支持多种编码语言和操作系统,因此具有跨平台性
  5. 高效性:JWT不需要查询数据库【首次需要的,之后请求就不需要了】,因此具有高效性。
    》》》缺点
  6. 安全性却决于密钥的管理。如果密钥被泄露或者被不当管理,那么JWT将会受到攻击
  7. 无法撤销,因为jwt是无状态的,一旦签发,就无法撤销
  8. 需要传输到客户端,由于jwt包含用户信息和授权信息,jwt传输到客户端,存在被窃取的风险
  9. 载荷大小有限
JWT应用场景

》》1 一次性验证
用户注册成功后发一份激活邮件或者其它业务需要邮箱激活操作,都可以使用JWT
原因:
JWT时效性:让该链接具有时效性(比如 30分钟内激活)
JWT不可纂改性(密钥在服务端):防止纂改以激活其它账户
》》2 RESTful api 的无状态认证
使用JWT做RestFul api 的身份凭证: 当用户身份校验成功,客户端每次接口访问带上JWT,服务端校验JWT合法性(是否过期、篡改等)

》》3 信息交换
JWT是在各方(项目间、服务间)之间安全传输信息的方式。因为JWT可以签名:例如使用公钥、私钥,所以可以确定发件人是他们自己的人,此外,由于使用标头和有效载荷计算签名,因此可以验证内容是否被篡改

》》 4 JWT令牌登录
JWT令牌登录也是一种应用场景,但也是JWT被诟病最多的地方,因为JWT令牌存在各种不安全。
>1. JWT令牌存储在客户端,容易被泄露并被伪造身份搞破坏
>2. JWT被签发,就无法撤销,当破坏在进行时,后端无法马上禁止
上面问题可通过监控异常JWT访问,设置黑名单+强制下线等方式尽量避免损失

JWT使用注意点

》》1. Redis校验实现令牌泄露保护
JWT无状态的,当JWT令牌被签发,在有效时间内,是无法进行撤销、销毁,所以就存在很多隐患:令牌泄露

  》》 解决方案:颁发JWT令牌时,在Redis中也存缓存一份,当判定某个JWT泄露了,立即移除Redis中的JWT。当接口发起请求时,强制用户重新进行身份验证,直到验证成功。

》》2 林检JWT限制敏感操作
JWT无状态性,同时泄露可能很大,一些涉及到敏感数据变动,执行临检操作

 》》 解决方案:在涉及到诸如新增、、修改、删除、上传、下载等敏感性操作时,强制检查用户身份,比如手机验证码,人脸识别等

》》3异常JWT监控:超频识别与限制
JWT令牌被盗取,一般会出现高频次的系统访问。针对这种情况,监控用户在单位时间内的请求次数,当单位时间内的请求次数超出预定阀值,则判断该用户JWT令牌异常

  》》 解决方案:当判断JWT令牌异常,直接进行限制(IP限流、JWT黑名单等)

》》4地域检查杜绝JWT泄露可能
一般用户活动范围是固定,意味着JWT客户端访问IP相对固定,JWT泄露之后,可能会异地登录的情况

 》》 解决方案:对JWT进行异地访问检查,有效时间内,IP频繁变动判断JWT泄露

》》5 客户端区分检查防止JWT泄露
对于APP产品来说,一般客户端是固定的,基本为移动设备(app、平板),可以结婚设备机器码进行绑定

  》》 解决方案:将JWT于机器码绑定,存储于服务端,当客户端发起请求时,通过检查客户端的机器码与服务端机器码是否匹配判断JWT是否泄露

》》6 JWT令牌保护 限时、限数、限频
JWT令牌泄露是无法避免,但是我们可以进行泄露识别,做好泄露后补救保证系统安全

 》》 解决方案:对客户端进行合理限制,比如限制每个客户端的JWT令牌数量、访问频率、JWT令牌时效等,以降低JWT令牌泄露的风险

客户端将 JWT保存到本地(通常使用 webstorage【localstorage、Sessionstorage】,也可以使用 cookie【但不能跨域】)
在这里插入图片描述

当用户希望访问一个受保护的路由或者资源的时候,
可以把它放在 Cookie 里面自动发送,但是这样不能跨域,
所以更好的做法是放在 HTTP 请求头信息的 Authorization 字段里,使用 Bearer 模式添加 JWT。

在这里插入图片描述

1、安装 System.IdentityModel.Tokens.Jwt
jwt 是服务器签发 给客户端的,服务器不保存任何信息,所以服务端的密钥要 不能泄露。
在这里插入图片描述
在这里插入图片描述

 // 设置JWT的密钥string secretKey = "wedfs5656456456456456hjghjghjgjgzen-token7897";byte[] keyBytes = Encoding.UTF8.GetBytes(secretKey);var securityKey = new SymmetricSecurityKey(keyBytes);// 创建JWT的签名凭证var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);// 设置JWT的Claimsvar claims = new[]{new Claim(“User_id”, "Ares-Wang"),new Claim(ClaimTypes.Email, "123@163.com"),// 添加其他需要的声明};// 创建JWT的Tokenvar token = new JwtSecurityToken(issuer: "your_issuer",audience: "your_audience",claims: claims,expires: DateTime.Now.AddDays(1),signingCredentials: signingCredentials);// 生成JWT字符串var jwtToken = new JwtSecurityTokenHandler().WriteToken(token);Response.Write(jwtToken);
/// <summary>/// 根据token反向解析/// </summary>/// <param name="token"></param>/// <returns></returns>public string GetInfoFromToken(string token = null){if (token is null || token == "")return null;string tokenStr = token.Replace("Bearer ", "");var handler = new JwtSecurityTokenHandler();// string tokenStr = token;var payload = handler.ReadJwtToken(tokenStr).Payload;var claims = payload.Claims;var userid = claims.First(claim => claim.Type == "User_id")?.Value;return userid;}/// <summary>/// 从Token中获取用户身份/// </summary>/// <param name="token"></param>/// <param name="securityKey">securityKey明文,Java加密使用的是Base64</param>/// <returns></returns>public ClaimsPrincipal GetPrincipal(string token){try{string securityKey = SecretKey;token = token.Replace("Bearer ", "");var handler = new JwtSecurityTokenHandler();TokenValidationParameters tokenValidationParameters = new TokenValidationParameters{ValidateAudience = false,ValidateIssuer = false,ValidateIssuerSigningKey = true,IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey)),ValidateLifetime = false};return handler.ValidateToken(token, tokenValidationParameters, out SecurityToken validatedToken);}catch (Exception ex){return null;}}/// <summary>/// 校验Token/// </summary>/// <param name="token">token</param>/// <returns></returns>public bool CheckToken(string token){var principal = GetPrincipal(token);if (principal is null){return false;}return true;}

在这里插入图片描述
在这里插入图片描述
有关于jwt生成和验证token的操作全部记录在jwthelper.cs文件中

/// <summary>
/// 授权JWT类
/// </summary>
public class JwtHelper
{public readonly string SecretKey = System.Configuration.ConfigurationManager.AppSettings["SecretKey"];public readonly string AppId = System.Configuration.ConfigurationManager.AppSettings["AppId"];public readonly string AppKey = System.Configuration.ConfigurationManager.AppSettings["AppKey"];/// <summary>/// 创建Token 这里面可以保存自己想要的信息/// </summary>/// <param name="user_id"></param>/// <param name="mobile"></param>/// <returns></returns>public string CreateToken(string user_id){// 1. 定义需要使用到的Claimsvar claims = new Claim[]{new Claim("user_id", user_id),           /* 可以保存自己想要信息,传参进来即可          new Claim("limit", "limit"),           */};// 2. 从 appsettings.json 中读取SecretKeyvar secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecretKey));// 3. 选择加密算法var algorithm = SecurityAlgorithms.HmacSha256;// 4. 生成Credentialsvar signingCredentials = new SigningCredentials(secretKey, algorithm);// 5. 根据以上,生成tokenvar jwtSecurityToken = new JwtSecurityToken(issuer: AppId,    //Issueraudience: AppKey,  //Audienceclaims: claims,                          //Claims,notBefore: DateTime.Now,                    //notBeforeexpires: DateTime.Now.AddHours(1),     //expiressigningCredentials: signingCredentials               //Credentials);// 6. 将token变为stringvar token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);return token;}/// <summary>/// 根据token反向解析/// </summary>/// <param name="token"></param>/// <returns></returns>public string GetInfoFromToken(string token = null){if (token is null || token == "")return null;string tokenStr = token.Replace("Bearer ", "");var handler = new JwtSecurityTokenHandler();// string tokenStr = token;var payload = handler.ReadJwtToken(tokenStr).Payload;var claims = payload.Claims;var userid = claims.First(claim => claim.Type == "user_id")?.Value;return userid;}/// <summary>/// 从Token中获取用户身份/// </summary>/// <param name="token"></param>/// <param name="securityKey">securityKey明文,Java加密使用的是Base64</param>/// <returns></returns>public ClaimsPrincipal GetPrincipal(string token){try{string securityKey = SecretKey;token = token.Replace("Bearer ", "");var handler = new JwtSecurityTokenHandler();TokenValidationParameters tokenValidationParameters = new TokenValidationParameters{ValidateAudience = false,ValidateIssuer = false,ValidateIssuerSigningKey = true,IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey)),ValidateLifetime = false};return handler.ValidateToken(token, tokenValidationParameters, out SecurityToken validatedToken);}catch (Exception ex){return null;}}/// <summary>/// 校验Token/// </summary>/// <param name="token">token</param>/// <returns></returns>public bool CheckToken(string token){var principal = GetPrincipal(token);if (principal is null){return false;}return true;}

参考资料

》》ActionFilterAttribute 在Action执行前 触发OnActionExecuting 执行后 OnActionExecuted

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;namespace WebApplication11
{public class CustomActionFilteAttribute:ActionFilterAttribute{public readonly string SecretKey = System.Configuration.ConfigurationManager.AppSettings["SecretKey"];public readonly string AppId = System.Configuration.ConfigurationManager.AppSettings["AppId"];public readonly string AppKey = System.Configuration.ConfigurationManager.AppSettings["AppKey"];public override void OnActionExecuting(HttpActionContext actionContext){Jwt.JwtHelper _jwt = new Jwt.JwtHelper();var token = "";if (actionContext.HttpContext.Request.Headers.AllKeys.Contains("Authorization")){int index = actionContext.HttpContext.Request.Headers.AllKeys.Select((a, i) => i).Where(i => actionContext.HttpContext.Request.Headers.AllKeys[i] == "Authorization").FirstOrDefault();token = actionContext.HttpContext.Request.Headers[index];}if (token == null || token == ""){var Auth = new{Status = 401,Message = "身份验证失败"};actionContext.Result = new ContentResult{ContentType = "application/json",Content = JsonConvert.SerializeObject(Auth)};return;}bool isOK = _jwt.CheckToken(token);if (!isOK){var Auth = new{Status = 401,Message = "身份验证失败"};actionContext.Result = new ContentResult{ContentType = "application/json",Content = JsonConvert.SerializeObject(Auth)}; return;}var userid = _jwt.GetInfoFromToken(token);base.OnActionExecuting(actionContext);base.OnActionExecuting(actionContext);}public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext){//在这里可以解决跨越问题base.OnActionExecuted(actionExecutedContext);}}
}

》》JWT 一般是放在 header 的 Authorization 自定义头里
JWT支持跨域访问,cookie不支持, Cookie 跨站是不能共享的,这样的话如果你要实现多应用(多系统)的单点登录(SSO),使用 Cookie 来做需要的话就很困难了。但如果用 token 来实现 SSO 会非常简单,只要在 header 中的 Authorization 字段(或其他自定义)加上 jwt即可完成所有跨域站点的认证。
JWT是无状态的,可以在多个服务器间共享
JWT可以避免CSRF攻击(跨站请求攻击)
JWT易与扩展,在移动端原生请求、小程序等请求 是没有Cookie的,而Session也是依赖于cookie。JWT是默认随着Header中的Authorize 传过来的。所以JWT天生就支持移动平台、可扩展性好

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

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

相关文章

【FFMPEG+Mediamtx】 本地RTSP测试推流记录

利用本地FFMPEGMediamtx 搭建本地RTSP测试推流电脑摄像头 起因 本来要用qt的qml的Video做摄像头测试。 &#x1f614;但是&#xff0c;不在现场&#xff0c;本地测试&#xff0c;又要测试rtsp流&#xff0c;又因为搜了一圈找不到一个比较好的在线测试rtsp推流网址&#x1f6…

自从用了这个 69k star 的项目,前端小姐姐再也不催我了

一般在开发前后端分离的项目时&#xff0c;双方会定义好前后端交互的 http 接口&#xff0c;根据接口文档各自进行开发。这样并行开发互不耽误&#xff0c;开发好后做个联调就可以提测了。 不过最近也不知道怎么回事&#xff0c;公司新来的前端小姐姐总是在刚开始开发的时候就…

全行业通用商城小程序源码

一站式购物新体验 一、引言&#xff1a;开启数字化购物新时代 在数字化快速发展的今天&#xff0c;小程序成为了商家们连接消费者的重要桥梁。特别是“全行业通用商城小程序”&#xff0c;以其便捷的购物体验和多样化的功能&#xff0c;成为了越来越多商家和消费者的首选。本…

嵌入式STM32F103项目实例可以按照以下步骤进行构建和实现

嵌入式STM32F103项目实例可以按照以下步骤进行构建和实现&#xff1a; 1. 项目概述 目标&#xff1a;演示STM32F103开发板的基本功能&#xff0c;通过LED闪烁来实现。硬件需求&#xff1a;STM32F103开发板、LED灯、杜邦线、USB转串口模块&#xff08;可选&#xff0c;用于调试…

Day12 单调栈 下一个最大元素

503. 下一个更大元素 II 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更大的数…

[AIGC] 动态规划的类型以及在 LeetCode 上的应用

动态规划是一种解决问题的优秀策略&#xff0c;它适用于涉及优化问题、组合问题及最短路径问题等领域。下面我们来探究几类常见的动态规划问题&#xff0c;并提供相应的 LeetCode 题目以及 Java 代码实现。 文章目录 1. 一维动态规划2. 二维动态规划3. 背包型动态规划 1. 一维动…

Unity URP简单烘焙场景步骤

Unity URP简单烘焙场景步骤 前言项目场景布置灯光模型Lighting设置环境设置烘焙前烘焙后增加角色 问题解决黑斑硬边清理缓存 参考 前言 项目中要烘焙一个3D场景&#xff0c;用的URP渲染管线&#xff0c;简单记录一下。 项目 场景布置 灯光 因为场景中有能动的东西&#xf…

JAVA每日作业day6.24

ok了家人们今天学习了一些关键字&#xff0c;用法和注意事项&#xff0c;静态代码块这些知识&#xff0c;闲话少叙我们一起看看吧。 一&#xff0c;final关键字 1.1 final关键字的概述 final&#xff1a; 不可改变。可以用于修饰类、方法和变量。 类&#xff1a;被修饰的类&a…

GPT-5 一年半后发布?对此你有何期待?

GPT-5的即将发布无疑引发了广泛的关注和讨论。以下是一些对GPT-5潜在影响和应用场景的见解和期待&#xff1a; 1. 提升工作效率 GPT-5可能会在很多领域进一步提升工作效率。其“博士级”智能在特定任务上的表现可以帮助专业人士更快地完成复杂的工作。例如&#xff0c;在法律…

Zoho邮箱怎么注册?最强完整指南

Zoho企业邮箱&#xff0c;凭借其16年的产品历程和卓越的服务品质&#xff0c;已经成为全球超过1800万企业级客户的信赖之选。今天&#xff0c;我们将手把手教你如何注册Zoho邮箱。 一、Zoho邮箱是什么&#xff1f; Zoho邮箱是Zoho Workplace套件中的核心产品&#xff0c;专门…

Java中的正则表达式使用技巧

Java中的正则表达式使用技巧 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天&#xff0c;我们来探讨一下Java中正则表达式的使用技巧。正则表达式是一种强大…

【昇思初学入门】第六天打卡

函数式自动微分 学习心得 反向传播&#xff1a;神经网络在训练时&#xff0c;会使用一个叫做“反向传播”的方法。这个方法的基本思路是这样的&#xff1a;首先&#xff0c;神经网络会做出一个预测&#xff08;我们称之为“logits”&#xff09;&#xff0c;然后我们将这个预…

【Python】已解决ModuleNotFoundError: No module named ‘requests’

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决ModuleNotFoundError: No module named ‘requests’ 一、分析问题背景 在使用Python进行网络编程或数据抓取时&#xff0c;requests库因其简洁易用的特性而受到广泛欢迎。然…

简说caffe

Caffe&#xff08;Convolutional Architecture for Fast Feature Embedding&#xff09;是一个开源的深度学习框架&#xff0c;由加州大学伯克利分校的Berkeley Vision and Learning Center&#xff08;BVLC&#xff09;开发。它主要用于图像分类、分割和图像生成等任务。以下是…

PrestaShop的一些使用介绍

目录 PrestaShop 是一个功能丰富的开源电子商务解决方案。 1. 以下是其基本概念和架构的一些要点&#xff1a; 2. PrestaShop 的模块开发是扩展其功能的重要方式。以下是对 PrestaShop 模块开发的详细介绍&#xff1a; 开发环境准备&#xff1a; 3. PrestaShop 的模块开发允…

Vue项目环境搭建及git仓库新建

不会安装的 可以找下博客&#xff0c;我会在另外一个博客 单独讲解git的安装 接下后启动对应的git bash文件&#xff0c;可以发送快捷方式到桌面 启动git命令的窗口 之后就可以在对应的文件下&#xff0c;启动git命令窗口了 3.码云-项目代码管理仓库 链接&#xff1a;https:…

年化16.6%,全球大类资产使用lightGBM预测轮动——数据缓存提升效率

原创文章第568篇&#xff0c;专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 Dataloader缓存 加载160个因子&#xff0c;10几支大类资产&#xff0c;这个计算还是需要一点时间&#xff0c;尤其在我们频繁运行的时候&#xff0c;需要等待&#xff0c;这里我们…

软件著作权申请(未完待续)

申请网站&#xff1a;中国版权保护中心 注册登录 选择注册身份&#xff0c;个人还是单位

Java基础:IO流

目录 一、定义 1.引言 2.分类 &#xff08;1&#xff09;按照流的方向分 &#xff08;2&#xff09;按操作文件的类型分 3.体系结构 二、字节流&#xff08;以操作本地文件为例&#xff09; 1. FileOutputStream 类 &#xff08;1&#xff09;定义 &#xff08;2&am…

持续总结中!2024年面试必问的操作系统面试题(一)

一、什么是操作系统&#xff1f;它有哪些基本功能&#xff1f; 操作系统&#xff08;Operating System&#xff0c;简称OS&#xff09;是计算机系统中的一个关键软件&#xff0c;它管理计算机硬件资源并提供各种服务以方便用户和应用程序的运行。操作系统充当了用户与计算机硬…