如何使用JWT进行身份验证与授权
简介
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进行身份验证与授权相关推荐
- .NET6之MiniAPI(九):基于角色的身份验证和授权
身份验证是这样一个过程:由用户提供凭据,然后将其与存储在操作系统.数据库.应用或资源中的凭据进行比较. 在授权过程中,如果凭据匹配,则用户身份验证成功,可执行已向其授权的操作. 授权指判断允许用户执行 ...
- 使用JWT的ASP.NET CORE令牌身份验证和授权(无Cookie)——第1部分
目录 介绍 JWT(JSON Web令牌) ASP.NET Core中的JWToken配置 用户模型类 创建令牌 第1步 第2步 第4步 令牌存储 中间件 自定义中间件app.Use() 中间件app ...
- 使用JWT的ASP.NET CORE令牌身份验证和授权(无Cookie)——第2部分
目录 介绍 用户角色 如何创建自定义授权特性? AuthorizeAttribute AuthorizeFilter 如何在控制器和操作方法级别设置权限? 检查用户权限的扩展方法 如何在操作方法(内联 ...
- 在SPA应用中利用JWT进行身份验证
版权声明:本文为博主chszs的原创文章,未经博主允许不得转载. https://blog.csdn.net/chszs/article/details/79639919 在SPA应用中利用JWT进行 ...
- 使用kubectl访问Kubernetes集群时的身份验证和授权
全栈工程师开发手册 (作者:栾鹏) 架构系列文章 kubectl是日常访问和管理Kubernetes集群最为常用的工具. 当我们使用kubeadm成功引导启动(init)一个Kubernetes集群的 ...
- 【.NET框架实战】IdentityServer4身份验证、授权
[.NET框架实战]IdentityServer4身份验证.授权 什么是身份认证 身份认证是指当客户端访问服务端资源时,验证客户端是否合法的一种机制 什么是授权 授权就是指当客户端经过身份认证后,能够 ...
- 什么是 JWT? 如何基于 JWT 进行身份验证?
什么是 JWT? JWT (JSON Web Token) 是目前最流行的跨域认证解决方案,是一种基于 Token 的认证授权机制.从 JWT 的全称可以看出,JWT 本身也是 Token,一种规范化 ...
- iis授权mysql验证_ASP.NET Web API身份验证和授权
本文是作者所理解和翻译的内容. 这篇文章包括两部分:身份验证和授权. 身份验证用来确定一个用户的身份.例如,Alice用她的用户名和密码登陆系统,服务器用她的用户名和密码来确定她的身份. 授权是判断一 ...
- ASP.NET Web API身份验证和授权
英语原文地址:http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-a ...
最新文章
- 手撕一个spirng IoC的过程
- XML 序列化 【译】
- html万年历闹钟怎么取消,万年历如何取消整点报时,他上面有四个键,分...
- 第五节 8登陆练习操作
- VTK:可视化之FlatShading
- 前端UI框架《Angulr》入门
- 剑指Offer - 面试题53 - II. 0~n-1中缺失的数字(二分、位运算)
- C#基础系列——语法
- 华为前端工程师分享:查明网站访问故障原因,教你4招快速应对
- php ajax跳转,ajax接口的php文件如何实现跳转
- Java TCP协议传输
- 京东一面:高并发下,如何保证分布式唯一全局 ID 生成?
- 浏览器原理学习笔记1-浏览器进程
- QTTabBar 使用
- 推荐一款绘画软件krita,开源正版免费,适合ps用户
- ethool工具之TSO、UFO、GSO、LRO、GRO和RSS介绍
- 迅捷路由器造成计算机无法上网,迅捷FAST无线路由器设置好了却上不了网现象的原因及解决方法介绍...
- Request Headers 和Response Headers——请求头和响应头
- seo是什么,干什么用,有什么作用(二)
- [Inside HotSpot] C1编译器HIR的构造
热门文章
- ▽算符在球坐标系_球坐标系中的角动量算符
- 星号下三角形python答案_Python利用for循环打印星号三角形的案例
- ps调整图片大小,像素大小
- System.IO.FileNotFoundException: Could not load file or assembly ‘xx.dll‘ or one of its dependencies
- 2019.1.21【NOIP提高组】模拟B组 JZOJ 4208 线段树什么的最讨厌了
- 12306火车票助手
- android view.isshown,关于android:View getVisibility()isShown()返回不正确的可见性
- Kaldi简介【开源语音识别工具】
- Avaya PBX sip trunk对接第三方sip server传递UUI的方法
- JS实现小方块上下移动