1 使用
1 项目里面添加依赖
代码语言:javascript复制 <!-- Token生成与解析-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
2 写工具类
代码语言:javascript复制package com.ruoyi.framework.web.service;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.AddressUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import eu.bitwalker.useragentutils.UserAgent;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
/**
* token验证处理
* 当前类作为bean 对象,让其他类调用 进行使用
*
* 对令牌 进行操作
* @author jing
* 已录
*/
@Component
public class TokenService
{
// 令牌自定义标识 Authorization
@Value("${token.header}")
private String header;
// 令牌秘钥 abcdefghijklmnopqrstuvwxyz
@Value("${token.secret}")
private String secret;
// 令牌有效期(默认30分钟)
@Value("${token.expireTime}")
private int expireTime;
// 秒
protected static final long MILLIS_SECOND = 1000;
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
// redis 工具类
@Autowired
private RedisCache redisCache;
/**
* 根据前端传过来的 token 获取用户身份信息
* 根据request 获取到用户的信息
*
* 也就是解析 token,获取用户信息
* @return 用户信息
*/
public LoginUser getLoginUser(HttpServletRequest request)
{
// 获取请求携带的令牌
String token = getToken(request);
if (StringUtils.isNotEmpty(token))
{
try
{
// 解析token
Claims claims = parseToken(token);
// 解析对应的权限以及用户信息 返回给用户的是uuid
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
// redis里面缓存的key, 根据uuid 拼接返回 redis 所存放的key
String userKey = getTokenKey(uuid);
// 根据key 从redis 里面 获取用户的具体信息
LoginUser user = redisCache.getCacheObject(userKey);
return user;
}
catch (Exception e)
{
}
}
return null;
}
/**
* 获取请求token
* 根据request 获取到前端传过来的 token
* @param request
* @return token
*/
private String getToken(HttpServletRequest request)
{
// # 令牌自定义标识
// header: Authorization
// 从request 里面获取到Authorization变量的值
String token = request.getHeader(header);// 获取到token的具体值
// 令牌前缀 TOKEN_PREFIX = "Bearer "
if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
{
token = token.replace(Constants.TOKEN_PREFIX, "");
}
return token;
}
/**
* 从令牌中获取数据声明
*将前端传过来的token 作为参数 ,传入
* @param token 令牌
* @return 数据声明
*/
private Claims parseToken(String token)
{
// 使用第三方的 工具 解析token ,获取到 具体数据
return Jwts.parser()
// 密钥
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
/**
* 获取请求token 的key
* 就是在redis里面 存的 key
* LOGIN_TOKEN_KEY = "login_tokens:"
*/
private String getTokenKey(String uuid)
{
return CacheConstants.LOGIN_TOKEN_KEY uuid;
}
/**
* 设置用户身份信息
* 将用户信息存储到reids 里面
*/
public void setLoginUser(LoginUser loginUser)
{
if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken()))
{
// 往redis 里面设置
refreshToken(loginUser);
}
}
/**
* 刷新令牌有效期
*
* @param loginUser 登录信息
*/
public void refreshToken(LoginUser loginUser)
{
// 登录时间
loginUser.setLoginTime(System.currentTimeMillis());
// 设置 过期时间
loginUser.setExpireTime(loginUser.getLoginTime() expireTime * MILLIS_MINUTE);
// 根据uuid将loginUser缓存
// loginUser.getToken() = 用户唯一标识 uuid 就是登陆成功返回给前端的token 里面存放的是uuid
// 具体的信息是存放在 redis里面
String userKey = getTokenKey(loginUser.getToken());
// 将用户的信息,保存到redis里面
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
}
/**
* 删除用户身份信息
* 根据前端传过来的 token 唯一标志 uuid
* redis 里面进行删除token
*/
public void delLoginUser(String token)
{
if (StringUtils.isNotEmpty(token))
{
// 获取请求token 的key
// * 就是在redis里面 存的 key
String userKey = getTokenKey(token);
redisCache.deleteObject(userKey);
}
}
/**
* 创建令牌
* 根据登录成功的用户 创建令牌
* @param loginUser 用户信息
* @return 令牌
*/
public String createToken(LoginUser loginUser)
{
String token = IdUtils.fastUUID();// 随机的uuid
// 返回给前端的 token 里面存放的就是 uuid
loginUser.setToken(token);
setUserAgent(loginUser);// 设置代理
// 将用户的信息存储到 redis里面
refreshToken(loginUser);// 刷新缓存
Map<String, Object> claims = new HashMap<>();
// Constants.LOGIN_USER_KEY 令牌前缀 login_user_key
claims.put(Constants.LOGIN_USER_KEY, token);
return createToken(claims);
}
/**
* 设置用户代理信息
*
* @param loginUser 登录信息
*/
public void setUserAgent(LoginUser loginUser)
{
// 根据request 获取代理对象
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
// 根据request 获取 当前请求的 IP
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
loginUser.setIpaddr(ip);
loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));//登录地点
loginUser.setBrowser(userAgent.getBrowser().getName());// 浏览器类型
loginUser.setOs(userAgent.getOperatingSystem().getName());// 操作系统
}
/**
* 从数据声明生成令牌
* 使用数据声明,密钥生成token
*
* claims 这个里面存放的是 uuid
* @param claims 数据声明
* @return 令牌
*/
private String createToken(Map<String, Object> claims)
{
String token = Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret).compact();
return token;
}
/**
* 验证令牌有效期,相差不足20分钟,自动刷新缓存
*
* @param loginUser
* @return 令牌
*/
public void verifyToken(LoginUser loginUser)
{
long expireTime = loginUser.getExpireTime();// 过期时间
long currentTime = System.currentTimeMillis();// 当前时间
if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
// 如果过期时间 间隔在设置的间隔之内
{
// 刷新缓存
refreshToken(loginUser);
}
}
/**
* 从令牌中获取用户名
* 将前端传过来的token 作为参数 ,传入
* @param token 令牌
* @return 用户名
*/
public String getUsernameFromToken(String token)
{
Claims claims = parseToken(token);
return claims.getSubject();
}
}
3 使用工具类
使用这个工具类 生成token 和 解析token