123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- package com.free.utils;
- 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.baomidou.mybatisplus.core.toolkit.StringUtils;
- import com.free.config.CustomizationException;
- import com.free.config.ExceptionEnum;
- import com.free.entity.system.LoginRecord;
- 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 javax.servlet.http.HttpServletRequest;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
- @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!@#";
- @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();
- 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;
- }
- /**
- * 注销用户,退出登录
- * 将token置空,在校验的时候会处理没有token的情况
- *
- * @param token
- */
- public static void logOff(String token) {
- Map<String, Object> map = getDetails(token);
- String user_id = (String) map.get("id");
- String type = (String) map.get("type");
- QueryWrapper<LoginRecord> qw = new QueryWrapper<>();
- qw.eq("user_id", user_id);
- qw.eq("type", type);
- LoginRecord record = jwtUtil.lrs.getOne(qw);
- // 没找到数据不需要处理
- if (null == record) {
- return;
- }
- // token不一致,不需要处理
- String dbToken = record.getToken();
- if (null == dbToken || !dbToken.equals(token)) {
- return;
- }
- // token置空
- LoginRecord lr = new LoginRecord();
- lr.setToken(null);
- lr.setId(record.getId());
- jwtUtil.lrs.updateById(lr);
- }
- /**
- * 创建登录数据
- *
- * @param token jwt
- */
- public static void createLoginRecord(String token) {
- Map<String, Object> map = getDetails(token);
- String user_id = (String) 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);
- LoginRecord histroy = jwtUtil.lrs.getOne(qw);
- // 准备数据
- LocalDateTime last_time = LocalDateTime.now();
- LocalDateTime expire_time = LocalDateTime.now().plusMinutes(EXPIRE_MIN);
- HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
- String ip = request.getRemoteAddr();
- if (null == histroy) {
- // 创建数据
- LoginRecord lr = new LoginRecord();
- lr.setExpire_time(expire_time);
- lr.setLast_time(last_time);
- lr.setToken(token);
- lr.setType(type);
- lr.setUser_id(user_id);
- lr.setLast_ip(ip);
- jwtUtil.lrs.save(lr);
- } else {
- // 修改数据
- LoginRecord lr = new LoginRecord();
- lr.setExpire_time(expire_time);
- lr.setLast_time(last_time);
- lr.setToken(token);
- lr.setLast_ip(ip);
- lr.setId(histroy.getId());
- jwtUtil.lrs.updateById(lr);
- }
- }
- /**
- * token续期
- *
- * @param token jwt
- */
- public static void renewal(String token) {
- Map<String, Object> map = getDetails(token);
- String user_id = (String) 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);
- // 准备数据
- LocalDateTime expire_time = LocalDateTime.now().plusMinutes(EXPIRE_MIN);
- LocalDateTime last_time = LocalDateTime.now();
- HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
- String ip = request.getRemoteAddr();
- if (null == histroy) {
- // 没有数据,转至创建
- createLoginRecord(token);
- } else {
- // 修改过期时间,使用时间,使用ip
- LoginRecord lr = new LoginRecord();
- lr.setExpire_time(expire_time);
- lr.setId(histroy.getId());
- lr.setLast_ip(ip);
- lr.setLast_time(last_time);
- lr.setToken(token);
- jwtUtil.lrs.updateById(lr);
- }
- }
- /**
- * 校验token是否正确
- *
- * @param token 令牌
- * @return 是否正确
- */
- public static void verify(String token) {
- // 解开token,查看数据
- Map<String, Object> map = getDetails(token);
- String user_id = (String) 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);
- }
- // 获取数据库的token
- String dbToken = histroy.getToken();
- if (null == dbToken) {
- throw new CustomizationException(ExceptionEnum.ACCOUNT_IS_LOGOUT);
- }
- // 取出过期时间,和当前时间进行比较
- LocalDateTime nowTime = LocalDateTime.now();
- boolean is_after = histroy.getExpire_time().isAfter(nowTime);
- if (!is_after) {
- throw new CustomizationException(ExceptionEnum.TOKEN_INVALID);
- }
- // token对比,如果时间允许,但是token码不一致,则说明在其他地点登录
- if (!dbToken.equals(token)) {
- throw new CustomizationException(ExceptionEnum.OTHER_PLACE_LOGIN);
- }
- // 如果需要校准 ip,再加上即可
- }
- /**
- * 获得token中的信息
- *
- * @return token中包含的名称
- */
- public static Map<String, Object> getDetails(String token) {
- if (null == token) {
- token = getToken();
- }
- 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();
- String v = jwt.getClaim(k).asString();
- returnMap.put(k, v);
- }
- return returnMap;
- } catch (Exception e) {
- return null;
- }
- }
- /**
- * 根据请求头获取token
- *
- * @return
- */
- public static String getToken() {
- HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
- String tokenHeader = request.getHeader(TOKEN_HEADER);
- if (StringUtils.isBlank(tokenHeader)) {
- throw new CustomizationException(ExceptionEnum.TOKEN_NOT_FOUND);
- }
- String token = tokenHeader.replace(JwtUtil.TOKEN_PREFIX, "");
- if (StringUtils.isBlank(tokenHeader)) {
- throw new CustomizationException(ExceptionEnum.TOKEN_NOT_FOUND);
- }
- return token;
- }
- }
|