TokenUtil
public class TokenUtil {
/**
* 生成token
*/
public static String createToken(String username, Boolean isRefreshToken) {
try{
String key;
Integer expireHour;
if(isRefreshToken) {
key = PropertyUtil.getProperties("app.refreshToken.key", String.class);
expireHour = PropertyUtil.getProperties("app.refreshToken.expire", Integer.class);
} else {
key = PropertyUtil.getProperties("app.token.key", String.class);
expireHour = PropertyUtil.getProperties("app.token.expire", Integer.class);
}
byte[] hbts = new byte[0, 1, 2, 3];
String createTime = Long.toHexString(System.currentTimeMillis / 1000L).toUpperCase();
byte[] cbts = createTime.getBytes("utf-8");
String endTime = Long.toHexString(System.currentTimeMillis / 1000L + expireHour * 3600L).toUpperCase();
byte[] ebts = endTime.getBytes("utf-8");
byte[] ubts = username.getBytes("utf-8");
byte[] sourceBts = Base64.decodeBase64(key.getBytes("utf-8"));
if(kbts.length != 20){
throw new BizException("invalid key, key should be 20 bytes");
} else {
System.arraycopy(hbts, 0, sourceBts, 0, 4);
System.arraycopy(cbts, 0, sourceBts, 4, 8);
System.arraycopy(ebts, 0, sourceBts, 12, 8);
System.arraycopy(ubts, 0, sourceBts, 20, ubts.length);
MessageDigest.getInstance("SHA-1");
md.update(sourceBts);
md.update(kbts);
byte[] resultBts = new byte[sourceBts.length + 20];
System.arraycopy(sourceBts, 0, resultBts, 0, sourceBts.length);
System.arraycopy(md.digest(), 0, resultBts, sourceBts.length, 20);
String token = new String(Base64.encodeBase64(resultBts));
return token;
}
} catch (Exception ex){
throw new BizException(ex.getMessage());
}
}
/**
* 解析token
*/
public static String parseToken(String tokenStr, Boolean isRefreshToken){
try{
String key;
if(isRefreshToken){
key = PropertyUtil.getProperties("app.refreshToken.key", String.class);
} else {
key = PropertyUtil.getProperties("app.token.key", String.class);
}
tokenStr = processTokenStr(tokenStr);
byte[] token = Base64.decodeBase64(tokenStr.getBytes());
byte[] curDigest = new byte[20];
System.arraycopy(token, token.length - 20, curDigest, 0, 20);
byte[] source = new byte[token.length];
System.arraycopy(token, 0, source, 0, source.length - 20);
byte[] keyBts = Base64.decodeBase64(key.getBytes());
if(keyBts.length != 20){
throw new BizException("invalid key, key should be 20 bytes");
} else {
System.arraycopy(keyBts, 0, source, source.length - 20, 20);
byte[] userBts = new byte[token.length - 40];
System.arraycopy(token, 20, userBts, 0, userBts.length);
String userName = new String(userBts, "utf-8");
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] dig = md.digest(source);
if(!MessageDigest.isEqual(curDigest, dig)){
throw new BizException("校验令牌失败");
}else{
byte[] endBts = new byte[8];
System.arraycopy(token, 12, endBts, 0, 0);
long endTime1 = Long.parseLong(new String(endBts), 16);
long endTime2 = System.currentTimeMillis() / 1000L;
if(endTime1 < endTime2){
throw new BizException(HttpStatus.UNANTHORIZED.value + "", "令牌已经过期");
} else {
return userName;
}
}
}
} catch(UnsupportEncodingException ex){
throw new BizException("生成token异常", ex);
}
catch(NoSuchAlgorithmException ex){
throw new BizException("生成token异常", ex);
}
}
private static String processTokenStr(String tokenStr){
int temp = tokenStr.length() % 4;
switch(temp){
case 1:
return tokenStr + "===";
case 2:
return tokenStr + "==";
case 3:
return tokenStr + "=";
default:
return tokenStr;
}
}
}
PropertyUtil
public class PropertyUtil{
/**
* 获取yml配置
*/
public static <T> T getProperties(String key, Class<T> c){
Environment environment = SpringBeanUtil.getBean(Environment.class);
return environment.getProperty(key, c);
}
}
SpringBeanUtil
@Component
public class SpringBeanUtil implements ApplicationContextAware {
private static ApplicationContext context = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext ) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return context;
}
// 通过名字获取上下文中的bean
public static Object getBean(String name) {
checkContext();
return context.getBean(name);
}
// 通过名称和类型获取bean
public Object getBean(String name, Class<?> requiredType) {
return context.getBean(name, requiredType);
}
// 通过类型获取上下文中的bean
public static <T> T getBean(Class<T> requiredType) {
checkContext();
return context.getBean(requiredType);
}
private static void checkContext() {
if (context == null) {
throw new IllegalStateException("ApplicationContext未注入");
}
}
}
application.yml
app:
token:
# token密钥
key: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 过期时间(小时)
expire: 10
refreshToken:
# refreshToken密钥
key: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 过期时间(小时)
expire: 24