PS:作者是小白能接触到的就只会这样写。勿喷。
前提
思路: 结合io流将登录token存储到配置文件中,不将token存储到浏览器端,从而避免盗取。
下面jwt的学习可以参考下这个:
JWT工具类
java
@Component
public class JWTtUtils {
public static final String USER_NAME = "username";
public static final String PASS_WORD = "password";
public static final String CREATE_TIME = "createTime";
public static final String SIGN_KEY = "QHX2004"; // 解析key
/**
* 用用户名和密码生成JWT
*
* @param username
* @param password
* @return
*/
public String generatorJWTFromUserNameAndPassword(String username,String password){
HashMap<String, Object> hashMap = new HashMap<>(); // 生成map
hashMap.put(USER_NAME,username);
hashMap.put(PASS_WORD,password);
hashMap.put(CREATE_TIME,new Date());
return generatorJWTFromUserNameAndPassword(hashMap);
}
/**
* 生成jwt过期时间,1个月
*
* @param
* @return
*/
private Date generatorExpirationDate() {
return new Date(System.currentTimeMillis() + (1000L * 60 * 60 *24 *30));
}
/**
* 用用户名和密码生成jwt
*
* @param paramMap
* @return
*/
private String generatorJWTFromUserNameAndPassword(HashMap<String, Object> paramMap) {
JwtBuilder jwtBuilder = Jwts.builder()
.setClaims(paramMap)
.setExpiration(generatorExpirationDate()) // 设置过期时间
.signWith(SignatureAlgorithm.HS512,SIGN_KEY);
return jwtBuilder.compact(); // 拿到token
}
/**
* 解析token拿到Claims
*
*
* @param token
* @return
*/
private Claims getClaimsFromToken(String token){
Claims claims = Jwts.parser()
.setSigningKey(SIGN_KEY)
.parseClaimsJws(token)
.getBody();
return claims;
}
/**
* 校验token是否过期
*
* @param token
* @return
*/
// 过期返回true
public boolean checkTokenIsOverdue(String token){
Claims claims = getClaimsFromToken(token);
Date date = claims.getExpiration();
return date.getTime() < new Date().getTime();
}
/**
* 刷新token:重新生成一个token
*
* @param
* @return
*/
public String flushToken(String token){
Claims claims = getClaimsFromToken(token);
String username = (String) claims.get(USER_NAME);
String password = (String)claims.get(PASS_WORD);
return generatorJWTFromUserNameAndPassword(username,password);
}
}
IO工具类
java
public class IOUtils {
public static final String FILE_NAME = "conf.properties";
/**
* 配置文件读取
* @param key
* @return value
*/
public static String getPropertiesKey(String key) {
return getKey(key);
}
/**
* 配置文件读取
*
* @param key
* @return
*/
private static String getKey(String key) {
Properties properties = new Properties();
File file = new File(FILE_NAME);
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
properties.load(inputStream); // 其实已经将配置文件拿到手了
} catch (IOException e) {
e.printStackTrace();
}finally {
if(inputStream != null){ // 还是这样关比较好,万一报错就tm关不了
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return properties.getProperty(key);
}
/**
* 配置文件设置
*
* @param key
* @param value
* @return
*/
public static boolean setPropertiesKey(String key,String value) {
// 判断key是否有重复
String key1 = getKey(key);
if(key1 == null){
return setKey(key,value); // 把核心业务逻辑抽出来
}
return false;
}
/**
* 配置文件设置
*
* @param key
* @param value
* @return boolean
*/
private static boolean setKey(String key, String value) {
Properties properties = new Properties();
File file = new File(FILE_NAME); // 其实有其他配置可以同意下yaml文件里面配置,然后这里面读取,好统一调配。
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(file,true);
properties.setProperty(key, value); // 存进map里面
properties.store(fileWriter,""); // 将map对应的键值对写进输出流。
} catch (IOException e) {
// 卧槽我加入设置key,value失败,肯定调到这个逻辑
return false;
} finally {
if (fileWriter != null) { // 还是这样关比较好,万一报错就tm关不了
try {
fileWriter.flush();
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
}
}
测试文件
java
@SpringBootTest
class IoDemoApplicationTests {
@Test
void contextLoads() {
// 用户第一登录 ----,我们这里浏览器端不存token,只存用户名,更安全。
String username = "qhx2005";
String password = "123456";
// 生成jwt
JWTtUtils jwTtUtils = new JWTtUtils();
String token = jwTtUtils.generatorJWTFromUserNameAndPassword(username, password);
// 将jwt存进配置文件
boolean success = IOUtils.setPropertiesKey(username, token);
System.out.println("存进配置文件成功状态:"+success);
assert success;
// 用户登录后访问其他页面。检验token过期,拿出配置文件是否存在----
// 获取token
String token1 = IOUtils.getPropertiesKey(username);
System.out.println(token1);
// 检验token是否过期
boolean overdue = jwTtUtils.checkTokenIsOverdue(token);
// 本来这里如果token过期,我们响应一个状态码,让前端axios过滤器捕获到,删除本地username,重定向到登录页。
System.out.println("已经过期:"+overdue);
}
}