1、基于springboot,启动项目时生成秘钥对
@Configuration
public class Initiation implements CommandLineRunner {
@Autowired
private KeyConfiguration keyConfiguration;
@Override
public void run(String... args) throws Exception {
// 初始化jwt
Map<String, byte[]> keyMap = RsaKeyHelper.generateKey(keyConfiguration.getUserSecret());
keyConfiguration.setUserPriKey(keyMap.get("pri"));
keyConfiguration.setUserPubKey(keyMap.get("pub"));
}
}
2、登录时生成token并存放到redis白名单
public String login(String username, String password) throws Exception {
String token = null;
AbtUser params = new AbtUser();
params.setUsername(username);
params.setPassword(md5PasswordEncoder.encodePassword(password, CommonConstants.PASSWORD_SALT));
AbtUser user = userMapper.selectOne(params);
if (user != null && user.getStatus().equals(CommonConstants.GLOBAL_VALID)) {
AbtUserToken tokenByUser = userTokenService.getTokenByUserId(user.getId());
//从数据库获取最近登录的token,防止多次生成,没有则直接生成新的并存入数据库
//如果token创建日期距离本次登录超过六天,生成新的token并更新到数据库
if (tokenByUser == null || (new Date().getTime() - tokenByUser.getCreateTime().getTime()) / (1000 * 60 * 60 * 24) >= 6) {
token = JWTHelper.generateToken(
new JWTInfo(user.getId().toString(), user.getUsername(), DateUtil.parseString(new Date(), DateUtil.DEFAULT_DATE_FORMAT)),
keyConfiguration.getUserPriKey(), keyConfiguration.getExpire());
AbtUserToken abtUserToken = new AbtUserToken();
abtUserToken.setCreateTime(new Date());
abtUserToken.setUserId(user.getId());
abtUserToken.setToken(token);
userTokenService.save(abtUserToken);
} else if(tokenByUser.getToken() != null){
token = tokenByUser.getToken();
}
redisService.set(token, new Date(), (long) keyConfiguration.getShortExpire());//设置三十分钟过期
}
return token;
}
3、用户操作时判断token是否存在白名单
@Component
public class SecurityInterceptor implements HandlerInterceptor {
@Autowired
private KeyConfiguration keyConfiguration;
@Autowired
private RedisService redisService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader(CommonConstants.JWT_TOKEN_HEADER);
JWTInfo jwt = null;
try {
jwt = JWTHelper.getInfoFromToken(token, keyConfiguration.getUserPubKey());
} catch (Exception e) {
throw new BaseException(AdminErrorConstants.USER_NOT_LOGIN, "用户登录超时");
}
//存入token到redis进行长时间未操作的判断数据
boolean exists = redisService.exists(token);
if(exists){
Date time = (Date) redisService.get(token);
Long datePoor = 30l - getDatePoor(time, new Date());
if(datePoor > 0 && datePoor <= 29){
redisService.set(token,new Date(),(long)keyConfiguration.getShortExpire());
}
}else{
throw new BaseException(AdminErrorConstants.USER_NOT_LOGIN, "用户登录超时");
}
return true;
}
/**
* 返回时间差-分钟
* @param beforeDate
* @param nowDate
* @return
*/
private Long getDatePoor(Date beforeDate, Date nowDate) {
long nm = 1000 * 60;
// 获得两个时间的毫秒时间差异
long diff = nowDate.getTime() - beforeDate.getTime();
// 计算差多少秒//输出结果
long min = diff / nm;
return min;
}
}