JWT全面解读、使用步骤
JWT全面解读
- JWT全面解读
- 前言
- JWT基本使用
- 在pom.xml引入java-jwt
- 示例如下
- 概念介绍
- JWT消息构成
- 头部
- playload
- 标准中注册的声明 (建议但不强制使用)
- 自定义数据
- 签名signature
- JJWT
- 引入
- 使用方法
- 生成token
- 解析token
前言
JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。
优点是在分布式系统中,很好地解决了单点登录问题,很容易解决了session共享的问题。
缺点是无法作废已颁布的令牌/不易应对数据过期。
可能习惯了redis保存session,使用shiro做登陆,突然使用JWT有点不适应,因为太简单了,我个人不是很建议使用,还是那句话,你的选择权有多大,你有学多少知识。
JWT基本使用
在pom.xml引入java-jwt
<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version>
</dependency>
Gradle下依赖
compile 'com.auth0:java-jwt:3.4.0'
示例如下
package yui.ui.web.sys.controller;import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;import com.alibaba.druid.util.StringUtils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;public class Test {/*** APP登录Token的生成和解析* *//** token秘钥,请勿泄露,请勿随便修改 backups:JKKLJOoasdlfj */public static final String SECRET = "JKKLJOoasdlfj";/** token 过期时间: 10天 */public static final int calendarField = Calendar.DATE;public static final int calendarInterval = 10;/*** JWT生成Token.<br/>* * JWT构成: header, payload, signature* * @param user_id* 登录成功后用户user_id, 参数user_id不可传空*/public static String createToken(Long user_id) throws Exception {Date iatDate = new Date();// expire timeCalendar nowTime = Calendar.getInstance();nowTime.add(calendarField, calendarInterval);Date expiresDate = nowTime.getTime();// header MapMap<String, Object> map = new HashMap<>();map.put("alg", "HS256");map.put("typ", "JWT");// build token// param backups {iss:Service, aud:APP}String token = JWT.create().withHeader(map) // header.withClaim("iss", "Service") // payload.withClaim("aud", "APP").withClaim("user_id", null == user_id ? null : user_id.toString()).withIssuedAt(iatDate) // sign time.withExpiresAt(expiresDate) // expire time.sign(Algorithm.HMAC256(SECRET)); // signaturereturn token;}/*** 解密Token* * @param token* @return* @throws Exception*/public static Map<String, Claim> verifyToken(String token) {DecodedJWT jwt = null;try {JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();jwt = verifier.verify(token);} catch (Exception e) {// e.printStackTrace();// token 校验失败, 抛出Token验证非法异常}return jwt.getClaims();}/*** 根据Token获取user_id* * @param token* @return user_id*/public static Long getAppUID(String token) {Map<String, Claim> claims = verifyToken(token);Claim user_id_claim = claims.get("user_id");if (null == user_id_claim || StringUtils.isEmpty(user_id_claim.asString())) {// token 校验失败, 抛出Token验证非法异常}return Long.valueOf(user_id_claim.asString());}
}
最终存放的数据在JWT内部的实体claims里。它是存放数据的地方
概念介绍
JWT消息构成
一个token分3部分,按顺序为
- 头部(header)
- 其为载荷(payload)
- 签证(signature)
由三部分生成token
3部分之间用“.
”号做分隔。例如eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
验证koten地址
头部
Jwt的头部承载两部分信息:
- 声明类型,这里是jwt
- 声明加密的算法 通常直接使用 HMAC SHA256
JWT里验证和签名使用的算法,可选择下面的。
JWS | 算法名称 | 描述 |
---|---|---|
HS256 | HMAC256 | HMAC with SHA-256 |
HS384 | HMAC384 | HMAC with SHA-384 |
HS512 | HMAC512 | HMAC with SHA-512 |
RS256 | RSA256 | RSASSA-PKCS1-v1_5 with SHA-256 |
RS384 | RSA384 | RSASSA-PKCS1-v1_5 with SHA-384 |
RS512 | RSA512 | RSASSA-PKCS1-v1_5 with SHA-512 |
ES256 | ECDSA256 | ECDSA with curve P-256 and SHA-256 |
ES384 | ECDSA384 | ECDSA with curve P-384 and SHA-384 |
ES512 | ECDSA512 | ECDSA with curve P-521 and SHA-512 |
使用代码如下
// header Map
Map<String, Object> map = new HashMap<>();
map.put("alg", "HS256");
map.put("typ", "JWT");
playload
载荷就是存放有效信息的地方。基本上填2种类型数据
-标准中注册的声明的数据
-自定义数据
由这2部分内部做base64加密。最张数据进入JWT的chaims里存放。
标准中注册的声明 (建议但不强制使用)
iss: jwt签发者sub: jwt所面向的用户aud: 接收jwt的一方exp: jwt的过期时间,这个过期时间必须要大于签发时间nbf: 定义在什么时间之前,该jwt都是不可用的.iat: jwt的签发时间 jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
使用方法
JWT.create().withHeader(map) // header.withClaim("iss", "Service") // payload.withClaim("aud", "APP").withIssuedAt(iatDate) // sign time.withExpiresAt(expiresDate) // expire time
自定义数据
这个就比较简单,存放我们想放在token中存放的key-value值
使用方法
JWT.create().withHeader(map) // header.withClaim("name", "cy") // payload.withClaim("user_id", "11222");
签名signature
jwt的第三部分是一个签证信息,这个签证信息算法如下:
base64UrlEncode(header) + "." + base64UrlEncode(payload)+your-256-bit-secret
这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。
基本上至此,JWT的API相关知识已经学完了,但是API不够有好,不停的用withClaim放数据。不够友好。下面推荐一款框架,相当于对JWT的实现框架
JJWT
它是为了更友好在JVM上使用JWT,是基本于JWT, JWS, JWE, JWK框架的java实现。
参考git地址
引入
Maven
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.0</version>
</dependency>
Gradle:
dependencies {compile 'io.jsonwebtoken:jjwt:0.9.0'
}
使用方法
生成token
getJwtToken是生成jjwt里的token方法。
import com.sun.javafx.scene.traversal.Algorithm;
import io.jsonwebtoken.*;
import io.jsonwebtoken.impl.DefaultJwsHeader;import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;private String SECRET = "DyoonSecret_0581";
private void getJwtToken(){Date iatDate = new Date();// expire timeCalendar nowTime = Calendar.getInstance();//有10天有效期nowTime.add(Calendar.DATE, 10);Date expiresDate = nowTime.getTime();Claims claims = Jwts.claims();claims.put("name","cy");claims.put("userId", "222");claims.setAudience("cy");claims.setIssuer("cy");String token = Jwts.builder().setClaims(claims).setExpiration(expiresDate).signWith(SignatureAlgorithm.HS512, SECRET).compact();}
上面将token中的载荷放在chaims中,其实chaims是JWT内部维持的一个存放有效信息的地方,不论使用任何API,最终都使用chaims保存信息。
setClaims
有2个重载
JwtBuilder setClaims(Claims claims);
JwtBuilder setClaims(Map<String, Object> claims);
不能就是说,我们也可以直接传入map值对象。
解析token
parseJwtToken方法是解析token。
public void parseJwtToken(String token) {try{}catch (Exception e){}Jws<Claims> jws = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);String signature = jws.getSignature();Map<String, String> header = jws.getHeader();Claims Claims = jws.getBody();}
扩展阅读
讲真,别再使用JWT了!
JWT全面解读、使用步骤相关推荐
- 【导航业务框架】开源无人驾驶项目autoware解读
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录 前言 一.Autoware的整体框架和模块 1.Autoware介绍 2. ...
- ASP.NET Core 3.1 系列之 Web API 添加身份验证Jwt
ASP.NET Core 3.1 系列之 Web API 中间件篇 (一) 身份验证(Jwt)中间件使用步骤 添加 NuGet程序包 添加包:Microsoft.AspNetCore.Authenti ...
- 小程序 jwt_使用JWT保护应用程序安全的简介
小程序 jwt JSON Web Tokens have become the favorite choice among modern developers when implementing us ...
- 跟我学Springboot开发后端管理系统8:Matrxi-Web权限设计实现
上篇文章讲述了Matrix-web整体实现的权限控制的思路.现在来回顾一下: 首先,用户需要登录,填用户名.密码,后端接收到登录请求,进行用户.密码的校验,校验成功后则根据用户名生成Token,并返回 ...
- https证书互信解决方案—创建私有CA并申请证书
前言 https相较于http而言有很大的安全性,当我们一个服务开启https并与之通信时,往往需要证书的认证,如果是浏览器访问服务,只要在浏览器内设置信任证书即可,而如果是程序内访问服务(如java ...
- 老李分享:HTTP协议之协议头
老李分享:HTTP协议之协议头 当我们打开一个网页时,浏览器要向网站服务器发送一个HTTP请求头,然后网站服务器根据HTTP请求头的内容生成当次请求的内容发送给浏览器.你明白HTTP请求头的具体含意吗 ...
- 因果推断笔记——因果图建模之微软开源的EconML(五)
文章目录 1 EconML介绍 1.1 EconML介绍 1.2 一些理论解答 1.3 常规CATE的估计器 1.4 IV工具变量 + CATE的估计器 1.5 动态处理效应的估计器 2 智能营销案例 ...
- apple授权登录(服务端)
一.apple配置 1.注册开发者 在apple开发者官网( https://developer.apple.com/)注册成开发者 2.创建应用 点击左边菜单的Certificates, Ident ...
- 【Excel】绘图案例_常见复合图:簇状图+堆积图+折线图
[Excel]绘图案例_常见复合图:簇状图+堆积图+折线图 前言 最近有朋友让我帮忙用excel画图,老实说我很讨厌用excel画图,点来点去,复杂一些还不能复用,非常繁琐.当然,入门也很简单.需求时 ...
- Docker最新超详细教程——基本操作
Docker最新超详细教程--基本操作 一.镜像操作 镜像名称 镜像命令 案例一:拉取.查看镜像 案例二:保存.导入镜像 二.容器操作 容器相关命令 容器三个状态 暂停与停止有什么差别? 案例一:创建 ...
最新文章
- 第三次冲刺阶段第五天
- OVS 各功能调用过程(三十一)
- Spring Cloud 微服务实战系列-Ribbon入门RestTemplate 介绍
- 信息论与编码_庆祝中山大学计算机科学系成立40周年系列活动 | 第四届“信息论与编码中大论坛”...
- C#:泛型(Generic)
- deeplearning4j的学习
- 需求分析之软件界面设计
- python Word批量转PDF
- layui iframe弹出层高度自适应,并垂直居中
- java 0-999 阿拉伯数字转英文
- 请求的操作需要提升 windows7 route add命令 windows7添加路由
- 【Python 实战基础】Pandas如何从股票数据找出收盘价最低行
- ddl是什么意思网络语_大学赶ddl是什么意思?DDL语句有什么功能?
- java sapi_使用Microsoft SAPI进行语音合成
- mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such f
- Celery Django 运行 task 任务的时候 提示NotRegistered
- 201671010434 王雯涵《英文文本统计分析》结对项目报告
- 计算机中的英语六级作文万能模板,英语六级作文万能模板(4篇)
- Paper pusher 摆弄文件的人
- 软路由的正确组网姿势(上篇)
热门文章
- 【知识点总结】电路原理 第一讲
- CSS度量单位px/pt/em/in/pc/mm/cm
- 不忘来时路 心系梦归处
- 读《富爸爸,穷爸爸》后感(二)
- 计算机win7的后缀名怎么显示,win7显示文件后缀名怎么显示?win7显示文件后缀
- Android 9.0 开启飞行模式
- linux 恢复member1账户,Linux操作系统第9讲 帐户管理和权限管理.ppt
- vant-list上拉加载onload事件触发多次
- 树的遍历 ALDS1_7_C: Tree Walk
- html 中全角波浪线,中间波浪怎么打出来,靠上的波浪符号怎么打