com.lx.boot.web.AuthUtil Maven / Gradle / Ivy
package com.lx.boot.web;
import com.lx.annotation.Note;
import com.lx.boot.OS;
import com.lx.entity.JwtInfo;
import com.lx.entity.UserInfo;
import com.lx.util.LX;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.concurrent.TimeUnit;
import static com.lx.constant.DefaultBaseConstant.*;
import static com.lx.constant.DefaultRedisConstant.RedisPrefix.*;
@Slf4j
@Component
@Note("登录信息工具类")
public class AuthUtil {
@Autowired
private StringRedisTemplate stringRedisTemplate;
//说明: 生成token
/**{ ylx } 2022/4/1 13:43 */
@Note("登录时创建token, 参数可为UserInfo的子类")
public String createToken(@Valid @NotNull(message = "用户信息不能为空!")UserInfo userInfo){
String token = LX.uuid32();
int time = OS.getIntProperty(SERVER_TOKEN_TIMEOUT_MINUTES+"."+userInfo.getTokenType(),"0");
if (time <=0){
time = OS.getIntProperty(SERVER_TOKEN_TIMEOUT_MINUTES,"600");
}
// 保存用户信息
stringRedisTemplate.opsForValue().set(USER_LOGIN_INFO_USER_INFO_APPID_BY_TOKEN+token,LX.toJSONString(userInfo),time, TimeUnit.MINUTES);
// 删除上次token 默认单个地方登录
if (!OS.getPropertyIsTrue(SERVER_AT_SAME_TIME_LOGIN,"false")){
deleteToken(userInfo);
}
// 保存用户id和用户类型对应的token
stringRedisTemplate.opsForValue().set(USER_LOGIN_INFO_TOKEN_BY_USER_ID_USER_TYPE+userInfo.getUserId()+userInfo.getTokenType(),token,time, TimeUnit.MINUTES);
return token;
}
//说明: 删除用户登录的token
/**{ ylx } 2022/4/1 14:04 */
@Note("删除用户登录的token")
public void deleteToken(@Valid @NotNull(message = "用户信息不能为空!") UserInfo userInfo){
String token = (String) stringRedisTemplate.opsForValue().get(USER_LOGIN_INFO_TOKEN_BY_USER_ID_USER_TYPE + userInfo.getUserId() + userInfo.getTokenType());
stringRedisTemplate.delete(USER_LOGIN_INFO_USER_INFO_APPID_BY_TOKEN+token);
}
//说明: 获取用户信息
/**{ ylx } 2022/4/1 11:38 */
@Note("获取用户信息")
public UserInfo getUserInfo(HttpServletRequest request){
return getUserInfo(UserInfo.class, request);
}
//说明: 获取用户信息
/**{ ylx } 2022/4/1 11:38 */
@Note("获取用户信息, T为UserInfo的子类")
public T getUserInfo(Class t, HttpServletRequest request){
try {
String token = request.getHeader(AUTHORIZATION);
if (LX.isEmpty(token)){
return null;
}
if (token.startsWith(JWT_HEADER)){
//jwt Token
return (T) getJwtUserInfo(token);
}
return LX.toObj(t, stringRedisTemplate.opsForValue().get(USER_LOGIN_INFO_USER_INFO_APPID_BY_TOKEN + token));
}catch (Exception e){
log.error("获取用户信息时发生错误!", e);
return null;
}
}
@Note("登录时创建JWT token, 参数可为UserInfo的子类 注意:该类型未控制用户在多个位置同时登录")
public String createJwtToken(@Valid @NotNull(message = "用户信息不能为空!")UserInfo userInfo){
int time = OS.getIntProperty(SERVER_TOKEN_TIMEOUT_MINUTES+"."+userInfo.getTokenType(),"0");
if (time <=0){
time = OS.getIntProperty(SERVER_TOKEN_TIMEOUT_MINUTES,"600");
}
return createJwtToken(userInfo, TimeUnit.MINUTES, time);
}
public static void main(String[]args){
System.out.println((char) (byte)46);
}
private final static String JWT_HEADER = base64UrlEncode("{\"alg\": \"HS256\",\"typ\": \"JWT\"}");
@Note("创建jwt")
private static String createJwtToken(UserInfo userInfo,TimeUnit timeUnit, long time){
JwtInfo jwtInfo = new JwtInfo(userInfo,timeUnit,time);
String payloadJson = LX.toJSONString(jwtInfo);
String payload = base64UrlEncode(payloadJson);
String key = OS.getProperty(SERVER_JWT_KEY,DEFAULT_SERVER_JWT_KEY);
byte[] res = LX.HmacSha.HmacSHA256.encode(key.getBytes(StandardCharsets.UTF_8),JWT_HEADER.getBytes(StandardCharsets.UTF_8),new byte[]{(byte)46},payload.getBytes(StandardCharsets.UTF_8));
return JWT_HEADER+"."+payload+"."+base64UrlEncode(res);
}
@Note("通过jwt获取用户信息")
private static UserInfo getJwtUserInfo(String token){
if (LX.isEmpty(token)){
return null;
}
String[] split = token.split("\\.");
if (split.length != 3){
return null;
}
String header = split[0];
String payload = split[1];
String key = OS.getProperty(SERVER_JWT_KEY,DEFAULT_SERVER_JWT_KEY);
byte[] res = LX.HmacSha.HmacSHA256.encode(key.getBytes(StandardCharsets.UTF_8),header.getBytes(StandardCharsets.UTF_8),new byte[]{(byte)46},payload.getBytes(StandardCharsets.UTF_8));
if (split[2].equals(base64UrlEncode(res))){
JwtInfo jwtInfo = LX.toObj(JwtInfo.class, LX.decode(split[1]));
if (!jwtInfo.expired()){
return jwtInfo.getUserInfo();
}
}
return null;
}
@Note("使用无填充的 base64URL 进行编码")
private static String base64UrlEncode(byte[] data){
return Base64.getUrlEncoder().withoutPadding().encodeToString(data);
}
private static String base64UrlEncode(String data){
return Base64.getUrlEncoder().withoutPadding().encodeToString(data.getBytes(StandardCharsets.UTF_8));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy