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

news2024/11/18 14:31:01

.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的Claims
            var claims = new[]
            {
               new Claim(“User_id”, "Ares-Wang"),
               new Claim(ClaimTypes.Email, "123@163.com"),
               // 添加其他需要的声明
            };

            // 创建JWT的Token
            var 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. 定义需要使用到的Claims
        var claims = new Claim[]
        {
            new Claim("user_id", user_id),           
            /* 可以保存自己想要信息,传参进来即可          
            new Claim("limit", "limit"),           
            */
        };
 
        // 2. 从 appsettings.json 中读取SecretKey
        var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecretKey));
 
        // 3. 选择加密算法
        var algorithm = SecurityAlgorithms.HmacSha256;
 
        // 4. 生成Credentials
        var signingCredentials = new SigningCredentials(secretKey, algorithm);
 
        // 5. 根据以上,生成token
        var jwtSecurityToken = new JwtSecurityToken(
           issuer: AppId,    //Issuer
           audience: AppKey,  //Audience
           claims: claims,                          //Claims,
           notBefore: DateTime.Now,                    //notBefore
           expires: DateTime.Now.AddHours(1),     //expires
           signingCredentials: signingCredentials               //Credentials
        );
 
        // 6. 将token变为string
        var 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.coloradmin.cn/o/1858584.html

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

相关文章

华为开发者大会闪耀东莞,康佳电视携手海思惊艳亮相

近日&#xff0c;华为开发者大会&#xff08;HDC2024&#xff09;在东莞松山湖举行。 作为电视领域唯一受邀参展的品牌&#xff0c;康佳电视以其优秀的创新实力&#xff0c;携手华为海思共同展示了基于OpenHarmony Standard层级的鸿鹄媒体创新方案。该方案不仅能够为用户带来更…

网络构建关键技术_1.网络高可用设计

1.网络高可用性概述 随着网络快速发展及应用日益深入&#xff0c;各种核心和增值业务在网络上广泛部署&#xff0c;网络的作用愈来愈凸显出来。即使网络出现短时间中断&#xff0c;都可能对业务带来比较大的影响&#xff0c;甚至给企业造成一定程度的经济损失。因此&#xff0c…

LeetCode 算法:对称二叉树 c++

原题链接&#x1f517;&#xff1a;对称二叉树 难度&#xff1a;简单⭐️ 题目 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;ro…

FreeRTOS实时操作系统

1.认识实施操作系统 1.1 裸机和实时操作系统 裸机&#xff1a; 早期嵌入式开发没有嵌入式操作系统的概念&#xff0c;直接操作裸机&#xff0c;在裸机上写程序&#xff0c;比如用51单片机基本就没有操作系统的概念。 通常把程序设计为前后台系统&#xff0c;主要分为两部分&a…

路由(urls)

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 Django的URL路由流程&#xff1a; l Django查找全局urlpatterns变量&#xff08;urls.py&#xff09;。 l 按照先后顺序&#xff0c;对URL逐一匹…

我做个人站长 7 年的经验,最痛的莫过于。。

大家好&#xff0c;我是程序员鱼皮&#xff0c;从大学期间上线个人博客网站开始&#xff0c;我做个人站长已经有 7 年多了。在这个过程中&#xff0c;我收获了很多&#xff0c;除了技术成长带来的快乐外&#xff0c;个人站长最开心的莫过于有用户使用、并且留下好评&#xff0c…

数据库精选题(七)(综合模拟题二)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;数据库 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 一、名词解释 1、事务 2、弱实体集 3、正…

顶尖项目经理都在用的SOP

接受任务SOP 了解任务背景了解任务目标&#xff08;包含deadline&#xff09;拆解任务&#xff0c;确认负责人执行方案审批确认跟进执行并定期汇报验收结果&#xff0c;进行反馈相关文档存档&#xff0c;形成闭环 推进任务SOP - PDCA循环 制定计划 Plan。依据目标&#xff0c…

【面试题】面试小技巧:如果有人问你 xxx 技术是什么?_面试问你对什么技术特别了解

前端工程越来越大&#xff0c;前面几种方案不能很好的支持单元测试。 在这样的背景下&#xff0c;React 诞生了。React 带来了新的思维模式&#xff0c;UI fn(props)&#xff0c;React 中一个组件就是一个函数或者一个类&#xff0c;一个函数或者一个类就是一个基础单位&…

OpenFeign 的请求处理流程

流程 1. 定义 Feign 客户端接口 首先&#xff0c;开发者需要定义一个 Feign 客户端接口&#xff0c;并使用 FeignClient 注解进行配置。例如&#xff1a; FeignClient(name "aService", url "http://localhost:8080") public interface ServiceProvid…

数据库 复习题

有一个关系模式&#xff1a;工程关系&#xff08;工程号&#xff0c;工程名称&#xff0c;职工号&#xff0c;姓名&#xff0c;聘期&#xff0c;职务&#xff0c;小时工资率&#xff0c;工时&#xff09;&#xff0c;公司按照工时和小时工资率支付工资&#xff0c;小时工资率由…

【面试题】马上金九银十了,简历该准备起来了,面试题你准备好了吗 ?浅谈 JS 浅拷贝和深拷贝

代码展示 let obj_old {name: Tom,age: 15,favorite: {food: bread,drink: milk} } let obj_new {...obj_old} console.log(obj_old obj_new) // false console.log(obj_old.name obj_new.name) // true console.log(obj_old.favorite obj_new.favorite) // true3. Ar…

什么是档案业务建设评价

档案业务建设评价是对档案管理机构或部门在档案业务建设方面进行的评估和考核。评价主要根据一定的评价标准和指标&#xff0c;对档案业务的各个方面进行综合评估&#xff0c;包括档案收集、整理、保管、利用等环节&#xff0c;以及档案管理机构的组织管理、技术能力等方面。 评…

OnlyOffice:现代办公的最佳选择

目录 安装 使用 评价 对比&#xff08;与WPS&#xff09; 总结 在当今的数字化办公时代&#xff0c;选择一款功能全面且易于使用的办公软件至关重要。OnlyOffice作为一款现代化的办公软件&#xff0c;凭借其强大的功能和友好的用户体验&#xff0c;逐渐成为了众多企业和个…

【ONLYOFFICE震撼8.1】ONLYOFFICE8.1版本桌面编辑器测评

随着远程工作的普及和数字化办公的发展&#xff0c;越来越多的人开始寻找一款具有强大功能和便捷使用的办公软件。在这个时候&#xff0c;ONLYOFFICE 8.1应运而生&#xff0c;成为了许多用户的新选择。ONLYOFFICE 8.1是一种办公套件软件&#xff0c;它提供了文档处理、电子表格…

19、删除链表的倒数第

1、题目描述 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]示例 …

数字图像处理实验报告小论文(Matlab语言)

1.课题分析 在当今信息化社会&#xff0c;图像处理技术已成为众多领域不可或缺的一部分&#xff0c;从医学影像分析到安防监控&#xff0c;再到日常生活中的图片美化&#xff0c;图像处理技术都发挥着至关重要的作用。本次课题主要聚焦于图像灰度处理、图像小波变换和图像分割这…

数字货币与区块链生态

前言&#xff1a;区块链技术与数字货币这一文详细介绍了区块链技术&#xff0c;感兴趣的可以先看看这篇文章 1.比特币之后的数字货币与区块链发展 2.区块链形态 • 无许可区块链&#xff08;permissionless blockchain&#xff09; 用户无需许可即可加入区块链网络 • 许…

【简单讲解下C++max函数的使用】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

PSL400PC10P80、PSL410PC10P100、PSL420PC10P60比例换向阀放大器

PSL100PC10P60、PSL110PC10P80、PSL120PC10P100、PSL200PC10P80、PSL210PC10P60、PSL220PC10P100、PSL400PC10P80、PSL410PC10P100、PSL420PC10P60、PSL500PC10P100、PSL510PC10P80、PSL520PC10P100、PSL600PC10P60、PSL610PC10P100、PSL620PC10P60、PSL700PC10P80、PSL710PC10…