JWT && Token
前言:近三个多月咩有发新csdn 也没有回复 程友的询问,与女友分手,缓解了百天。中间也换了个新的生活地,一份新工作,人嘛总要向前看。
- 1、 什么是JWT?
- 2、什么时候使用JWT?
- 3、JWT组成结构?
- 4、基于JAVA的案例展示
- 1、什么是JWT?
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
Although JWTs can be encrypted to also provide secrecy between parties, we will focus on signed tokens. Signed tokens can verify the integrity of the claims contained within it, while encrypted tokens hide those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it.
简而言之
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
- 2.什么时候使用JWT?
- Authorization(授权):一旦用户登录后,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务器和资源。
- Information Exchange(信息交换):对于安全的在各方之间传输信息而言,JSON Web Tokens无疑是一种很好的方式。因为JWT可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。
- 3、JWT组成结构
JWT 由三部分组成,之间用.
连接
- Header
- Payload
- Signature
所以整体样子如下
aaaa.bbbb.cccc
3.1 JWT----Header
- Header 经典部分由两部分组成:token的类型 和算法名称
{
"alg": "HS256",
"typ": "JWT"
}
然后,用Base64
对这个JSON编码就得到JWT的第一部分
3.2 JWT----Payload
Payload JWT的第二部分是payload,它包含声明(要求)。声明是关于实体(通常是用户)和其他数据的声明。声明有三种类型: registered, public 和 private。 Registered claims :
这里有一组预定义的声明,它们不是强制的,但是推荐。比如:iss (issuer), exp (expiration time), sub(subject), aud (audience)等。 Public claims : 可以随意定义。 Private claims : 用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明。
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后对有效负载进行Base64Url编码,以形成JSON Web令牌的第二部分。
请注意,对于已签名的令牌,此信息尽管可以防止篡改,但任何人都可以读取。除非将其加密,否则请勿将机密信息放入JWT的有效负载或报头元素中。
3.3 JWT----Signature
要创建签名部分,您必须获取编码的标头,编码的有效负载,机密,标头中指定的算法,并对其进行签名。
例如,如果要使用HMAC SHA256算法,则将通过以下方式创建签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
该签名用于验证消息在整个过程中没有更改,并且对于使用私钥进行签名的令牌,它还可以验证JWT的发送者是它所说的真实身份。
- 4、基于JAVA的案例展示
CheckResult.java
package com.lxn.jwt_token.bean;
import io.jsonwebtoken.Claims;
import lombok.Data;
/**
* @author: ligangan
* @Date: 2020/12/6
* @Time: 21:27
*/
@Data
public class CheckResult {
private Claims claims;
private Boolean success;
private String errCode;
}
SystemConstant.java
package com.lxn.jwt_token.utils;
/**
* @author: ligangan
* @Date: 2020/12/6
* @Time: 21:32
*/
public class SystemConstant {
public static final String JWT_ERRCODE_EXPIRE = "1";
public static final String JWT_ERRCODE_FAIL="2";
public static final String JWT_SECERT="1234567890";
}
JwtUtils.java
package com.lxn.jwt_token.utils;
import com.lxn.jwt_token.bean.CheckResult;
import io.jsonwebtoken.*;
import org.bouncycastle.util.encoders.Base64;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
/**
* @author: ligangan
* @Date: 2020/12/6
* @Time: 21:03
*/
public class JwtUtils {
/**
* 签发JWT
*
* @param id
* @param subject 可以是JSON数据 尽可能少
* @param ttlMillis
* @return String
*
*/
public static String createJWT(String id, String subject, long ttlMillis) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
SecretKey secretKey = generalKey();
JwtBuilder builder = Jwts.builder().setId(id).setSubject(subject) // 主题
.setIssuer("user") // 签发者
.setIssuedAt(now) // 签发时间
.signWith(signatureAlgorithm, secretKey); // 签名算法以及密匙
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date expDate = new Date(expMillis);
builder.setExpiration(expDate); // 过期时间
}
return builder.compact();
}
/**
* 验证JWT
*
* @param jwtStr
* @return
*/
public static CheckResult validateJWT(String jwtStr) {
CheckResult checkResult = new CheckResult();
Claims claims = null;
try {
claims = parseJWT(jwtStr);
checkResult.setSuccess(true);
checkResult.setClaims(claims);
} catch (ExpiredJwtException e) {
checkResult.setErrCode(SystemConstant.JWT_ERRCODE_EXPIRE);
checkResult.setSuccess(false);
} catch (SignatureException e) {
checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
checkResult.setSuccess(false);
} catch (Exception e) {
checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
checkResult.setSuccess(false);
}
return checkResult;
}
public static SecretKey generalKey() {
byte[] encodedKey = Base64.decode(SystemConstant.JWT_SECERT);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
/**
*
* 解析JWT字符串
*
* @param jwt
* @return
* @throws Exception
*/
public static Claims parseJWT(String jwt) throws Exception {
SecretKey secretKey = generalKey();
return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();
}
}
package com.lxn.jwt_token.test;
import com.lxn.jwt_token.bean.CheckResult;
import com.lxn.jwt_token.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import javax.crypto.SecretKey;
/**
* @author: ligangan
* @Date: 2020/12/6
* @Time: 21:38
*/
public class JWTTest {
public static void main(String[] args) throws Exception {
// 1000 * 60 60s
String jwt = JwtUtils.createJWT("1", "username", 1000 * 60);
SecretKey secretKey = JwtUtils.generalKey();
Claims claims = JwtUtils.parseJWT(jwt);
CheckResult checkResult = JwtUtils.validateJWT(jwt);
System.out.println("----------");
}
}