在这里咱们来探讨一下如何学习一门新的技术,我我的总结为 RSA。html
首先让咱们JWT 官网一探究竟。https://jwt.iojava
本身英文很差 使用百度翻译内容以下:git
JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于在各方之间做为JSON对象安全地传输信息。该信息能够被验证和信任,由于它是数字签名的。JWTS能够使用秘密(使用HMAC算法)或公钥/私钥对使用RSA或ECDSA来签名。github
虽然JWTS能够加密,但也提供保密各方之间,咱们将重点放在签名令牌。签名的令牌能够验证包含在其中的声明的完整性,而加密的令牌隐藏这些声明以防其余各方。当令牌使用公钥/私钥对签名时,签名也证实只有持有私钥的方才是签名的方。算法
接下来咱们开始学习若是使用JWT,经过点击上图中 LEARN MORE ABOUT JWT 显示以下图:而后点击START USING THE TOOLspring
以下图所示 选择对应的语言的jwt 使用教程。咱们这里介绍是是 标注有:maven:com.auth0 java-jwt 的版本。安全
查看 jwt github 示例教程和源码。 https://github.com/auth0/java-jwtspringboot
在README.md 文件中有使用介绍和示例程序。服务器
使用jwt 咱们须要处理三块内容以下:maven
头部信息由2部分组成
例如:
{ "alg": "HS256", "typ": "JWT" }
而后,这个JSON被编码为Base64Url,造成JWT的第一部分。
其中包含声明(claims)。声明能够存放实体(一般是用户)和其余数据的声明,声明包括3种类型
这些是一组预约义声明,不是强制性的,但建议使用,以提供一组有用的,可互操做的声明。其中一些是: iss(发行人), exp(到期时间),子(主题), aud(观众)等
能够参考 IANA JSON Web令牌注册表 查看公共的声明
根据根据本身的业务须要自定义的一些数据格式。
示例有效负载能够是:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
这个部分须要base64加密后的header和base64加密后的payload使用.链接组成的字符串,而后经过header中声明的加密方 式进行加盐secret组合加密,而后就构成了jwt的第三部分。
例如,若是要使用HMAC SHA256算法,将按如下方式建立签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
第一步引入JWT 依赖到pom.xml中
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.1</version> </dependency>
咱们经过三个方法来演示如何使用JWT
构建头部信息
Map<String, Object> map = new HashMap<String, Object>(); map.put("alg", "HS256"); map.put("typ", "JWT");
构建密钥信息
Algorithm algorithm = Algorithm.HMAC256("secret");
咱们经过定义注册和自定义声明 并组合头部信息和密钥信息生成jwt token
String token = JWT.create() .withHeader(map) /*设置 载荷 Payload*/ .withClaim("loginName", "zhuoqianmingyue") .withIssuer("SERVICE")//签名是有谁生成 例如 服务器 .withSubject("this is test token")//签名的主题 //.withNotBefore(new Date())//该jwt都是不可用的时间 .withAudience("APP")//签名的观众 也能够理解谁接受签名的 .withIssuedAt(nowDate) //生成签名的时间 .withExpiresAt(expireDate)//签名过时的时间 /*签名 Signature */ .sign(algorithm);
构建密钥信息
Algorithm algorithm = Algorithm.HMAC256("secret");
经过密钥信息和签名的发布者的信息生成JWTVerifier (JWT验证类)
JWTVerifier verifier = JWT.require(algorithm) .withIssuer("SERVICE") .build();
经过JWTVerifier 的verify获取 token中的信息。
DecodedJWT jwt = verifier.verify(token);
以下面代码所示就能够获取到咱们以前生成token的 签名的主题,观众 和自定义的声明信息。
String subject = jwt.getSubject(); List<String> audience = jwt.getAudience(); Map<String, Claim> claims = jwt.getClaims();
具体代码以下:
package com.ljk.springBootLearn.jwt; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Map; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTCreationException; import com.auth0.jwt.exceptions.JWTVerificationException; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; public class JWTDemo { public String createToken() { try { String secret = "secret";//token 密钥 Algorithm algorithm = Algorithm.HMAC256("secret"); //头部信息 Map<String, Object> map = new HashMap<String, Object>(); map.put("alg", "HS256"); map.put("typ", "JWT"); Date nowDate = new Date(); Date expireDate = getAfterDate(nowDate,0,0,0,2,0,0);//2小过时 String token = JWT.create() /*设置头部信息 Header*/ .withHeader(map) /*设置 载荷 Payload*/ .withIssuer("SERVICE")//签名是有谁生成 例如 服务器 .withSubject("this is test token")//签名的主题 //.withNotBefore(new Date())//定义在什么时间以前,该jwt都是不可用的. .withAudience("APP")//签名的观众 也能够理解谁接受签名的 .withIssuedAt(nowDate) //生成签名的时间 .withExpiresAt(expireDate)//签名过时的时间 /*签名 Signature */ .sign(algorithm); return token; } catch (JWTCreationException exception){ exception.printStackTrace(); } return null; } public String createTokenWithClaim() { try { Algorithm algorithm = Algorithm.HMAC256("secret"); Map<String, Object> map = new HashMap<String, Object>(); Date nowDate = new Date(); Date expireDate = getAfterDate(nowDate,0,0,0,2,0,0);//2小过时 map.put("alg", "HS256"); map.put("typ", "JWT"); String token = JWT.create() /*设置头部信息 Header*/ .withHeader(map) /*设置 载荷 Payload*/ .withClaim("loginName", "lijunkui") .withIssuer("SERVICE")//签名是有谁生成 例如 服务器 .withSubject("this is test token")//签名的主题 //.withNotBefore(new Date())//定义在什么时间以前,该jwt都是不可用的. .withAudience("APP")//签名的观众 也能够理解谁接受签名的 .withIssuedAt(nowDate) //生成签名的时间 .withExpiresAt(expireDate)//签名过时的时间 /*签名 Signature */ .sign(algorithm); return token; } catch (JWTCreationException exception){ exception.printStackTrace(); } return null; } /** * 返回必定时间后的日期 * @param date 开始计时的时间 * @param year 增长的年 * @param month 增长的月 * @param day 增长的日 * @param hour 增长的小时 * @param minute 增长的分钟 * @param second 增长的秒 * @return */ public Date getAfterDate(Date date, int year, int month, int day, int hour, int minute, int second){ if(date == null){ date = new Date(); } Calendar cal = new GregorianCalendar (); cal.setTime(date); if(year != 0){ cal.add(Calendar.YEAR, year); } if(month != 0){ cal.add(Calendar.MONTH, month); } if(day != 0){ cal.add(Calendar.DATE, day); } if(hour != 0){ cal.add(Calendar.HOUR_OF_DAY, hour); } if(minute != 0){ cal.add(Calendar.MINUTE, minute); } if(second != 0){ cal.add(Calendar.SECOND, second); } return cal.getTime(); } public void verifyToken(String token) { try { Algorithm algorithm = Algorithm.HMAC256("secret"); JWTVerifier verifier = JWT.require(algorithm) .withIssuer("SERVICE") .build(); //Reusable verifier instance DecodedJWT jwt = verifier.verify(token); String subject = jwt.getSubject(); Map<String, Claim> claims = jwt.getClaims(); Claim claim = claims.get("loginName"); System.out.println(claim.asString()); List<String> audience = jwt.getAudience(); System.out.println(subject); System.out.println(audience.get(0)); } catch (JWTVerificationException exception){ exception.printStackTrace(); } } public static void main(String[] args) { JWTDemo demo = new JWTDemo(); //String createToken = demo.createToken(); String createTokenWithClaim = demo.createTokenWithClaim(); demo.verifyToken(createTokenWithClaim); } }
参考文献:http://www.javashuo.com/article/p-uxridfao-cg.html
另外也能够关注一下 个人GitHub项目: springbootexamples 进行学习