简介

JWT定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

工作流程

1、用户使用账号、密码登录应用,登录的请求发送到认证服务器。

2、认证服务器进行用户验证,然后创建JWT字符串返回给客户端。

3、客户端请求接口时,在请求头带上JWT。应用服务器验证JWT合法性,如果合法则继续调用应用接口返回结果。

数据结构

JWT由3部分组成:标头(Header)、有效载荷(Payload)和签名(Signature)。在传输的时候,会将JWT的3部分分别进行Base64编码后用.进行连接形成最终传输的字符串JWT由3部分组成:标头(Header)、有效载荷(Payload)和签名(Signature)。在传输的时候,会将JWT的3部分分别进行Base64编码后用.进行连接形成最终传输的字符串JWT一般是这样一个字符串,分为三个部分,以"."隔开:

xxxxx.yyyyy.zzzzz
JWTString=Base64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)

token认证的优势

相⽐于 Session 认证的⽅式来说,使⽤ jwt 进⾏⾝份认证主要有下⾯优势

1.⽆状态

2.有效避免了CSRF 攻击

3.适合移动端应⽤

4.单点登录友好

NETCore使用JWT

添加数据访问模拟api,ValuesController

其中api/value1是可以直接访问的,api/value2添加了权限校验特性标签 [Authorize]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;namespace Demo.Jwt.Controllers
{[ApiController]public class ValuesController : ControllerBase{[HttpGet][Route("api/value1")]public ActionResult<IEnumerable<string>> Get(){return new string[] { "value1", "value1" };}[HttpGet][Route("api/value2")][Authorize]public ActionResult<IEnumerable<string>> Get2(){return new string[] { "value2", "value2" };}}
}

添加模拟登陆,生成Token的api,AuthController

这里模拟一下登陆校验,只验证了用户密码不为空即通过校验,真实环境完善校验用户和密码的逻辑。

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;namespace Demo.Jwt.Controllers
{[Route("api/[controller]")][ApiController]public class AuthController : ControllerBase{[AllowAnonymous][HttpGet]public IActionResult Get(string userName, string pwd){if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(pwd)){var claims = new[]{new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") ,new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddMinutes(30)).ToUnixTimeSeconds()}"),new Claim(ClaimTypes.Name, userName)};var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Const.SecurityKey));var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);var token = new JwtSecurityToken(issuer: Const.Domain,audience: Const.Domain,claims: claims,expires: DateTime.Now.AddMinutes(30),signingCredentials: creds);return Ok(new{token = new JwtSecurityTokenHandler().WriteToken(token)});}else{return BadRequest(new { message = "username or password is incorrect." });}}}
}

Startup添加JWT验证的相关配置

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Text;namespace Demo.Jwt
{public class Startup{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){//添加jwt验证:services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {options.TokenValidationParameters = new TokenValidationParameters{ValidateIssuer = true,//是否验证IssuerValidateAudience = true,//是否验证AudienceValidateLifetime = true,//是否验证失效时间ClockSkew = TimeSpan.FromSeconds(30),ValidateIssuerSigningKey = true,//是否验证SecurityKeyValidAudience = Const.Domain,//AudienceValidIssuer = Const.Domain,//Issuer,这两项和前面签发jwt的设置一致IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Const.SecurityKey))//拿到SecurityKey};});services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env){///添加jwt验证app.UseAuthentication();if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseMvc(routes =>{routes.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}");});}}
}
namespace Demo.Jwt
{public class Const{/// <summary>/// 这里为了演示,写死一个密钥。实际生产环境可以从配置文件读取,这个是用网上工具随便生成的一个密钥/// </summary>public const string SecurityKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI2a2EJ7m872v0afyoSDJT2o1+SitIeJSWtLJU8/Wz2m7gStexajkeD+Lka6DSTy8gt9UwfgVQo6uKjVLG5Ex7PiGOODVqAEghBuS7JzIYU5RvI543nNDAPfnJsas96mSA7L/mD7RTE2drj6hf3oZjJpMPZUQI/B1Qjb5H3K3PNwIDAQAB";public const string Domain = "http://localhost:5000";}
}

在实际开发中需要用下列手段来增加JWT的安全性:

1、因为JWT是在请求头中传递的,所以为了避免网络劫持,推荐使用HTTPS来传输,更加安全

2、JWT的哈希签名的密钥是存放在服务端的,所以只要服务器不被攻破,理论上JWT是安全的。因此要保证服务器的安全

3、JWT可以使用暴力穷举来破解,所以为了应对这种破解方式,可以定期更换服务端的哈希签名密钥(相当于盐值)。这样可以保证等破解结果出来了,你的密钥也已经换了

token 过期后,如何自动续期

1、方式1

将 token 过期时间设置为15分钟;

前端发起请求,后端验证 token 是否过期;如果过期,前端发起刷新token请求,后端为前端返回一个新的token;

前端用新的token发起请求,请求成功;

如果要实现每隔72小时,必须重新登录,后端需要记录每次用户的登录时间;用户每次请求时,检查用户最后一次登录日期,如超过72小时,则拒绝刷新token的请求,请求失败,跳转到登录页面。

另外后端还可以记录刷新token的次数,比如最多刷新50次,如果达到50次,则不再允许刷新,需要用户重新授权。

2、方式2

登录成功以后,后端返回 access_token 和 refresh_token,客户端缓存此两种token;

使用 access_token 请求接口资源,成功则调用成功;如果token超时,客户端携带 refresh_token 调用token刷新接口获取新的 access_token;

后端接受刷新token的请求后,检查 refresh_token 是否过期。如果过期,拒绝刷新,客户端收到该状态后,跳转到登录页;如果未过期,生成新的 access_token 返回给客户端。

客户端携带新的 access_token 重新调用上面的资源接口。

客户端退出登录或修改密码后,注销旧的token,使 access_token 和 refresh_token 失效,同时清空客户端的 access_token 和 refresh_toke。

后端实现token过期还可以利用Redis来存储token,设置redis的键值对的过期时间。如果发现redis中不存在token的记录,说明token已经过期了。

如何使用JWT进行身份验证与授权相关推荐

  1. .NET6之MiniAPI(九):基于角色的身份验证和授权

    身份验证是这样一个过程:由用户提供凭据,然后将其与存储在操作系统.数据库.应用或资源中的凭据进行比较. 在授权过程中,如果凭据匹配,则用户身份验证成功,可执行已向其授权的操作. 授权指判断允许用户执行 ...

  2. 使用JWT的ASP.NET CORE令牌身份验证和授权(无Cookie)——第1部分

    目录 介绍 JWT(JSON Web令牌) ASP.NET Core中的JWToken配置 用户模型类 创建令牌 第1步 第2步 第4步 令牌存储 中间件 自定义中间件app.Use() 中间件app ...

  3. 使用JWT的ASP.NET CORE令牌身份验证和授权(无Cookie)——第2部分

    目录 介绍 用户角色 如何创建自定义授权特性? AuthorizeAttribute AuthorizeFilter 如何在控制器和操作方法级别设置权限? 检查用户权限的扩展方法 如何在操作方法(内联 ...

  4. 在SPA应用中利用JWT进行身份验证

    版权声明:本文为博主chszs的原创文章,未经博主允许不得转载. https://blog.csdn.net/chszs/article/details/79639919 在SPA应用中利用JWT进行 ...

  5. 使用kubectl访问Kubernetes集群时的身份验证和授权

    全栈工程师开发手册 (作者:栾鹏) 架构系列文章 kubectl是日常访问和管理Kubernetes集群最为常用的工具. 当我们使用kubeadm成功引导启动(init)一个Kubernetes集群的 ...

  6. 【.NET框架实战】IdentityServer4身份验证、授权

    [.NET框架实战]IdentityServer4身份验证.授权 什么是身份认证 身份认证是指当客户端访问服务端资源时,验证客户端是否合法的一种机制 什么是授权 授权就是指当客户端经过身份认证后,能够 ...

  7. 什么是 JWT? 如何基于 JWT 进行身份验证?

    什么是 JWT? JWT (JSON Web Token) 是目前最流行的跨域认证解决方案,是一种基于 Token 的认证授权机制.从 JWT 的全称可以看出,JWT 本身也是 Token,一种规范化 ...

  8. iis授权mysql验证_ASP.NET Web API身份验证和授权

    本文是作者所理解和翻译的内容. 这篇文章包括两部分:身份验证和授权. 身份验证用来确定一个用户的身份.例如,Alice用她的用户名和密码登陆系统,服务器用她的用户名和密码来确定她的身份. 授权是判断一 ...

  9. ASP.NET Web API身份验证和授权

    英语原文地址:http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-a ...

最新文章

  1. 手撕一个spirng IoC的过程
  2. XML 序列化 【译】
  3. html万年历闹钟怎么取消,万年历如何取消整点报时,他上面有四个键,分...
  4. 第五节 8登陆练习操作
  5. VTK:可视化之FlatShading
  6. 前端UI框架《Angulr》入门
  7. 剑指Offer - 面试题53 - II. 0~n-1中缺失的数字(二分、位运算)
  8. C#基础系列——语法
  9. 华为前端工程师分享:查明网站访问故障原因,教你4招快速应对
  10. php ajax跳转,ajax接口的php文件如何实现跳转
  11. Java TCP协议传输
  12. 京东一面:高并发下,如何保证分布式唯一全局 ID 生成?
  13. 浏览器原理学习笔记1-浏览器进程
  14. QTTabBar 使用
  15. 推荐一款绘画软件krita,开源正版免费,适合ps用户
  16. ethool工具之TSO、UFO、GSO、LRO、GRO和RSS介绍
  17. 迅捷路由器造成计算机无法上网,迅捷FAST无线路由器设置好了却上不了网现象的原因及解决方法介绍...
  18. Request Headers 和Response Headers——请求头和响应头
  19. seo是什么,干什么用,有什么作用(二)
  20. [Inside HotSpot] C1编译器HIR的构造

热门文章

  1. ▽算符在球坐标系_球坐标系中的角动量算符
  2. 星号下三角形python答案_Python利用for循环打印星号三角形的案例
  3. ps调整图片大小,像素大小
  4. System.IO.FileNotFoundException: Could not load file or assembly ‘xx.dll‘ or one of its dependencies
  5. 2019.1.21【NOIP提高组】模拟B组 JZOJ 4208 线段树什么的最讨厌了
  6. 12306火车票助手
  7. android view.isshown,关于android:View getVisibility()isShown()返回不正确的可见性
  8. Kaldi简介【开源语音识别工具】
  9. Avaya PBX sip trunk对接第三方sip server传递UUI的方法
  10. JS实现小方块上下移动