|
@@ -0,0 +1,202 @@
|
|
|
|
+package com.free.utils;
|
|
|
|
+
|
|
|
|
+import com.auth0.jwt.JWTVerifier;
|
|
|
|
+import com.auth0.jwt.algorithms.Algorithm;
|
|
|
|
+import com.auth0.jwt.interfaces.Claim;
|
|
|
|
+import com.auth0.jwt.interfaces.DecodedJWT;
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
|
+import com.free.entity.system.LoginRecord;
|
|
|
|
+import com.free.frame.CustomizationException;
|
|
|
|
+import com.free.frame.ExceptionEnum;
|
|
|
|
+import com.free.mapper.system.LoginRecordMapper;
|
|
|
|
+import com.free.service.system.LoginRecordService;
|
|
|
|
+import com.auth0.jwt.JWT;
|
|
|
|
+import com.auth0.jwt.JWTCreator;
|
|
|
|
+
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
|
+import java.util.Date;
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.Map;
|
|
|
|
+
|
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
|
+
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
|
+@Component
|
|
|
|
+public class JwtUtil {
|
|
|
|
+ public static final String TOKEN_HEADER = "Authorization";
|
|
|
|
+ public static final String TOKEN_PREFIX = "Free ";
|
|
|
|
+ // 过期时间, 半个小时
|
|
|
|
+ private static final long EXPIRE_MIN = 30;
|
|
|
|
+ private static final long EXPIRE_TIME = EXPIRE_MIN * 60 * 1000;
|
|
|
|
+ // 密钥
|
|
|
|
+ private static final String SECRET = "Ziyouyanfa!@#";
|
|
|
|
+ /** 特殊处理的key,id.因为是long类型 */
|
|
|
|
+ private static String spcialKey = "id";
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private LoginRecordService lrs;
|
|
|
|
+
|
|
|
|
+ private static JwtUtil jwtUtil = new JwtUtil();
|
|
|
|
+
|
|
|
|
+ @PostConstruct
|
|
|
|
+ public void init() {
|
|
|
|
+ jwtUtil = this;
|
|
|
|
+ jwtUtil.lrs = this.lrs;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 生成签名
|
|
|
|
+ *
|
|
|
|
+ * @param map 数据
|
|
|
|
+ * @param secret 密码
|
|
|
|
+ * @return 加密后的token
|
|
|
|
+ */
|
|
|
|
+ public static String sign(Map<String, Object> map) {
|
|
|
|
+ Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
|
|
|
|
+ Algorithm algorithm = Algorithm.HMAC256(SECRET); // 使用HS256算法
|
|
|
|
+ JWTCreator.Builder builder = JWT.create();
|
|
|
|
+
|
|
|
|
+ for (Map.Entry<String, Object> entry : map.entrySet()) {
|
|
|
|
+ String k = entry.getKey();
|
|
|
|
+ if (spcialKey.equals(k)) {
|
|
|
|
+ Long v = (Long) entry.getValue();
|
|
|
|
+ builder.withClaim(k, v);
|
|
|
|
+ } else {
|
|
|
|
+ String v = (String) entry.getValue();
|
|
|
|
+ builder.withClaim(k, v);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ String token = builder.withExpiresAt(date)
|
|
|
|
+ .sign(algorithm);
|
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
+ sb.append(TOKEN_PREFIX);
|
|
|
|
+ sb.append(token);
|
|
|
|
+ String returnToken = sb.toString();
|
|
|
|
+ // 创建登录数据
|
|
|
|
+ createLoginRecord(token);
|
|
|
|
+ return returnToken;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 创建登录数据
|
|
|
|
+ *
|
|
|
|
+ * @param token jwt
|
|
|
|
+ */
|
|
|
|
+ public static void createLoginRecord(String token) {
|
|
|
|
+ Map<String, Object> map = getDetails(token);
|
|
|
|
+ Long user_id = (Long) map.get("id");
|
|
|
|
+ String type = (String) map.get("type");
|
|
|
|
+ // 第一次登录是创建,以后都是更新, 每个用户都有1个登录数据,但是能否使用要看过期时间
|
|
|
|
+ QueryWrapper<LoginRecord> qw = new QueryWrapper<>();
|
|
|
|
+ // qw.eq("user_id", user_id);
|
|
|
|
+ // qw.eq("type", type);
|
|
|
|
+ Map<String,Object> qm = new HashMap<>();
|
|
|
|
+ qm.put("user_id",user_id);
|
|
|
|
+ qm.put("type",type);
|
|
|
|
+ qw.allEq(qm);
|
|
|
|
+ LoginRecord histroy = jwtUtil.lrs.getOne(qw);
|
|
|
|
+ LocalDateTime last_login_time = LocalDateTime.now();
|
|
|
|
+ LocalDateTime expire_time = LocalDateTime.now().plusMinutes(EXPIRE_MIN);
|
|
|
|
+ if (null == histroy) {
|
|
|
|
+ // 创建数据
|
|
|
|
+ LoginRecord lr = new LoginRecord();
|
|
|
|
+ lr.setExpire_time(expire_time);
|
|
|
|
+ lr.setLast_login_time(last_login_time);
|
|
|
|
+ lr.setToken(token);
|
|
|
|
+ lr.setType(type);
|
|
|
|
+ lr.setUser_id(user_id);
|
|
|
|
+ jwtUtil.lrs.save(lr);
|
|
|
|
+ } else {
|
|
|
|
+ // 修改数据
|
|
|
|
+ LoginRecord lr = new LoginRecord();
|
|
|
|
+ lr.setExpire_time(expire_time);
|
|
|
|
+ lr.setLast_login_time(last_login_time);
|
|
|
|
+ lr.setToken(token);
|
|
|
|
+ lr.setId(histroy.getId());
|
|
|
|
+ jwtUtil.lrs.updateById(lr);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * token续期
|
|
|
|
+ *
|
|
|
|
+ * @param token jwt
|
|
|
|
+ */
|
|
|
|
+ public static void renewal(String token) {
|
|
|
|
+ Map<String, Object> map = getDetails(token);
|
|
|
|
+ Long user_id = (Long) map.get("id");
|
|
|
|
+ String type = (String) map.get("type");
|
|
|
|
+ LocalDateTime expire_time = LocalDateTime.now().plusMinutes(EXPIRE_MIN);
|
|
|
|
+ QueryWrapper<LoginRecord> qw = new QueryWrapper<>();
|
|
|
|
+ qw.eq("user_id", user_id).eq("type", type);
|
|
|
|
+ LoginRecord histroy = jwtUtil.lrs.getOne(qw);
|
|
|
|
+ if (null == histroy) {
|
|
|
|
+ // 没有数据,转至创建
|
|
|
|
+ createLoginRecord(token);
|
|
|
|
+ } else {
|
|
|
|
+ // 修改过期时间
|
|
|
|
+ LoginRecord lr = new LoginRecord();
|
|
|
|
+ lr.setExpire_time(expire_time);
|
|
|
|
+ lr.setId(histroy.getId());
|
|
|
|
+ jwtUtil.lrs.updateById(lr);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 校验token是否正确
|
|
|
|
+ *
|
|
|
|
+ * @param token 令牌
|
|
|
|
+ * @return 是否正确
|
|
|
|
+ */
|
|
|
|
+ public static void verify(String token) {
|
|
|
|
+ try {
|
|
|
|
+ // jwt先解密,如果解不开,那就不用往后继续查时间的问题了
|
|
|
|
+ JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ throw new CustomizationException(ExceptionEnum.TOKEN_ERROR);
|
|
|
|
+ }
|
|
|
|
+ // 再解开token,查看数据
|
|
|
|
+ Map<String, Object> map = getDetails(token);
|
|
|
|
+ Long user_id = (Long) map.get("id");
|
|
|
|
+ String type = (String) map.get("type");
|
|
|
|
+ QueryWrapper<LoginRecord> qw = new QueryWrapper<>();
|
|
|
|
+ qw.eq("user_id", user_id).eq("type", type);
|
|
|
|
+ LoginRecord histroy = jwtUtil.lrs.getOne(qw);
|
|
|
|
+ if (null == histroy) {
|
|
|
|
+ throw new CustomizationException(ExceptionEnum.NO_LOGIN_RECORD);
|
|
|
|
+ }
|
|
|
|
+ // 取出过期时间,和当前时间进行比较
|
|
|
|
+ LocalDateTime nowTime = LocalDateTime.now();
|
|
|
|
+ boolean is_before = histroy.getExpire_time().isBefore(nowTime);
|
|
|
|
+ if (!is_before) {
|
|
|
|
+ throw new CustomizationException(ExceptionEnum.TOKEN_INVALID);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获得token中的信息
|
|
|
|
+ *
|
|
|
|
+ * @return token中包含的名称
|
|
|
|
+ */
|
|
|
|
+ public static Map<String, Object> getDetails(String token) {
|
|
|
|
+ try {
|
|
|
|
+ DecodedJWT jwt = JWT.decode(token);
|
|
|
|
+ Map<String, Claim> map = jwt.getClaims();
|
|
|
|
+ Map<String, Object> returnMap = new HashMap<>();
|
|
|
|
+ for (Map.Entry<String, Claim> entry : map.entrySet()) {
|
|
|
|
+ String k = entry.getKey();
|
|
|
|
+ if (spcialKey.equals(k)) {
|
|
|
|
+ Long v = jwt.getClaim(k).asLong();
|
|
|
|
+ returnMap.put(k, v);
|
|
|
|
+ } else {
|
|
|
|
+ String v = jwt.getClaim(k).asString();
|
|
|
|
+ returnMap.put(k, v);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return returnMap;
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|