All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.macrocloud.kernel.security.utils.SecureUtil Maven / Gradle / Ivy

There is a newer version: 1.1.0-RELEASE
Show newest version
package org.macrocloud.kernel.security.utils;

import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.SneakyThrows;
import org.macrocloud.kernel.auth.TokenInfo;
import org.macrocloud.kernel.auth.exception.SecureException;
import org.macrocloud.kernel.auth.utils.AuthUtil;
import org.macrocloud.kernel.auth.utils.JwtUtil;
import org.macrocloud.kernel.launch.constant.TokenConstant;
import org.macrocloud.kernel.security.constant.SecureConstant;
import org.macrocloud.kernel.security.provider.IClientDetails;
import org.macrocloud.kernel.security.provider.IClientDetailsService;
import org.macrocloud.kernel.toolkit.utils.Charsets;
import org.macrocloud.kernel.toolkit.utils.Func;
import org.macrocloud.kernel.toolkit.utils.SpringUtil;
import org.macrocloud.kernel.toolkit.utils.StringPool;
import org.macrocloud.kernel.toolkit.utils.StringUtil;
import org.macrocloud.kernel.toolkit.utils.WebUtil;

import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.*;

/**
 * Secure工具类
 *
 */
public class SecureUtil extends AuthUtil {
	private final static String CLIENT_ID = TokenConstant.CLIENT_ID;

	private static IClientDetailsService clientDetailsService;

	/**
	 * 获取客户端服务类
	 *
	 * @return clientDetailsService
	 */
	private static IClientDetailsService getClientDetailsService() {
		if (clientDetailsService == null) {
			clientDetailsService = SpringUtil.getBean(IClientDetailsService.class);
		}
		return clientDetailsService;
	}



	/**
	 * 创建令牌
	 *
	 * @param user      user
	 * @param audience  audience
	 * @param issuer    issuer
	 * @param tokenType tokenType
	 * @return jwt
	 */
	public static TokenInfo createJWT(Map user, String audience, String issuer, String tokenType) {

		String[] tokens = extractAndDecodeHeader();
		String clientId = tokens[0];
		String clientSecret = tokens[1];

		// 获取客户端信息
		IClientDetails clientDetails = clientDetails(clientId);

		// 校验客户端信息
		if (!validateClient(clientDetails, clientId, clientSecret)) {
			throw new SecureException("client authentication failed, please check the header parameters");
		}

		SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

		long nowMillis = System.currentTimeMillis();
		Date now = new Date(nowMillis);

		//生成签名密钥
		byte[] apiKeySecretBytes = Base64.getDecoder().decode(JwtUtil.getBase64Security());
		Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

		//添加构成JWT的类		byte[] apiKeySecretBytes = Base64.getDecoder().decode(JwtUtil.getBase64Security());
		JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
				.setIssuer(issuer)
				.setAudience(audience)
				.signWith(signingKey);

		//设置JWT参数
		user.forEach(builder::claim);

		//设置应用id
		builder.claim(CLIENT_ID, clientId);

		//添加Token过期时间
		long expireMillis;
		if (tokenType.equals(TokenConstant.ACCESS_TOKEN)) {
			expireMillis = clientDetails.getAccessTokenValidity() * 1000L;
		} else if (tokenType.equals(TokenConstant.REFRESH_TOKEN)) {
			expireMillis = clientDetails.getRefreshTokenValidity() * 1000L;
		} else {
			expireMillis = getExpire();
		}
		long expMillis = nowMillis + expireMillis;
		Date exp = new Date(expMillis);
		builder.setExpiration(exp).setNotBefore(now);

		//组装Token信息
		TokenInfo tokenInfo = new TokenInfo();
		tokenInfo.setToken(builder.compact());
		tokenInfo.setExpire((int) (expireMillis / 1000L));

		//Token状态配置, 仅在生成AccessToken时候执行
		if (TokenConstant.ACCESS_TOKEN.equals(tokenType)) {
			String tenantId = String.valueOf(user.get(TokenConstant.TENANT_ID));
			String userId = String.valueOf(user.get(TokenConstant.USER_ID));
		}

		return tokenInfo;
	}

	/**
	 * 获取过期时间(次日凌晨3点)
	 *
	 * @return expire
	 */
	public static long getExpire() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DAY_OF_YEAR, 1);
		cal.set(Calendar.HOUR_OF_DAY, 3);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTimeInMillis() - System.currentTimeMillis();
	}

	/**
	 * 客户端信息解码
	 */
	@SneakyThrows
	public static String[] extractAndDecodeHeader() {
		// 获取请求头客户端信息
		String header = Objects.requireNonNull(WebUtil.getRequest()).getHeader(SecureConstant.BASIC_HEADER_KEY);
		header = Func.toStr(header).replace(SecureConstant.BASIC_HEADER_PREFIX_EXT, SecureConstant.BASIC_HEADER_PREFIX);
		if (!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];
	}

	/**
	 * 获取客户端信息
	 *
	 * @param clientId 客户端id
	 * @return clientDetails
	 */
	private static IClientDetails clientDetails(String clientId) {
		return getClientDetailsService().loadClientByClientId(clientId);
	}

	/**
	 * 校验Client
	 *
	 * @param clientId     客户端id
	 * @param clientSecret 客户端密钥
	 * @return boolean
	 */
	private static boolean validateClient(IClientDetails clientDetails, String clientId, String clientSecret) {
		if (clientDetails != null) {
			return StringUtil.equals(clientId, clientDetails.getClientId()) && StringUtil.equals(clientSecret, clientDetails.getClientSecret());
		}
		return false;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy