|
@@ -20,12 +20,14 @@ import io.jsonwebtoken.Claims;
|
|
|
import io.jsonwebtoken.JwtBuilder;
|
|
import io.jsonwebtoken.JwtBuilder;
|
|
|
import io.jsonwebtoken.Jwts;
|
|
import io.jsonwebtoken.Jwts;
|
|
|
import io.jsonwebtoken.SignatureAlgorithm;
|
|
import io.jsonwebtoken.SignatureAlgorithm;
|
|
|
|
|
+import lombok.SneakyThrows;
|
|
|
import org.springblade.core.launch.constant.TokenConstant;
|
|
import org.springblade.core.launch.constant.TokenConstant;
|
|
|
import org.springblade.core.secure.BladeUser;
|
|
import org.springblade.core.secure.BladeUser;
|
|
|
-import org.springblade.core.tool.utils.Charsets;
|
|
|
|
|
-import org.springblade.core.tool.utils.Func;
|
|
|
|
|
-import org.springblade.core.tool.utils.StringPool;
|
|
|
|
|
-import org.springblade.core.tool.utils.WebUtil;
|
|
|
|
|
|
|
+import org.springblade.core.secure.constant.SecureConstant;
|
|
|
|
|
+import org.springblade.core.secure.exception.SecureException;
|
|
|
|
|
+import org.springblade.core.secure.provider.IClientDetails;
|
|
|
|
|
+import org.springblade.core.secure.provider.IClientDetailsService;
|
|
|
|
|
+import org.springblade.core.tool.utils.*;
|
|
|
|
|
|
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
@@ -48,9 +50,16 @@ public class SecureUtil {
|
|
|
private final static String USER_NAME = TokenConstant.USER_NAME;
|
|
private final static String USER_NAME = TokenConstant.USER_NAME;
|
|
|
private final static String ROLE_NAME = TokenConstant.ROLE_NAME;
|
|
private final static String ROLE_NAME = TokenConstant.ROLE_NAME;
|
|
|
private final static String TENANT_CODE = TokenConstant.TENANT_CODE;
|
|
private final static String TENANT_CODE = TokenConstant.TENANT_CODE;
|
|
|
|
|
+ private final static String CLIENT_ID = TokenConstant.CLIENT_ID;
|
|
|
private final static Integer AUTH_LENGTH = TokenConstant.AUTH_LENGTH;
|
|
private final static Integer AUTH_LENGTH = TokenConstant.AUTH_LENGTH;
|
|
|
private static String BASE64_SECURITY = Base64.getEncoder().encodeToString(TokenConstant.SIGN_KEY.getBytes(Charsets.UTF_8));
|
|
private static String BASE64_SECURITY = Base64.getEncoder().encodeToString(TokenConstant.SIGN_KEY.getBytes(Charsets.UTF_8));
|
|
|
|
|
|
|
|
|
|
+ private static IClientDetailsService clientDetailsService;
|
|
|
|
|
+
|
|
|
|
|
+ static {
|
|
|
|
|
+ clientDetailsService = SpringUtil.getBean(IClientDetailsService.class);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 获取用户信息
|
|
* 获取用户信息
|
|
|
*
|
|
*
|
|
@@ -84,6 +93,7 @@ public class SecureUtil {
|
|
|
if (claims == null) {
|
|
if (claims == null) {
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
|
|
+ String clientId = Func.toStr(claims.get(SecureUtil.CLIENT_ID));
|
|
|
Integer userId = Func.toInt(claims.get(SecureUtil.USER_ID));
|
|
Integer userId = Func.toInt(claims.get(SecureUtil.USER_ID));
|
|
|
String tenantCode = Func.toStr(claims.get(SecureUtil.TENANT_CODE));
|
|
String tenantCode = Func.toStr(claims.get(SecureUtil.TENANT_CODE));
|
|
|
String roleId = Func.toStr(claims.get(SecureUtil.ROLE_ID));
|
|
String roleId = Func.toStr(claims.get(SecureUtil.ROLE_ID));
|
|
@@ -91,6 +101,7 @@ public class SecureUtil {
|
|
|
String roleName = Func.toStr(claims.get(SecureUtil.ROLE_NAME));
|
|
String roleName = Func.toStr(claims.get(SecureUtil.ROLE_NAME));
|
|
|
String userName = Func.toStr(claims.get(SecureUtil.USER_NAME));
|
|
String userName = Func.toStr(claims.get(SecureUtil.USER_NAME));
|
|
|
BladeUser bladeUser = new BladeUser();
|
|
BladeUser bladeUser = new BladeUser();
|
|
|
|
|
+ bladeUser.setClientId(clientId);
|
|
|
bladeUser.setUserId(userId);
|
|
bladeUser.setUserId(userId);
|
|
|
bladeUser.setTenantCode(tenantCode);
|
|
bladeUser.setTenantCode(tenantCode);
|
|
|
bladeUser.setAccount(account);
|
|
bladeUser.setAccount(account);
|
|
@@ -206,6 +217,27 @@ public class SecureUtil {
|
|
|
return (null == user) ? StringPool.EMPTY : user.getTenantCode();
|
|
return (null == user) ? StringPool.EMPTY : user.getTenantCode();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取客户端id
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return tenantCode
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String getClientId() {
|
|
|
|
|
+ BladeUser user = getUser();
|
|
|
|
|
+ return (null == user) ? StringPool.EMPTY : user.getClientId();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取客户端id
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param request request
|
|
|
|
|
+ * @return tenantCode
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String getClientId(HttpServletRequest request) {
|
|
|
|
|
+ BladeUser user = getUser(request);
|
|
|
|
|
+ return (null == user) ? StringPool.EMPTY : user.getClientId();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 获取Claims
|
|
* 获取Claims
|
|
|
*
|
|
*
|
|
@@ -260,7 +292,7 @@ public class SecureUtil {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 创建jwt
|
|
|
|
|
|
|
+ * 创建令牌
|
|
|
*
|
|
*
|
|
|
* @param user user
|
|
* @param user user
|
|
|
* @param audience audience
|
|
* @param audience audience
|
|
@@ -269,6 +301,17 @@ public class SecureUtil {
|
|
|
* @return jwt
|
|
* @return jwt
|
|
|
*/
|
|
*/
|
|
|
public static String createJWT(Map<String, String> user, String audience, String issuer, boolean isExpire) {
|
|
public static String createJWT(Map<String, String> user, String audience, String issuer, boolean isExpire) {
|
|
|
|
|
+
|
|
|
|
|
+ String[] tokens = extractAndDecodeHeader();
|
|
|
|
|
+ assert tokens.length == 2;
|
|
|
|
|
+ String clientId = tokens[0];
|
|
|
|
|
+ String clientSecret = tokens[1];
|
|
|
|
|
+
|
|
|
|
|
+ // 校验客户端信息
|
|
|
|
|
+ if (!validateClient(clientId, clientSecret)) {
|
|
|
|
|
+ throw new SecureException("客户端认证失败!");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
|
|
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
|
|
|
|
|
|
|
|
long nowMillis = System.currentTimeMillis();
|
|
long nowMillis = System.currentTimeMillis();
|
|
@@ -287,6 +330,9 @@ public class SecureUtil {
|
|
|
//设置JWT参数
|
|
//设置JWT参数
|
|
|
user.forEach(builder::claim);
|
|
user.forEach(builder::claim);
|
|
|
|
|
|
|
|
|
|
+ //设置应用id
|
|
|
|
|
+ builder.claim(CLIENT_ID, clientId);
|
|
|
|
|
+
|
|
|
//添加Token过期时间
|
|
//添加Token过期时间
|
|
|
if (isExpire) {
|
|
if (isExpire) {
|
|
|
long expMillis = nowMillis + getExpire();
|
|
long expMillis = nowMillis + getExpire();
|
|
@@ -322,4 +368,56 @@ public class SecureUtil {
|
|
|
return (int) (getExpire() / 1000);
|
|
return (int) (getExpire() / 1000);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 客户端信息解码
|
|
|
|
|
+ */
|
|
|
|
|
+ @SneakyThrows
|
|
|
|
|
+ public static String[] extractAndDecodeHeader() {
|
|
|
|
|
+ // 获取请求头客户端信息
|
|
|
|
|
+ String header = Objects.requireNonNull(WebUtil.getRequest()).getHeader(SecureConstant.BASIC_HEADER_KEY);
|
|
|
|
|
+ if (header == null || !header.startsWith(SecureConstant.BASIC_HEADER_PREFIX)) {
|
|
|
|
|
+ throw new SecureException("No client information in request header");
|
|
|
|
|
+ }
|
|
|
|
|
+ byte[] base64Token = header.substring(6).getBytes(Charsets.UTF_8_NAME);
|
|
|
|
|
+
|
|
|
|
|
+ byte[] decoded;
|
|
|
|
|
+ try {
|
|
|
|
|
+ decoded = Base64.getDecoder().decode(base64Token);
|
|
|
|
|
+ } catch (IllegalArgumentException var7) {
|
|
|
|
|
+ throw new RuntimeException("Failed to decode basic authentication token");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String token = new String(decoded, Charsets.UTF_8_NAME);
|
|
|
|
|
+ int index = token.indexOf(StringPool.COLON);
|
|
|
|
|
+ if (index == -1) {
|
|
|
|
|
+ throw new RuntimeException("Invalid basic authentication token");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return new String[]{token.substring(0, index), token.substring(index + 1)};
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取请求头中的客户端id
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String getClientIdFromHeader() {
|
|
|
|
|
+ String[] tokens = extractAndDecodeHeader();
|
|
|
|
|
+ assert tokens.length == 2;
|
|
|
|
|
+ return tokens[0];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 校验Client
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param clientId 客户端id
|
|
|
|
|
+ * @param clientSecret 客户端密钥
|
|
|
|
|
+ * @return boolean
|
|
|
|
|
+ */
|
|
|
|
|
+ private static boolean validateClient(String clientId, String clientSecret) {
|
|
|
|
|
+ IClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
|
|
|
|
|
+ if (clientDetails != null) {
|
|
|
|
|
+ return StringUtil.equals(clientId, clientDetails.getClientId()) && StringUtil.equals(clientSecret, clientDetails.getClientSecret());
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|