# 1、什么是 JWT
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准((RFC 7519 (opens new window)).该 token 被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该 token 也可直接被用于认证,也可被加密。
推荐教程:JSON Web Token 入门教程 (opens new window)
# 2、使用
建立 maven 工程,这里只贴出了 jwt 的,集成到 SSM 中
代码语言:javascript复制 <!-- json web token -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.10.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
将 JWT 生成和验证封装成一个工具类,如下:
注意类中使用到的常量,在开发的过程中我们需要避免使用魔法值,所以将一些常用的字符声明到常量当中
代码语言:javascript复制public class JwtUtil {
static Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
/**
* 由字符串生成加密key
*
* @return
*/
public static SecretKey generalKey() {
String stringKey = Constant.JWT_SECRET;//本地配置文件中加密的密文7786df7fc3a34e26a61c034d5ec8245d
byte[] encodedKey = Base64.decodeBase64(stringKey);//本地的密码解码[B@152f6e2
System.out.println(encodedKey);//[B@152f6e2
System.out.println(Base64.encodeBase64URLSafeString(encodedKey));//7786df7fc3a34e26a61c034d5ec8245d
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");// 根据给定的字节数组使用AES加密算法构造一个密钥,使用 encodedKey中的始于且包含 0 到前 leng 个字节这是当然是所有。(后面的文章中马上回推出讲解Java加密和解密的一些算法)
return key;
}
/**
* 创建jwt
*
* @param id
* @param subject
* @param ttlMillis 过期的时间长度
* @return
* @throws Exception
*/
public static String createJWT(String id, String subject, long ttlMillis) throws Exception {
long nowMillis = System.currentTimeMillis();//生成JWT的时间
Date now = new Date(nowMillis);
//下面就是在为payload添加各种标准声明和私有声明了
JwtBuilder builder = Jwts.builder() //这里其实就是new一个JwtBuilder,设置jwt的body
.setId(id) //设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。
.setIssuedAt(now) //iat: jwt的签发时间
.setSubject(subject) //sub(Subject):代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。
.signWith(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 static Claims parseJWT(String jwt) throws Exception {
jwt = jwt.replace("Bearer ", "");
return Jwts.parser().setSigningKey(key).parseClaimsJws(jwt).getBody();
}
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(Constant.JWT_ERRCODE_EXPIRE);
checkResult.setSuccess(false);
} catch (SignatureException e) {
checkResult.setErrCode(Constant.JWT_ERRCODE_FAIL);
checkResult.setSuccess(false);
} catch (Exception e) {
checkResult.setErrCode(Constant.JWT_ERRCODE_FAIL);
checkResult.setSuccess(false);
}
return checkResult;
}
/**
* 生成subject信息
*
* @param user
* @return
*/
public static String generalSubject(User user) {
return JSON.toJSONString(user);
}
}
主要的就是在客户端发起请求的时候,在请求处理之前我们对请求头进行判断,判断请求头中是否带有服务器端给客户端发送过去的 jwt
代码语言:javascript复制public class TokenIntercepter implements HandlerInterceptor {
Logger log=LoggerFactory.getLogger(TokenIntercepter.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
if(token==null || token.equals("")){
throw new BaseException(999,"token is null");
}
CheckResult checkResult = JwtUtil.validateJWT(token);
if (checkResult.isSuccess()) {
Claims claims = checkResult.getClaims();
String subject = claims.getSubject();
JSONObject jsonObject = JSONObject.parseObject(subject);
User user = JSON.toJavaObject(jsonObject, User.class);
log.info("token parse success {}",user.toString());
return true;
}else{
throw new BaseException(999,"token parse error");
}
}
}