|
|
@@ -0,0 +1,337 @@
|
|
|
+package org.zhongzheng.common.secure;
|
|
|
+
|
|
|
+//
|
|
|
+// Source code recreated from a .class file by IntelliJ IDEA
|
|
|
+// (powered by FernFlower decompiler)
|
|
|
+//
|
|
|
+
|
|
|
+
|
|
|
+import io.jsonwebtoken.Claims;
|
|
|
+import io.jsonwebtoken.JwtBuilder;
|
|
|
+import io.jsonwebtoken.Jwts;
|
|
|
+import io.jsonwebtoken.SignatureAlgorithm;
|
|
|
+
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
+import java.security.Key;
|
|
|
+import java.util.Base64;
|
|
|
+import java.util.Calendar;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+import javax.crypto.spec.SecretKeySpec;
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import org.zhongzheng.common.env.TokenConstants;
|
|
|
+import org.zhongzheng.common.secure.ZhongZhengUser;
|
|
|
+import org.zhongzheng.common.secure.TokenInfo;
|
|
|
+import org.zhongzheng.common.secure.SecureException;
|
|
|
+import org.zhongzheng.common.secure.ZhongZhengTokenProperties;
|
|
|
+import org.zhongzheng.common.secure.IClientDetails;
|
|
|
+import org.zhongzheng.common.secure.IClientDetailsService;
|
|
|
+import org.zhongzheng.common.secure.AesUtil;
|
|
|
+import org.zhongzheng.common.utils.Charsets;
|
|
|
+import org.zhongzheng.common.utils.Func;
|
|
|
+import org.zhongzheng.common.utils.SpringUtil;
|
|
|
+import org.zhongzheng.common.utils.StringUtil;
|
|
|
+import org.zhongzheng.common.utils.WebUtil;
|
|
|
+
|
|
|
+public class SecureUtil {
|
|
|
+ private static final String ZHONGZHENG_USER_REQUEST_ATTR = "_ZHONGZHENG_USER_REQUEST_ATTR_";
|
|
|
+ private static final String HEADER = "blade-auth";
|
|
|
+ private static final String BEARER = "bearer";
|
|
|
+ private static final String CRYPTO = "crypto";
|
|
|
+ private static final String ACCOUNT = "account";
|
|
|
+ private static final String USER_ID = "user_id";
|
|
|
+ private static final String ROLE_ID = "role_id";
|
|
|
+ private static final String DEPT_ID = "dept_id";
|
|
|
+ private static final String USER_NAME = "user_name";
|
|
|
+ private static final String ROLE_NAME = "role_name";
|
|
|
+ private static final String TENANT_ID = "tenant_id";
|
|
|
+ private static final String CLIENT_ID = "client_id";
|
|
|
+ private static final Integer AUTH_LENGTH;
|
|
|
+ private static IClientDetailsService CLIENT_DETAILS_SERVICE;
|
|
|
+ private static ZhongZhengTokenProperties TOKEN_PROPERTIES;
|
|
|
+ private static String BASE64_SECURITY;
|
|
|
+
|
|
|
+ public SecureUtil() {
|
|
|
+ }
|
|
|
+
|
|
|
+ private static IClientDetailsService getClientDetailsService() {
|
|
|
+ if (CLIENT_DETAILS_SERVICE == null) {
|
|
|
+ CLIENT_DETAILS_SERVICE = (IClientDetailsService)SpringUtil.getBean(IClientDetailsService.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ return CLIENT_DETAILS_SERVICE;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static ZhongZhengTokenProperties getTokenProperties() {
|
|
|
+ if (TOKEN_PROPERTIES == null) {
|
|
|
+ TOKEN_PROPERTIES = (ZhongZhengTokenProperties)SpringUtil.getBean(ZhongZhengTokenProperties.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ return TOKEN_PROPERTIES;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getBase64Security() {
|
|
|
+ if (BASE64_SECURITY == null) {
|
|
|
+ BASE64_SECURITY = Base64.getEncoder().encodeToString(getTokenProperties().getSignKey().getBytes(Charsets.UTF_8));
|
|
|
+ }
|
|
|
+
|
|
|
+ return BASE64_SECURITY;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static ZhongZhengUser getUser() {
|
|
|
+ HttpServletRequest request = WebUtil.getRequest();
|
|
|
+ if (request == null) {
|
|
|
+ return null;
|
|
|
+ } else {
|
|
|
+ Object zzUser = request.getAttribute("_ZHONGZHENG_USER_REQUEST_ATTR_");
|
|
|
+ if (zzUser == null) {
|
|
|
+ zzUser = getUser(request);
|
|
|
+ if (zzUser != null) {
|
|
|
+ request.setAttribute("_ZHONGZHENG_USER_REQUEST_ATTR_", zzUser);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (ZhongZhengUser)zzUser;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static ZhongZhengUser getUser(HttpServletRequest request) {
|
|
|
+ Claims claims = getClaims(request);
|
|
|
+ if (claims == null) {
|
|
|
+ return null;
|
|
|
+ } else {
|
|
|
+ String clientId = Func.toStr(claims.get("client_id"));
|
|
|
+ Long userId = Func.toLong(claims.get("user_id"));
|
|
|
+ String tenantId = Func.toStr(claims.get("tenant_id"));
|
|
|
+ String roleId = Func.toStr(claims.get("role_id"));
|
|
|
+ String deptId = Func.toStr(claims.get("dept_id"));
|
|
|
+ String account = Func.toStr(claims.get("account"));
|
|
|
+ String roleName = Func.toStr(claims.get("role_name"));
|
|
|
+ String userName = Func.toStr(claims.get("user_name"));
|
|
|
+ ZhongZhengUser zzUser = new ZhongZhengUser();
|
|
|
+ zzUser.setClientId(clientId);
|
|
|
+ zzUser.setUserId(userId);
|
|
|
+ zzUser.setTenantId(tenantId);
|
|
|
+ zzUser.setAccount(account);
|
|
|
+ zzUser.setRoleId(roleId);
|
|
|
+ zzUser.setDeptId(deptId);
|
|
|
+ zzUser.setRoleName(roleName);
|
|
|
+ zzUser.setUserName(userName);
|
|
|
+ return zzUser;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static boolean isAdministrator() {
|
|
|
+ return StringUtil.containsAny(getUserRole(), new CharSequence[]{"administrator"});
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Long getUserId() {
|
|
|
+ ZhongZhengUser user = getUser();
|
|
|
+ return null == user ? -1L : user.getUserId();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Long getUserId(HttpServletRequest request) {
|
|
|
+ ZhongZhengUser user = getUser(request);
|
|
|
+ return null == user ? -1L : user.getUserId();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getUserAccount() {
|
|
|
+ ZhongZhengUser user = getUser();
|
|
|
+ return null == user ? "" : user.getAccount();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getUserAccount(HttpServletRequest request) {
|
|
|
+ ZhongZhengUser user = getUser(request);
|
|
|
+ return null == user ? "" : user.getAccount();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getUserName() {
|
|
|
+ ZhongZhengUser user = getUser();
|
|
|
+ return null == user ? "" : user.getUserName();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getUserName(HttpServletRequest request) {
|
|
|
+ ZhongZhengUser user = getUser(request);
|
|
|
+ return null == user ? "" : user.getUserName();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getUserRole() {
|
|
|
+ ZhongZhengUser user = getUser();
|
|
|
+ return null == user ? "" : user.getRoleName();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getUserRole(HttpServletRequest request) {
|
|
|
+ ZhongZhengUser user = getUser(request);
|
|
|
+ return null == user ? "" : user.getRoleName();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getTenantId() {
|
|
|
+ ZhongZhengUser user = getUser();
|
|
|
+ return null == user ? "" : user.getTenantId();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getTenantId(HttpServletRequest request) {
|
|
|
+ ZhongZhengUser user = getUser(request);
|
|
|
+ return null == user ? "" : user.getTenantId();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getClientId() {
|
|
|
+ ZhongZhengUser user = getUser();
|
|
|
+ return null == user ? "" : user.getClientId();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getClientId(HttpServletRequest request) {
|
|
|
+ ZhongZhengUser user = getUser(request);
|
|
|
+ return null == user ? "" : user.getClientId();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Claims getClaims(HttpServletRequest request) {
|
|
|
+ String auth = request.getHeader("blade-auth");
|
|
|
+ String token = getToken(StringUtil.isNotBlank(auth) ? auth : request.getParameter("blade-auth"));
|
|
|
+ return parseJWT(token);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getToken(String auth) {
|
|
|
+ if (isBearer(auth)) {
|
|
|
+ return auth.substring(AUTH_LENGTH);
|
|
|
+ } else {
|
|
|
+ return isCrypto(auth) ? AesUtil.decryptFormBase64ToString(auth.substring(AUTH_LENGTH), getTokenProperties().getAesKey()) : null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Boolean isBearer(String auth) {
|
|
|
+ if (auth != null && auth.length() > AUTH_LENGTH) {
|
|
|
+ String headStr = auth.substring(0, 6).toLowerCase();
|
|
|
+ return headStr.compareTo("bearer") == 0;
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Boolean isCrypto(String auth) {
|
|
|
+ if (auth != null && auth.length() > AUTH_LENGTH) {
|
|
|
+ String headStr = auth.substring(0, 6).toLowerCase();
|
|
|
+ return headStr.compareTo("crypto") == 0;
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getHeader() {
|
|
|
+ return getHeader((HttpServletRequest)Objects.requireNonNull(WebUtil.getRequest()));
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getHeader(HttpServletRequest request) {
|
|
|
+ return request.getHeader("blade-auth");
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Claims parseJWT(String jsonWebToken) {
|
|
|
+ try {
|
|
|
+ return (Claims)Jwts.parserBuilder().setSigningKey(Base64.getDecoder().decode(getBase64Security())).build().parseClaimsJws(jsonWebToken).getBody();
|
|
|
+ } catch (Exception var2) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static TokenInfo createJWT(Map<String, String> user, String audience, String issuer, String tokenType) throws UnsupportedEncodingException {
|
|
|
+ String[] tokens = extractAndDecodeHeader();
|
|
|
+
|
|
|
+ assert tokens.length == 2;
|
|
|
+
|
|
|
+ String clientId = tokens[0];
|
|
|
+ String clientSecret = tokens[1];
|
|
|
+ IClientDetails clientDetails = clientDetails(clientId);
|
|
|
+ if (!validateClient(clientDetails, clientId, clientSecret)) {
|
|
|
+ throw new SecureException("客户端认证失败!");
|
|
|
+ } else {
|
|
|
+ SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
|
|
|
+ long nowMillis = System.currentTimeMillis();
|
|
|
+ Date now = new Date(nowMillis);
|
|
|
+ byte[] apiKeySecretBytes = Base64.getDecoder().decode(getBase64Security());
|
|
|
+ Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
|
|
|
+ JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT").setIssuer(issuer).setAudience(audience).signWith(signingKey);
|
|
|
+ user.forEach(builder::claim);
|
|
|
+ builder.claim("client_id", clientId);
|
|
|
+ long expireMillis;
|
|
|
+ if (tokenType.equals("access_token")) {
|
|
|
+ expireMillis = (long)(clientDetails.getAccessTokenValidity() * 1000);
|
|
|
+ } else if (tokenType.equals("refresh_token")) {
|
|
|
+ expireMillis = (long)(clientDetails.getRefreshTokenValidity() * 1000);
|
|
|
+ } else {
|
|
|
+ expireMillis = getExpire();
|
|
|
+ }
|
|
|
+
|
|
|
+ long expMillis = nowMillis + expireMillis;
|
|
|
+ Date exp = new Date(expMillis);
|
|
|
+ builder.setExpiration(exp).setNotBefore(now);
|
|
|
+ TokenInfo tokenInfo = new TokenInfo();
|
|
|
+ tokenInfo.setToken(builder.compact());
|
|
|
+ tokenInfo.setExpire((int)expireMillis / 1000);
|
|
|
+ return tokenInfo;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static long getExpire() {
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
+ cal.add(6, 1);
|
|
|
+ cal.set(11, 3);
|
|
|
+ cal.set(13, 0);
|
|
|
+ cal.set(12, 0);
|
|
|
+ cal.set(14, 0);
|
|
|
+ return cal.getTimeInMillis() - System.currentTimeMillis();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String[] extractAndDecodeHeader() throws UnsupportedEncodingException {
|
|
|
+ try {
|
|
|
+ String header = ((HttpServletRequest)Objects.requireNonNull(WebUtil.getRequest())).getHeader("Authorization");
|
|
|
+ header = Func.toStr(header).replace("Basic%20", "Basic ");
|
|
|
+ if (!header.startsWith("Basic ")) {
|
|
|
+ throw new SecureException("No client information in request header");
|
|
|
+ } else {
|
|
|
+ byte[] base64Token = header.substring(6).getBytes(Charsets.UTF_8_NAME);
|
|
|
+
|
|
|
+ byte[] decoded;
|
|
|
+ try {
|
|
|
+ decoded = Base64.getDecoder().decode(base64Token);
|
|
|
+ } catch (IllegalArgumentException var5) {
|
|
|
+ throw new RuntimeException("Failed to decode basic authentication token");
|
|
|
+ }
|
|
|
+
|
|
|
+ String token = new String(decoded, Charsets.UTF_8_NAME);
|
|
|
+ int index = token.indexOf(":");
|
|
|
+ if (index == -1) {
|
|
|
+ throw new RuntimeException("Invalid basic authentication token");
|
|
|
+ } else {
|
|
|
+ return new String[]{token.substring(0, index), token.substring(index + 1)};
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Throwable var6) {
|
|
|
+ throw var6;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getClientIdFromHeader() throws UnsupportedEncodingException {
|
|
|
+ String[] tokens = extractAndDecodeHeader();
|
|
|
+
|
|
|
+ assert tokens.length == 2;
|
|
|
+
|
|
|
+ return tokens[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ private static IClientDetails clientDetails(String clientId) {
|
|
|
+ return getClientDetailsService().loadClientByClientId(clientId);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static boolean validateClient(IClientDetails clientDetails, String clientId, String clientSecret) {
|
|
|
+ if (clientDetails == null) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ return StringUtil.equals(clientId, clientDetails.getClientId()) && StringUtil.equals(clientSecret, clientDetails.getClientSecret());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ static {
|
|
|
+ AUTH_LENGTH = TokenConstants.AUTH_LENGTH;
|
|
|
+ }
|
|
|
+}
|