JWT学习(二):Json Web Token JWT的Java使用 (JJWT)
2019独角兽企业重金招聘Python工程师标准>>>
什么是JWT?
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
jwt的组成
- Header: 标题包含了令牌的元数据,并且在最小包含签名和/或加密算法的类型
- Claims: Claims包含您想要签署的任何信息
- JSON Web Signature (JWS): 在header中指定的使用该算法的数字签名和声明
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Header: {"alg": "HS256","typ": "JWT" } Claims: {"sub": "1234567890","name": "John Doe","admin": true } Signature: base64UrlEncode(Header) + "." + base64UrlEncode(Claims) |
加密生成的token:
有关JWT的详细介绍,请阅读这篇文章:JWT学习(一):什么是JWT?- JSON WEB TOKEN
JJWT
JJWT是一个提供端到端的JWT创建和验证的Java库。永远免费和开源(Apache License,版本2.0),JJWT很容易使用和理解。它被设计成一个以建筑为中心的流畅界面,隐藏了它的大部分复杂性。
- JJWT的目标是最容易使用和理解用于在JVM上创建和验证JSON Web令牌(JWTs)的库。
- JJWT是基于JWT、JWS、JWE、JWK和JWA RFC规范的Java实现。
- JJWT还添加了一些不属于规范的便利扩展,比如JWT压缩和索赔强制。
JJWT 规范兼容
- 创建和解析明文压缩JWTs
- 创建、解析和验证所有标准JWS算法的数字签名压缩JWTs(又称JWSs):
- HS256:使用SHA-256的HMAC
- HS384:使用SHA-384的HMAC
- HS512:使用SHA-512的HMAC
- RS256:使用SHA-256的RSASSA-PKCS-v1_5
- RS384:使用SHA-384的RSASSA-PKCS-v1_5
- RS512:使用SHA-512的RSASSA-PKCS-v1_5
- PS256:使用SHA-256的RSASSA-PSS和使用SHA-256的MGF1
- PS384:使用SHA-384的RSASSA-PSS和使用SHA-384的MGF1
- PS512:使用SHA-512的RSASSA-PSS和使用SHA-512的MGF1
- ES256:使用P-256和SHA-256的ECDSA
- ES384:使用P-384和SHA-384的ECDSA
- ES512:使用P-521和SHA-512的ECDSA
下面我们根据 https://github.com/jwtk/jjwt 上的demo,来介绍下 JJWT 的用法。
jjwt 安装
jjwt 提供了 Maven 和 Gradle 两种构建方式,Maven 配置如下即可使用 JJWT。
1 2 3 4 5 |
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency> |
Gradle 使用方式如下:
1 |
dependencies { compile 'io.jsonwebtoken:jjwt:0.9.0' } |
注意:JJWT依赖于Jackson 2.x. 如果您已经在您的应用程序中使用了旧版本的 Jackson 请升级相关配置。
示例代码
签发JWT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public static String createJWT() {SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;SecretKey secretKey = generalKey();JwtBuilder builder = Jwts.builder().setId(id) // JWT_ID.setAudience("") // 接受者.setClaims(null) // 自定义属性.setSubject("") // 主题.setIssuer("") // 签发者.setIssuedAt(new Date()) // 签发时间.setNotBefore(new Date()) // 失效时间.setExpiration(long) // 过期时间.signWith(signatureAlgorithm, secretKey); // 签名算法以及密匙return builder.compact(); } |
验证JWT
1 2 3 4 5 6 7 |
public static Claims parseJWT(String jwt) throws Exception {SecretKey secretKey = generalKey();return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody(); } |
完整示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
import com.google.gson.Gson; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.apache.tomcat.util.codec.binary.Base64;import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Date; import java.util.HashMap; import java.util.Map;public class JwtUtil {/*** 由字符串生成加密key** @return*/public SecretKey generalKey() {String stringKey = Constant.JWT_SECRET;// 本地的密码解码byte[] encodedKey = Base64.decodeBase64(stringKey);// 根据给定的字节数组使用AES加密算法构造一个密钥SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;}/*** 创建jwt* @param id* @param issuer* @param subject* @param ttlMillis* @return* @throws Exception*/public String createJWT(String id, String issuer, String subject, long ttlMillis) throws Exception {// 指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;// 生成JWT的时间long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);// 创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)Map<String, Object> claims = new HashMap<>();claims.put("uid", "123456");claims.put("user_name", "admin");claims.put("nick_name", "X-rapido");// 生成签名的时候使用的秘钥secret,切记这个秘钥不能外露哦。它就是你服务端的私钥,在任何场景都不应该流露出去。// 一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。SecretKey key = generalKey();// 下面就是在为payload添加各种标准声明和私有声明了JwtBuilder builder = Jwts.builder() // 这里其实就是new一个JwtBuilder,设置jwt的body.setClaims(claims) // 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setId(id) // 设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。.setIssuedAt(now) // iat: jwt的签发时间.setIssuer(issuer) // issuer:jwt签发人.setSubject(subject) // sub(Subject):代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。.signWith(signatureAlgorithm, key); // 设置签名使用的签名算法和签名使用的秘钥// 设置过期时间if (ttlMillis >= 0) {long expMillis = nowMillis + ttlMillis;Date exp = new Date(expMillis);builder.setExpiration(exp);}return builder.compact();}/*** 解密jwt** @param jwt* @return* @throws Exception*/public Claims parseJWT(String jwt) throws Exception {SecretKey key = generalKey(); //签名秘钥,和生成的签名的秘钥一模一样Claims claims = Jwts.parser() //得到DefaultJwtParser.setSigningKey(key) //设置签名的秘钥.parseClaimsJws(jwt).getBody(); //设置需要解析的jwtreturn claims;}public static void main(String[] args) {User user = new User("tingfeng", "bulingbuling", "1056856191");String subject = new Gson().toJson(user);try {JwtUtil util = new JwtUtil();String jwt = util.createJWT(Constant.JWT_ID, "Anson", subject, Constant.JWT_TTL);System.out.println("JWT:" + jwt);System.out.println("\n解密\n");Claims c = util.parseJWT(jwt);System.out.println(c.getId());System.out.println(c.getIssuedAt());System.out.println(c.getSubject());System.out.println(c.getIssuer());System.out.println(c.get("uid", String.class));} catch (Exception e) {e.printStackTrace();}} } |
常量类:Constant.java
1 2 3 4 5 6 7 8 9 10 11 |
import java.util.UUID;public class Constant {public static final String JWT_ID = UUID.randomUUID().toString();/*** 加密密文*/public static final String JWT_SECRET = "woyebuzhidaoxiediansha";public static final int JWT_TTL = 60*60*1000; //millisecond } |
输出示例:
1 2 3 4 5 6 7 8 9 |
JWT:eyJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiIxMjM0NTYiLCJzdWIiOiJ7XCJuaWNrbmFtZVwiOlwidGluZ2ZlbmdcIixcIndlY2hhdFwiOlwiYnVsaW5nYnVsaW5nXCIsXCJxcVwiOlwiMTA1Njg1NjE5MVwifSIsInVzZXJfbmFtZSI6ImFkbWluIiwibmlja19uYW1lIjoiWC1yYXBpZG8iLCJpc3MiOiJBbnNvbiIsImV4cCI6MTUyMjMxNDEyNCwiaWF0IjoxNTIyMzEwNTI0LCJqdGkiOiJhNGQ5MjA0Zi1kYjM3LTRhZGYtODE0NS1iZGNmMDAzMzFmZjYifQ.B5wdY3_W4MZLj9uBHSYalG6vmYwdpdTXg0otdwTmU4U解密a4d9204f-db37-4adf-8145-bdcf00331ff6 Thu Mar 29 16:02:04 CST 2018 {"nickname":"tingfeng","wechat":"bulingbuling","qq":"1056856191"} Anson 123456 |
一般我们把验证操作作为中间件或者拦截器就行了,请求后端API接口时候,通过过滤器获取header中的token,验证是否正确、是否过期等。
转载于:https://my.oschina.net/xiaominmin/blog/2999894
JWT学习(二):Json Web Token JWT的Java使用 (JJWT)相关推荐
- JSON Web Token (JWT)生成Token及解密实战
转载自 JSON Web Token (JWT)生成Token及解密实战 昨天讲解了JWT的介绍.应用场景.优点及注意事项等,今天来个JWT具体的使用实践吧. 从JWT官网支持的类库来看,jjwt是J ...
- JSON Web Token (JWT),服务端信息传输安全解决方案
转载自 JSON Web Token (JWT),服务端信息传输安全解决方案 JWT介绍 JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑独立的基于JSON对 ...
- php jwt token 解析,JSON Web Token(JWT)入坑详解
JSON Web Token(JWT)入坑详解 龙行 PHP 2019-6-17 1651 0评论 /** JWT生成类 **/ class Jwt { private $al ...
- Json web token (JWT) golang实现
Json web token (JWT) eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG ...
- (json web token)JWT攻击
前记 最近国赛+校赛遇到两次json web token的题,发现自己做的并不算顺畅,于是有了这篇学习文章. 为什么要使用Json Web Token Json Web Token简称jwt 顾名思义 ...
- jwttoken解码_使用 JSON WEB TOKEN (jwt) 验证
一.什么JSON Web Tokens? JSON Web Tokens是一种开放的行业标准 RFC 7519方法,用于在双方之间安全地表示索赔. JWT.IO允许您解码,验证和生成JWT.其中.J ...
- JSON Web Token(JWT)对比Opaque Token
身份验证通常用来验证某人或某事是否如它所说的那样是谁或者是什么. 身份验证技术通过测试查看用户的凭据是否与经过身份验证的用户数据库或服务器中的凭据相匹配,从而提供设备访问控制. 基于token的身份验 ...
- JSON Web Token (JWT)笔记(token实现单点登录功能)
文章目录 前情提要 cookie(储存在用户本地终端上的数据) Cookie特点: session(web服务端内存) cookie和session 单点登录(只登录一次,可使用账号下全部服务)三种方 ...
- 用户登入身份验证,手机app登入身份验证,TokenAuth身份验证,JSON Web Token(JWT)身份验证
JJWT身份验证 1.pom依赖: <dependency ...
- JWT(JSON Web Token)简介
文章目录 一.JWT是什么 二.跨域认证问题 三.JWT原理 四.JWT数据结构 1.header(头部) 2.Payload(负载) 3.Signature 五.JWT是如何工作的 一.JWT是什么 ...
最新文章
- CISCO ACL的匹配数问题
- 移动端也能兼容的web页面制作2:导航栏、背景图片设置
- ML之SVM:利用SVM算法(超参数组合进行单线程网格搜索+3fCrVa)对20类新闻文本数据集进行分类预测、评估
- Typora markdown公式换行等号对齐_Typora-编写博客格式化文档的最佳软件
- java delphi 三层_三层架构delphi+Java+Oracle模式的实现
- okHttp源码解析------待续
- html跑马灯_用Excel居然能做“跑马灯”,而且还这么简单!
- Python 列表 min() 方法
- SharePoint 2013 Step by Step——How to Create a Lookup Column to Another Site(Cross Site) 阅读目录...
- 代码分析测试SaaS平台Code Climate获得450万美元A轮融资
- EJB-02:EJB开发流程
- Scrum板与Kanban如何抉择?ecusiqoiw板与按照eqymgy
- 计算机颜色更换,如何给证件照换底色;怎么快速更换证件照底色
- 创建oracle自增序列
- 你真的了解ESD吗?老司机从零教学系列之学会ESD选型
- PowerBI开发 第三篇:报表设计技巧
- latex集合的包含_latex 集合相关符号:实数集,整数集,并,包含,真包含
- java程序设计高级教程答案_Java高级程序设计实战教程答案
- uniapp+uniCloud实现批量上传图片到云端(解决h5端跨域问题)
- Windows Batch 常用命令