136 lines
3.9 KiB
Java
136 lines
3.9 KiB
Java
package com.macro.mall.util;
|
||
|
||
import io.jsonwebtoken.*;
|
||
import org.slf4j.Logger;
|
||
import org.slf4j.LoggerFactory;
|
||
import org.springframework.beans.factory.annotation.Value;
|
||
import org.springframework.security.core.userdetails.UserDetails;
|
||
import org.springframework.stereotype.Component;
|
||
|
||
import java.util.Date;
|
||
import java.util.HashMap;
|
||
import java.util.Map;
|
||
|
||
/**
|
||
* JwtToken生成的工具类
|
||
* JWT token的格式:header.payload.signature
|
||
* header的格式(算法、token的类型):
|
||
* {"alg": "HS512","typ": "JWT"}
|
||
* payload的格式(用户名、创建时间、生成时间):
|
||
* {"sub":"wang","created":1489079981393,"exp":1489684781}
|
||
* signature的生成算法:
|
||
* HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
|
||
* Created by macro on 2018/4/26.
|
||
*/
|
||
@Component
|
||
public class JwtTokenUtil {
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtil.class);
|
||
private static final String CLAIM_KEY_USERNAME = "sub";
|
||
private static final String CLAIM_KEY_CREATED = "created";
|
||
@Value("${jwt.secret}")
|
||
private String secret;
|
||
@Value("${jwt.expiration}")
|
||
private Long expiration;
|
||
|
||
/**
|
||
* 根据负责生成JWT的token
|
||
*/
|
||
private String generateToken(Map<String, Object> claims) {
|
||
return Jwts.builder()
|
||
.setClaims(claims)
|
||
.setExpiration(generateExpirationDate())
|
||
.signWith(SignatureAlgorithm.HS512, secret)
|
||
.compact();
|
||
}
|
||
|
||
/**
|
||
* 从token中获取JWT中的负载
|
||
*/
|
||
private Claims getClaimsFromToken(String token) {
|
||
Claims claims = null;
|
||
try {
|
||
claims = Jwts.parser()
|
||
.setSigningKey(secret)
|
||
.parseClaimsJws(token)
|
||
.getBody();
|
||
} catch (Exception e) {
|
||
LOGGER.info("JWT格式验证失败:{}",token);
|
||
}
|
||
return claims;
|
||
}
|
||
|
||
/**
|
||
* 生成token的过期时间
|
||
*/
|
||
private Date generateExpirationDate() {
|
||
return new Date(System.currentTimeMillis() + expiration * 1000);
|
||
}
|
||
|
||
/**
|
||
* 从token中获取登录用户名
|
||
*/
|
||
public String getUserNameFromToken(String token) {
|
||
String username;
|
||
try {
|
||
Claims claims = getClaimsFromToken(token);
|
||
username = claims.getSubject();
|
||
} catch (Exception e) {
|
||
username = null;
|
||
}
|
||
return username;
|
||
}
|
||
|
||
/**
|
||
* 验证token是否还有效
|
||
*
|
||
* @param token 客户端传入的token
|
||
* @param userDetails 从数据库中查询出来的用户信息
|
||
*/
|
||
public boolean validateToken(String token, UserDetails userDetails) {
|
||
String username = getUserNameFromToken(token);
|
||
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
|
||
}
|
||
|
||
/**
|
||
* 判断token是否已经失效
|
||
*/
|
||
private boolean isTokenExpired(String token) {
|
||
Date expiredDate = getExpiredDateFromToken(token);
|
||
return expiredDate.before(new Date());
|
||
}
|
||
|
||
/**
|
||
* 从token中获取过期时间
|
||
*/
|
||
private Date getExpiredDateFromToken(String token) {
|
||
Claims claims = getClaimsFromToken(token);
|
||
return claims.getExpiration();
|
||
}
|
||
|
||
/**
|
||
* 根据用户信息生成token
|
||
*/
|
||
public String generateToken(UserDetails userDetails) {
|
||
Map<String, Object> claims = new HashMap<>();
|
||
claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());
|
||
claims.put(CLAIM_KEY_CREATED, new Date());
|
||
return generateToken(claims);
|
||
}
|
||
|
||
/**
|
||
* 判断token是否可以被刷新
|
||
*/
|
||
public boolean canRefresh(String token) {
|
||
return !isTokenExpired(token);
|
||
}
|
||
|
||
/**
|
||
* 刷新token
|
||
*/
|
||
public String refreshToken(String token) {
|
||
Claims claims = getClaimsFromToken(token);
|
||
claims.put(CLAIM_KEY_CREATED, new Date());
|
||
return generateToken(claims);
|
||
}
|
||
}
|