jeecg-boot-base-core/pom.xml
@@ -258,7 +258,17 @@ <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.5</version> </dependency> <!-- Bouncy Castle å å¯ --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15to18</artifactId> <version>1.78</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15to18</artifactId> <version>1.78</version> </dependency> </dependencies> </project> jeecg-boot-base-core/src/main/java/org/jeecg/common/sign/SM2Utils.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,141 @@ package org.jeecg.common.sign; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; /** * å½å¯2 å ç¾/éªç¾ï¼ å å¯è§£å¯æ¥å£ */ public class SM2Utils { //å便¨¡å¼ private static SM2Utils instance; public static SM2Utils getInstance() { if (instance == null) { instance = new SM2Utils(); } return instance; } /** * å ç¾ï¼ å å¯ç¾å (ä½¿ç¨ ç¾åç§é¥) * @param raw å¾ å ç¾çæ°æ® * @param privateKey ç¾åç§é¥ * @return å ç¾åçæ°æ®, hex */ public String sign(String raw, String privateKey) { try { return Sm2Lib.sign(raw, privateKey); }catch (Exception e){ log("Sm2Util.sign Exception:"+e.getMessage()); return null; } } /** * éªç¾ï¼ ç¾åæ ¡éª (ä½¿ç¨ å ¬é¥) * @param raw æææ°æ® * @param sign å¯ææ°æ®ï¼hex æ ¼å¼ * @param publicKey éªç¾å ¬é¥ * @return éªç¾ç»æ true/false */ public boolean verify(String raw, String sign, String publicKey) { try { return Sm2Lib.verify(raw, publicKey, sign); } catch (Exception e) { log("Sm2Util.verify Exception:"+e.getMessage()); } return false; } /** * çæç§é¥å¯¹(å·¥å ·å½æ°) * @return 0 å ¬é¥ï¼ 1ç§é¥ */ public String[] genKey() { return Sm2Lib.genKey(); } /** * æ°æ®å å¯(ä½¿ç¨ å ¬é¥) * @param data å¾ å 坿°æ® * @param publicKey æ°æ®å å¯å ¬é¥ * @return å å¯åçå¯ææ°æ® */ public String encrypt(String data, String publicKey) { if(StringUtils.isEmpty(data)|| "null".equals(data)){ return null; } try{ return Sm2Lib.encrypt(data, publicKey); }catch(Exception e){ log("Sm2Util.encrypt Exception: "+ e); e.printStackTrace(); return null; } } /** * æ°æ®è§£å¯ (é»è®¤ ç§é¥) * @param data å¯ææ°æ® * @param privateKey æ°æ®è§£å¯ç§é¥ * @return è§£å¯åçæææ°æ® */ public String decrypt(String data, String privateKey) { try { return Sm2Lib.decrypt(data, privateKey); }catch(Exception e){ log("Sm2Util.decrypt Exception: "+ e); return null; } } public static String getSignContent(Map<String, String> sortedParams) { StringBuffer content = new StringBuffer(); List<String> keys = new ArrayList<String>(sortedParams.keySet()); Collections.sort(keys); int index = 0; for (int i = 0; i < keys.size(); i++) { String key = keys.get(i); String value = sortedParams.get(key); if (areNotEmpty(key, value)) { content.append(index == 0 ? "" : "&").append(key).append("=").append(value); index++; } } return content.toString(); } private static boolean areNotEmpty(String... values) { boolean result = true; if (values == null || values.length == 0) { result = false; } else { for (String value : values) { result &= !StringUtils.isEmpty(value); } } return result; } private void log(String msg){ System.out.println(msg); } public static void main(String[] args) { String[] strings = getInstance().genKey(); for (String string : strings) { System.out.println(string); } } } jeecg-boot-base-core/src/main/java/org/jeecg/common/sign/Sm2Lib.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,882 @@ package org.jeecg.common.sign; import org.apache.commons.lang3.StringUtils; import org.bouncycastle.asn1.*; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X962Parameters; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.x9.X9ECPoint; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.CryptoException; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.engines.SM2Engine; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.crypto.params.*; import org.bouncycastle.crypto.signers.SM2Signer; import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; import org.bouncycastle.jcajce.spec.SM2ParameterSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.FixedPointCombMultiplier; import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve; import org.bouncycastle.pqc.legacy.math.linearalgebra.ByteUtils; import org.bouncycastle.util.Strings; import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemReader; import org.bouncycastle.util.io.pem.PemWriter; import javax.crypto.Cipher; import java.io.*; import java.math.BigInteger; import java.security.*; import java.security.spec.*; import java.util.*; import java.util.regex.Pattern; //SM2 åºç¡åº public class Sm2Lib { //SM2ç®æ³é»è®¤ç¨æ·IDï¼ç®å弿¾å¹³å°ä¸ä¼ä½¿ç¨éé»è®¤ç¨æ·ID public static String DEFAULT_USER_ID = "1234567812345678"; public static String DEFAULT_CHARSET = "utf8"; public static final String SM2_ECC_GY_VAL = "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"; public static final String SM2_ECC_GX_VAL = "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"; public static final SM2P256V1Curve CURVE = new SM2P256V1Curve(); public final static BigInteger SM2_ECC_N = CURVE.getOrder(); public final static BigInteger SM2_ECC_H = CURVE.getCofactor(); public final static BigInteger SM2_ECC_GX = new BigInteger(SM2_ECC_GX_VAL, 16); public final static BigInteger SM2_ECC_GY = new BigInteger(SM2_ECC_GY_VAL, 16); public static final ECPoint G_POINT = CURVE.createPoint(SM2_ECC_GX, SM2_ECC_GY); public static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, G_POINT, SM2_ECC_N, SM2_ECC_H); public final static BigInteger SM2_ECC_P = CURVE.getQ(); public final static BigInteger SM2_ECC_A = CURVE.getA().toBigInteger(); public final static BigInteger SM2_ECC_B = CURVE.getB().toBigInteger(); //public static final int CURVE_LEN = BCECUtils.getCurveLength(DOMAIN_PARAMS); public static final EllipticCurve JDK_CURVE = new EllipticCurve(new ECFieldFp(SM2_ECC_P), SM2_ECC_A, SM2_ECC_B); public static final java.security.spec.ECPoint JDK_G_POINT = new java.security.spec.ECPoint( G_POINT.getAffineXCoord().toBigInteger(), G_POINT.getAffineYCoord().toBigInteger()); public static final java.security.spec.ECParameterSpec JDK_EC_SPEC = new java.security.spec.ECParameterSpec( JDK_CURVE, JDK_G_POINT, SM2_ECC_N, SM2_ECC_H.intValue()); private static BouncyCastleProvider provider; static { provider = new BouncyCastleProvider(); Security.addProvider(provider); } public static String decrypt(String cipherTextBase64, String privateKey) throws Exception { return decrypt(cipherTextBase64, privateKey, DEFAULT_CHARSET); } public static String decrypt(String cipherTextBase64, String privateKey, String charset) throws Exception { byte[] cipher = Base64.getDecoder().decode(cipherTextBase64); boolean isMatch = Pattern.matches("^[0-9a-f]+$", privateKey.toLowerCase()); if (isMatch) { ECPrivateKeyParameters ecPrivateKeyParameters = BCECUtils.createECPrivateKeyParameters(privateKey, DOMAIN_PARAMS); byte[] buf = decrypt(ecPrivateKeyParameters, cipher); //å°è§£å¯åçææææå®å符éç¼ç åè¿å try { String strContent = new String(buf, charset); return strContent; } catch (UnsupportedEncodingException e) { throw new Exception(e); } } else { byte[] privateKeyByte = Base64.getDecoder().decode(privateKey); // è§£æX509æ ¼å¼SM2ç§é¥ PrivateKey sm2PrivateKey = parsePKCS8PrivateKey(privateKeyByte); // 使ç¨SM2ç§é¥è§£å¯ byte[] buf = sm2Decrypt(cipher, sm2PrivateKey); //å°è§£å¯åçææææå®å符éç¼ç åè¿å try { String strContent = new String(buf, charset); return strContent; } catch (UnsupportedEncodingException e) { throw new Exception(e); } } } public static String encrypt(String plainText, String publicKey) throws Exception { return encrypt(plainText, publicKey, DEFAULT_CHARSET); } public static String encrypt(String plainText, String publicKey, String charset) throws Exception { byte[] plain = plainText.getBytes(charset); boolean isMatch = Pattern.matches("^[0-9a-f]+$", publicKey.toLowerCase()); if (isMatch) { ECPoint point = CURVE.decodePoint(ByteUtils.fromHexString(publicKey)); ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(point, DOMAIN_PARAMS); byte[] cipher = encrypt(ecPublicKeyParameters, plain); //å°å¯æBase64ç¼ç åè¿å String strContent = Base64.getEncoder().encodeToString(cipher); return strContent; } else { // è§£æPKCS8æ ¼å¼SM2ç§é¥ byte[] publicKeyByte = Base64.getDecoder().decode(publicKey); PublicKey sm2PublicKey = parseX509PublicKey(publicKeyByte); byte[] cipher = sm2Encrypt(plain, sm2PublicKey); //å°å¯æBase64ç¼ç åè¿å String strContent = Base64.getEncoder().encodeToString(cipher); return strContent; } } public static String sign(String content, String privateKey) throws Exception { return sign(content, privateKey, null, DEFAULT_CHARSET); } public static String sign(String content, String privateKey, String userId, String charset) throws Exception { if (StringUtils.isEmpty(userId)) { userId = DEFAULT_USER_ID; } byte[] message = content.getBytes(charset); boolean isMatch = Pattern.matches("^[0-9a-f]+$", privateKey.toLowerCase()); if (isMatch) { ECPrivateKeyParameters ecPrivateKeyParameters = BCECUtils.createECPrivateKeyParameters(privateKey, DOMAIN_PARAMS); byte[] signature = sign(ecPrivateKeyParameters, Strings.toByteArray(userId), message); try { String sign = Base64.getEncoder().encodeToString(signature); return sign; } catch (Exception e) { throw new Exception(e); } } else { byte[] privateKeyByte = Base64.getDecoder().decode(privateKey); PrivateKey sm2PrivateKey = parsePKCS8PrivateKey(privateKeyByte); byte[] signature = sm2Sign(message, sm2PrivateKey, userId); String sign = Base64.getEncoder().encodeToString(signature); return sign; } } public static boolean verify(String content, String publicKey, String sign) throws Exception { return verify(content, publicKey, sign, null, DEFAULT_CHARSET); } public static boolean verify(String content, String publicKey, String sign, String userId, String charset) throws Exception { if (StringUtils.isEmpty(userId)) { userId = DEFAULT_USER_ID; } byte[] message = content.getBytes(charset); byte[] signature = Base64.getDecoder().decode(sign); boolean isMatch = Pattern.matches("^[0-9a-f]+$", publicKey.toLowerCase()); if (isMatch) { ECPoint point = CURVE.decodePoint(ByteUtils.fromHexString(publicKey)); ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(point, DOMAIN_PARAMS); boolean valid = verify(ecPublicKeyParameters, Strings.toByteArray(userId), message, signature); return valid; } else { byte[] publicKeyByte = Base64.getDecoder().decode(publicKey); PublicKey sm2PublicKey = parseX509PublicKey(publicKeyByte); boolean valid = sm2Verify(signature, message, sm2PublicKey, userId); return valid; } } private static byte[] sm2Encrypt(byte[] plain, PublicKey sm2PublicKey) throws Exception { try { Cipher sm2CipherEngine = Cipher.getInstance("SM2", "BC"); sm2CipherEngine.init(Cipher.ENCRYPT_MODE, sm2PublicKey); return sm2CipherEngine.doFinal(plain); } catch (Exception e) { throw new Exception(e); } } private static byte[] sm2Decrypt(byte[] cipher, PrivateKey sm2PrivateKey) throws Exception { try { Cipher sm2CipherEngine = Cipher.getInstance("SM2", "BC"); sm2CipherEngine.init(Cipher.DECRYPT_MODE, sm2PrivateKey); return sm2CipherEngine.doFinal(cipher); } catch (Exception e) { throw new Exception(e); } } private static byte[] sm2Sign(byte[] message, PrivateKey sm2PrivateKey, String sm2UserId) throws Exception { try { Signature sm2SignEngine = Signature.getInstance("SM3withSM2"); sm2SignEngine.setParameter(new SM2ParameterSpec( Strings.toByteArray(sm2UserId))); sm2SignEngine.initSign(sm2PrivateKey); sm2SignEngine.update(message); return sm2SignEngine.sign(); } catch (Exception e) { throw new Exception(e); } } private static boolean sm2Verify(byte[] signature, byte[] message, PublicKey publicKey, String sm2UserId) { try { Signature sm2SignEngine = Signature.getInstance("SM3withSM2"); sm2SignEngine.setParameter(new SM2ParameterSpec(Strings.toByteArray(sm2UserId))); sm2SignEngine.initVerify(publicKey); sm2SignEngine.update(message); return sm2SignEngine.verify(signature); } catch (Exception e) { return false; } } private static PublicKey parseX509PublicKey(byte[] x509PublicKey) throws Exception { try { KeyFactory keyFactory = KeyFactory.getInstance("EC"); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(x509PublicKey); return keyFactory.generatePublic(keySpec); } catch (Exception e) { throw new Exception(e); } } private static PrivateKey parsePKCS8PrivateKey(byte[] pkcs8PriateKey) throws Exception { try { KeyFactory keyFactory = KeyFactory.getInstance("EC"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8PriateKey); return keyFactory.generatePrivate(keySpec); } catch (Exception e) { throw new Exception(e); } } public static String getSignContent(Map<String, String> sortedParams) { StringBuffer content = new StringBuffer(); List<String> keys = new ArrayList<>(sortedParams.keySet()); Collections.sort(keys); int index = 0; for (int i = 0; i < keys.size(); i++) { String key = keys.get(i); String value = sortedParams.get(key); if (areNotEmpty(key, value)) { content.append((index == 0 ? "" : "&") + key + "=" + value); index++; } } return content.toString(); } private static boolean areNotEmpty(String... values) { boolean result = true; if (values == null || values.length == 0) { result = false; } else { for (String value : values) { result &= !isEmpty(value); } } return result; } private static boolean isEmpty(String value) { int strLen; if (value == null || (strLen = value.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if ((Character.isWhitespace(value.charAt(i)) == false)) { return false; } } return true; } /** * @param pubKeyParams å ¬é¥ * @param srcData åæ * @return é»è®¤è¾åºC1C3C2顺åºç坿ãC1为65åè第1åè为å缩æ è¯ï¼è¿éåºå®ä¸º0x04ï¼åé¢64åè为xyåéå32åèãC3为32åèãC2é¿åº¦ä¸åæä¸è´ã * @throws InvalidCipherTextException */ private static byte[] encrypt(final ECPublicKeyParameters pubKeyParams, final byte[] srcData) throws InvalidCipherTextException { return encrypt(SM2Engine.Mode.C1C3C2, pubKeyParams, srcData); } /** * @param priKeyParams ç§é¥ * @param sm2Cipher é»è®¤è¾å ¥C1C3C2顺åºç坿ãC1为65åè第1åè为å缩æ è¯ï¼è¿éåºå®ä¸º0x04ï¼åé¢64åè为xyåéå32åèãC3为32åèãC2é¿åº¦ä¸åæä¸è´ã * @return åæãSM2è§£å¯è¿åäºæ°æ®åä¸å®æ¯åæï¼å 为SM2èªå¸¦æ ¡éªï¼å¦æå¯æè¢«ç¯¡æ¹æè å¯é¥å¯¹ä¸ä¸ï¼é½æ¯ä¼ç´æ¥æ¥å¼å¸¸çã * @throws InvalidCipherTextException */ private static byte[] decrypt(final ECPrivateKeyParameters priKeyParams, final byte[] sm2Cipher) throws InvalidCipherTextException { return decrypt(SM2Engine.Mode.C1C3C2, priKeyParams, sm2Cipher); } /** * @param mode æå®å¯æç»æï¼æ°ç[ãSM2å¯ç ç®æ³ä½¿ç¨è§èã GM/T 0009-2012]æ å为C1C3C2 * @param pubKeyParams å ¬é¥ * @param srcData åæ * @return æ ¹æ®modeä¸åï¼è¾åºç坿C1C2C3æå顺åºä¸åãC1为65åè第1åè为å缩æ è¯ï¼è¿éåºå®ä¸º0x04ï¼åé¢64åè为xyåéå32åèãC3为32åèãC2é¿åº¦ä¸åæä¸è´ã * @throws InvalidCipherTextException */ private static byte[] encrypt(final SM2Engine.Mode mode, final ECPublicKeyParameters pubKeyParams, final byte[] srcData) throws InvalidCipherTextException { final SM2Engine engine = new SM2Engine(mode); final ParametersWithRandom pwr = new ParametersWithRandom(pubKeyParams, new SecureRandom()); engine.init(true, pwr); return engine.processBlock(srcData, 0, srcData.length); } /** * @param mode æå®å¯æç»æï¼æ°ç[ãSM2å¯ç ç®æ³ä½¿ç¨è§èã GM/T 0009-2012]æ å为C1C3C2 * @param priKeyParams ç§é¥ * @param sm2Cipher æ ¹æ®modeä¸åï¼éè¦è¾å ¥ç坿C1C2C3æå顺åºä¸åãC1为65åè第1åè为å缩æ è¯ï¼è¿éåºå®ä¸º0x04ï¼åé¢64åè为xyåéå32åèãC3为32åèãC2é¿åº¦ä¸åæä¸è´ã * @return åæãSM2è§£å¯è¿åäºæ°æ®åä¸å®æ¯åæï¼å 为SM2èªå¸¦æ ¡éªï¼å¦æå¯æè¢«ç¯¡æ¹æè å¯é¥å¯¹ä¸ä¸ï¼é½æ¯ä¼ç´æ¥æ¥å¼å¸¸çã * @throws InvalidCipherTextException */ private static byte[] decrypt(final SM2Engine.Mode mode, final ECPrivateKeyParameters priKeyParams, final byte[] sm2Cipher) throws InvalidCipherTextException { final SM2Engine engine = new SM2Engine(mode); engine.init(false, priKeyParams); return engine.processBlock(sm2Cipher, 0, sm2Cipher.length); } /** * ç¾å * * @param priKeyParams ç§é¥ * @param withId å¯ä»¥ä¸ºnullï¼è¥ä¸ºnullï¼åé»è®¤withId为åèæ°ç»:"1234567812345678".getBytes() * @param srcData æºæ°æ® * @return DERç¼ç åçç¾åå¼ * @throws CryptoException */ private static byte[] sign(final ECPrivateKeyParameters priKeyParams, final byte[] withId, final byte[] srcData) throws CryptoException { SM2Signer signer = new SM2Signer(); CipherParameters param = null; ParametersWithRandom pwr = new ParametersWithRandom(priKeyParams, new SecureRandom()); if (withId != null) { param = new ParametersWithID(pwr, withId); } else { param = pwr; } signer.init(true, param); signer.update(srcData, 0, srcData.length); return signer.generateSignature(); } /** * éªç¾ * * @param pubKeyParams å ¬é¥ * @param withId å¯ä»¥ä¸ºnullï¼è¥ä¸ºnullï¼åé»è®¤withId为åèæ°ç»:"1234567812345678".getBytes() * @param srcData åæ * @param sign DERç¼ç çç¾åå¼ * @return éªç¾æåè¿åtrueï¼å¤±è´¥è¿åfalse */ private static boolean verify(final ECPublicKeyParameters pubKeyParams, final byte[] withId, final byte[] srcData, final byte[] sign) { final SM2Signer signer = new SM2Signer(); CipherParameters param; if (withId != null) { param = new ParametersWithID(pubKeyParams, withId); } else { param = pubKeyParams; } signer.init(false, param); signer.update(srcData, 0, srcData.length); return signer.verifySignature(sign); } /** * çæç§é¥å¯¹(å·¥å ·å½æ°) * @return 0 å ¬é¥ï¼ 1ç§é¥ */ public static String[] genKey() { AsymmetricCipherKeyPair kPair = BCECUtils.generateKeyPairParameter(DOMAIN_PARAMS, new SecureRandom()); ECPrivateKeyParameters ecPriv = (ECPrivateKeyParameters)kPair.getPrivate(); ECPublicKeyParameters ecPub = (ECPublicKeyParameters)kPair.getPublic(); BigInteger privateKey = ecPriv.getD(); ECPoint publicKey = ecPub.getQ(); byte[] priv = privateKey.toByteArray(); byte[] pub = publicKey.getEncoded(false); if (priv.length == 33) { byte[] newPriv = new byte[32]; System.arraycopy(priv, 1, newPriv, 0, 32); priv = newPriv; } String[] keyPairs = new String[2]; keyPairs[0] = ByteUtils.toHexString(pub); keyPairs[1] = ByteUtils.toHexString(priv); return keyPairs; } } /** * è¿ä¸ªå·¥å ·ç±»çæ¹æ³ï¼ä¹éç¨äºå ¶ä»åºäºBCåºçECCç®æ³ */ class BCECUtils { private static final String ALGO_NAME_EC = "EC"; private static final String PEM_STRING_PUBLIC = "PUBLIC KEY"; private static final String PEM_STRING_ECPRIVATEKEY = "EC PRIVATE KEY"; /** * çæECCå¯é¥å¯¹ * * @return ECCå¯é¥å¯¹ */ public static AsymmetricCipherKeyPair generateKeyPairParameter( ECDomainParameters domainParameters, SecureRandom random) { ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(domainParameters, random); ECKeyPairGenerator keyGen = new ECKeyPairGenerator(); keyGen.init(keyGenerationParams); return keyGen.generateKeyPair(); } public static KeyPair generateKeyPair(ECDomainParameters domainParameters, SecureRandom random) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGO_NAME_EC, BouncyCastleProvider.PROVIDER_NAME); ECParameterSpec parameterSpec = new ECParameterSpec(domainParameters.getCurve(), domainParameters.getG(), domainParameters.getN(), domainParameters.getH()); kpg.initialize(parameterSpec, random); return kpg.generateKeyPair(); } public static int getCurveLength(ECKeyParameters ecKey) { return getCurveLength(ecKey.getParameters()); } public static int getCurveLength(ECDomainParameters domainParams) { return (domainParams.getCurve().getFieldSize() + 7) / 8; } public static byte[] fixToCurveLengthBytes(int curveLength, byte[] src) { if (src.length == curveLength) { return src; } byte[] result = new byte[curveLength]; if (src.length > curveLength) { System.arraycopy(src, src.length - result.length, result, 0, result.length); } else { System.arraycopy(src, 0, result, result.length - src.length, src.length); } return result; } /** * @param dHex åå è¿å¶å符串形å¼çç§é¥då¼ï¼å¦ææ¯SM2ç®æ³ï¼Hexå符串é¿åº¦åºè¯¥æ¯64ï¼å³32åèï¼ * @param domainParameters EC Domainåæ°ï¼ä¸è¬æ¯åºå®çï¼å¦ææ¯SM2ç®æ³çå¯åè{@link Sm2Lib#DOMAIN_PARAMS} * @return */ public static ECPrivateKeyParameters createECPrivateKeyParameters( String dHex, ECDomainParameters domainParameters) { return createECPrivateKeyParameters(ByteUtils.fromHexString(dHex), domainParameters); } /** * @param dBytes åèæ°ç»å½¢å¼çç§é¥då¼ï¼å¦ææ¯SM2ç®æ³ï¼åºè¯¥æ¯32åè * @param domainParameters EC Domainåæ°ï¼ä¸è¬æ¯åºå®çï¼å¦ææ¯SM2ç®æ³çå¯åè{@link Sm2Lib#DOMAIN_PARAMS} * @return */ public static ECPrivateKeyParameters createECPrivateKeyParameters( byte[] dBytes, ECDomainParameters domainParameters) { return createECPrivateKeyParameters(new BigInteger(1, dBytes), domainParameters); } /** * @param d 大æ°å½¢å¼çç§é¥då¼ * @param domainParameters EC Domainåæ°ï¼ä¸è¬æ¯åºå®çï¼å¦ææ¯SM2ç®æ³çå¯åè{@link Sm2Lib#DOMAIN_PARAMS} * @return */ public static ECPrivateKeyParameters createECPrivateKeyParameters( BigInteger d, ECDomainParameters domainParameters) { return new ECPrivateKeyParameters(d, domainParameters); } /** * æ ¹æ®ECç§é¥æé ECå ¬é¥ * * @param priKey ECCç§é¥åæ°å¯¹è±¡ * @return */ public static ECPublicKeyParameters buildECPublicKeyByPrivateKey(ECPrivateKeyParameters priKey) { ECDomainParameters domainParameters = priKey.getParameters(); ECPoint q = new FixedPointCombMultiplier().multiply(domainParameters.getG(), priKey.getD()); return new ECPublicKeyParameters(q, domainParameters); } /** * @param x 大æ°å½¢å¼çå ¬é¥xåé * @param y 大æ°å½¢å¼çå ¬é¥yåé * @param curve ECæ²çº¿åæ°ï¼ä¸è¬æ¯åºå®çï¼å¦ææ¯SM2ç®æ³çå¯åè{@link Sm2Lib#CURVE} * @param domainParameters EC Domainåæ°ï¼ä¸è¬æ¯åºå®çï¼å¦ææ¯SM2ç®æ³çå¯åè{@link Sm2Lib#DOMAIN_PARAMS} * @return */ public static ECPublicKeyParameters createECPublicKeyParameters( BigInteger x, BigInteger y, ECCurve curve, ECDomainParameters domainParameters) { return createECPublicKeyParameters(x.toByteArray(), y.toByteArray(), curve, domainParameters); } /** * @param xHex åå è¿å¶å½¢å¼çå ¬é¥xåéï¼å¦ææ¯SM2ç®æ³ï¼Hexå符串é¿åº¦åºè¯¥æ¯64ï¼å³32åèï¼ * @param yHex åå è¿å¶å½¢å¼çå ¬é¥yåéï¼å¦ææ¯SM2ç®æ³ï¼Hexå符串é¿åº¦åºè¯¥æ¯64ï¼å³32åèï¼ * @param curve ECæ²çº¿åæ°ï¼ä¸è¬æ¯åºå®çï¼å¦ææ¯SM2ç®æ³çå¯åè{@link Sm2Lib#CURVE} * @param domainParameters EC Domainåæ°ï¼ä¸è¬æ¯åºå®çï¼å¦ææ¯SM2ç®æ³çå¯åè{@link Sm2Lib#DOMAIN_PARAMS} * @return */ public static ECPublicKeyParameters createECPublicKeyParameters( String xHex, String yHex, ECCurve curve, ECDomainParameters domainParameters) { return createECPublicKeyParameters(ByteUtils.fromHexString(xHex), ByteUtils.fromHexString(yHex), curve, domainParameters); } /** * @param xBytes åå è¿å¶å½¢å¼çå ¬é¥xåéï¼å¦ææ¯SM2ç®æ³ï¼åºè¯¥æ¯32åè * @param yBytes åå è¿å¶å½¢å¼çå ¬é¥yåéï¼å¦ææ¯SM2ç®æ³ï¼åºè¯¥æ¯32åè * @param curve ECæ²çº¿åæ°ï¼ä¸è¬æ¯åºå®çï¼å¦ææ¯SM2ç®æ³çå¯åè{@link Sm2Lib#CURVE} * @param domainParameters EC Domainåæ°ï¼ä¸è¬æ¯åºå®çï¼å¦ææ¯SM2ç®æ³çå¯åè{@link Sm2Lib#DOMAIN_PARAMS} * @return */ public static ECPublicKeyParameters createECPublicKeyParameters( byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters) { final byte uncompressedFlag = 0x04; int curveLength = getCurveLength(domainParameters); xBytes = fixToCurveLengthBytes(curveLength, xBytes); yBytes = fixToCurveLengthBytes(curveLength, yBytes); byte[] encodedPubKey = new byte[1 + xBytes.length + yBytes.length]; encodedPubKey[0] = uncompressedFlag; System.arraycopy(xBytes, 0, encodedPubKey, 1, xBytes.length); System.arraycopy(yBytes, 0, encodedPubKey, 1 + xBytes.length, yBytes.length); return new ECPublicKeyParameters(curve.decodePoint(encodedPubKey), domainParameters); } public static ECPrivateKeyParameters convertPrivateKeyToParameters(BCECPrivateKey ecPriKey) { ECParameterSpec parameterSpec = ecPriKey.getParameters(); ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(), parameterSpec.getN(), parameterSpec.getH()); return new ECPrivateKeyParameters(ecPriKey.getD(), domainParameters); } public static ECPublicKeyParameters convertPublicKeyToParameters(BCECPublicKey ecPubKey) { ECParameterSpec parameterSpec = ecPubKey.getParameters(); ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(), parameterSpec.getN(), parameterSpec.getH()); return new ECPublicKeyParameters(ecPubKey.getQ(), domainParameters); } public static BCECPublicKey createPublicKeyFromSubjectPublicKeyInfo(SubjectPublicKeyInfo subPubInfo) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException, IOException { return BCECUtils.convertX509ToECPublicKey(subPubInfo.toASN1Primitive().getEncoded(ASN1Encoding.DER)); } /** * å°ECCç§é¥è½¬æ¢ä¸ºPKCS8æ åçåèæµ * * @param priKey * @param pubKey å¯ä»¥ä¸ºç©ºï¼ä½æ¯å¦æä¸ºç©ºçè¯å¾å°çç»æOpenSSLå¯è½è§£æä¸äº * @return */ public static byte[] convertECPrivateKeyToPKCS8( ECPrivateKeyParameters priKey, ECPublicKeyParameters pubKey) { ECDomainParameters domainParams = priKey.getParameters(); ECParameterSpec spec = new ECParameterSpec(domainParams.getCurve(), domainParams.getG(), domainParams.getN(), domainParams.getH()); BCECPublicKey publicKey = null; if (pubKey != null) { publicKey = new BCECPublicKey(ALGO_NAME_EC, pubKey, spec, BouncyCastleProvider.CONFIGURATION); } BCECPrivateKey privateKey = new BCECPrivateKey(ALGO_NAME_EC, priKey, publicKey, spec, BouncyCastleProvider.CONFIGURATION); return privateKey.getEncoded(); } /** * å°PKCS8æ åçç§é¥åèæµè½¬æ¢ä¸ºç§é¥å¯¹è±¡ * * @param pkcs8Key * @return * @throws NoSuchAlgorithmException * @throws NoSuchProviderException * @throws InvalidKeySpecException */ public static BCECPrivateKey convertPKCS8ToECPrivateKey(byte[] pkcs8Key) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException { PKCS8EncodedKeySpec peks = new PKCS8EncodedKeySpec(pkcs8Key); KeyFactory kf = KeyFactory.getInstance(ALGO_NAME_EC, BouncyCastleProvider.PROVIDER_NAME); return (BCECPrivateKey) kf.generatePrivate(peks); } /** * å°PKCS8æ åçç§é¥åèæµè½¬æ¢ä¸ºPEM * * @param encodedKey * @return * @throws IOException */ public static String convertECPrivateKeyPKCS8ToPEM(byte[] encodedKey) throws IOException { return convertEncodedDataToPEM(PEM_STRING_ECPRIVATEKEY, encodedKey); } /** * å°PEMæ ¼å¼çç§é¥è½¬æ¢ä¸ºPKCS8æ ååèæµ * * @param pemString * @return * @throws IOException */ public static byte[] convertECPrivateKeyPEMToPKCS8(String pemString) throws IOException { return convertPEMToEncodedData(pemString); } /** * å°ECCç§é¥è½¬æ¢ä¸ºSEC1æ åçåèæµ * openssl d2i_ECPrivateKey彿°è¦æ±çDERç¼ç çç§é¥ä¹æ¯SEC1æ åçï¼ * è¿ä¸ªå·¥å ·å½æ°ç主è¦ç®çå°±æ¯ä¸ºäºè½çæä¸ä¸ªopensslå¯ä»¥ç´æ¥âè¯å«âçECCç§é¥. * ç¸å¯¹RSAç§é¥çPKCS1æ åï¼ECCç§é¥çæ å为SEC1 * * @param priKey * @param pubKey * @return * @throws IOException */ public static byte[] convertECPrivateKeyToSEC1( ECPrivateKeyParameters priKey, ECPublicKeyParameters pubKey) throws IOException { byte[] pkcs8Bytes = convertECPrivateKeyToPKCS8(priKey, pubKey); PrivateKeyInfo pki = PrivateKeyInfo.getInstance(pkcs8Bytes); ASN1Encodable encodable = pki.parsePrivateKey(); ASN1Primitive primitive = encodable.toASN1Primitive(); byte[] sec1Bytes = primitive.getEncoded(); return sec1Bytes; } /** * å°SEC1æ åçç§é¥åèæµæ¢å¤ä¸ºPKCS8æ åçåèæµ * * @param sec1Key * @return * @throws IOException */ public static byte[] convertECPrivateKeySEC1ToPKCS8(byte[] sec1Key) throws IOException { /** * åèorg.bouncycastle.asn1.pkcs.PrivateKeyInfoå * org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKeyï¼éåæ¼è£ */ X962Parameters params = getDomainParametersFromName(Sm2Lib.JDK_EC_SPEC, false); ASN1OctetString privKey = new DEROctetString(sec1Key); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new ASN1Integer(0)); //çæ¬å· v.add(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params)); //ç®æ³æ è¯ v.add(privKey); DERSequence ds = new DERSequence(v); return ds.getEncoded(ASN1Encoding.DER); } /** * å°SEC1æ åçç§é¥åèæµè½¬ä¸ºBCECPrivateKey对象 * * @param sec1Key * @return * @throws NoSuchAlgorithmException * @throws NoSuchProviderException * @throws InvalidKeySpecException * @throws IOException */ public static BCECPrivateKey convertSEC1ToBCECPrivateKey(byte[] sec1Key) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException { PKCS8EncodedKeySpec peks = new PKCS8EncodedKeySpec(convertECPrivateKeySEC1ToPKCS8(sec1Key)); KeyFactory kf = KeyFactory.getInstance(ALGO_NAME_EC, BouncyCastleProvider.PROVIDER_NAME); return (BCECPrivateKey) kf.generatePrivate(peks); } /** * å°SEC1æ åçç§é¥åèæµè½¬ä¸ºECPrivateKeyParameters对象 * openssl i2d_ECPrivateKey彿°çæçDERç¼ç çeccç§é¥æ¯ï¼SEC1æ åçã带æEC_GROUPã带æå ¬é¥çï¼ * è¿ä¸ªå·¥å ·å½æ°ç主è¦ç®çå°±æ¯ä¸ºäºä½¿Javaç¨åºè½å¤âè¯å«âopensslçæçECCç§é¥ * * @param sec1Key * @return * @throws NoSuchAlgorithmException * @throws NoSuchProviderException * @throws InvalidKeySpecException */ public static ECPrivateKeyParameters convertSEC1ToECPrivateKey(byte[] sec1Key) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException { BCECPrivateKey privateKey = convertSEC1ToBCECPrivateKey(sec1Key); return convertPrivateKeyToParameters(privateKey); } /** * å°ECCå ¬é¥å¯¹è±¡è½¬æ¢ä¸ºX509æ åçåèæµ * * @param pubKey * @return */ public static byte[] convertECPublicKeyToX509(ECPublicKeyParameters pubKey) { ECDomainParameters domainParams = pubKey.getParameters(); ECParameterSpec spec = new ECParameterSpec(domainParams.getCurve(), domainParams.getG(), domainParams.getN(), domainParams.getH()); BCECPublicKey publicKey = new BCECPublicKey(ALGO_NAME_EC, pubKey, spec, BouncyCastleProvider.CONFIGURATION); return publicKey.getEncoded(); } /** * å°X509æ åçå ¬é¥åèæµè½¬ä¸ºå ¬é¥å¯¹è±¡ * * @param x509Bytes * @return * @throws NoSuchProviderException * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static BCECPublicKey convertX509ToECPublicKey(byte[] x509Bytes) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException { X509EncodedKeySpec eks = new X509EncodedKeySpec(x509Bytes); KeyFactory kf = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME); return (BCECPublicKey) kf.generatePublic(eks); } /** * å°X509æ åçå ¬é¥åèæµè½¬ä¸ºPEM * * @param encodedKey * @return * @throws IOException */ public static String convertECPublicKeyX509ToPEM(byte[] encodedKey) throws IOException { return convertEncodedDataToPEM(PEM_STRING_PUBLIC, encodedKey); } /** * å°PEMæ ¼å¼çå ¬é¥è½¬ä¸ºX509æ åçåèæµ * * @param pemString * @return * @throws IOException */ public static byte[] convertECPublicKeyPEMToX509(String pemString) throws IOException { return convertPEMToEncodedData(pemString); } /** * copy from BC * * @param genSpec * @return */ public static X9ECParameters getDomainParametersFromGenSpec(ECGenParameterSpec genSpec) { return getDomainParametersFromName(genSpec.getName()); } /** * copy from BC * * @param curveName * @return */ public static X9ECParameters getDomainParametersFromName(String curveName) { X9ECParameters domainParameters; try { if (curveName.charAt(0) >= '0' && curveName.charAt(0) <= '2') { ASN1ObjectIdentifier oidID = new ASN1ObjectIdentifier(curveName); domainParameters = ECUtil.getNamedCurveByOid(oidID); } else { if (curveName.indexOf(' ') > 0) { curveName = curveName.substring(curveName.indexOf(' ') + 1); domainParameters = ECUtil.getNamedCurveByName(curveName); } else { domainParameters = ECUtil.getNamedCurveByName(curveName); } } } catch (IllegalArgumentException ex) { domainParameters = ECUtil.getNamedCurveByName(curveName); } return domainParameters; } /** * copy from BC * * @param ecSpec * @param withCompression * @return */ public static X962Parameters getDomainParametersFromName( java.security.spec.ECParameterSpec ecSpec, boolean withCompression) { X962Parameters params; if (ecSpec instanceof ECNamedCurveSpec) { ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec) ecSpec).getName()); if (curveOid == null) { curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec) ecSpec).getName()); } params = new X962Parameters(curveOid); } else if (ecSpec == null) { params = new X962Parameters(DERNull.INSTANCE); } else { ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve()); X9ECParameters ecP = new X9ECParameters( curve, new X9ECPoint(EC5Util.convertPoint(curve, ecSpec.getGenerator()), withCompression), ecSpec.getOrder(), BigInteger.valueOf(ecSpec.getCofactor()), ecSpec.getCurve().getSeed()); //// 妿æ¯1.62ææ´ä½çæ¬çbcprov-jdk15onåºè¯¥ä½¿ç¨ä»¥ä¸è¿æ®µä»£ç ï¼å 为é«çæ¬çEC5Util.convertPoint没æåä¸å ¼å®¹ /* X9ECParameters ecP = new X9ECParameters( curve, EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression), ecSpec.getOrder(), BigInteger.valueOf(ecSpec.getCofactor()), ecSpec.getCurve().getSeed()); */ params = new X962Parameters(ecP); } return params; } private static String convertEncodedDataToPEM(String type, byte[] encodedData) throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); PemWriter pWrt = new PemWriter(new OutputStreamWriter(bOut)); try { PemObject pemObj = new PemObject(type, encodedData); pWrt.writeObject(pemObj); } finally { pWrt.close(); } return new String(bOut.toByteArray()); } private static byte[] convertPEMToEncodedData(String pemString) throws IOException { ByteArrayInputStream bIn = new ByteArrayInputStream(pemString.getBytes()); PemReader pRdr = new PemReader(new InputStreamReader(bIn)); try { PemObject pemObject = pRdr.readPemObject(); return pemObject.getContent(); } finally { pRdr.close(); } } } jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/LoginUser.java
@@ -36,6 +36,10 @@ @SensitiveField private String username; @SensitiveField private String ssouserid; /** * ç»å½äººåå */ jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DepartmentSortUtil.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,92 @@ package org.jeecg.common.util; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import java.util.*; /** * é¨é¨æåº * desc: æ¥å£è·åçé¨é¨å表éè¦æç¶èç¹æå¨åé¢ï¼å¦ååèç¹æ æ³æå ¥ */ public class DepartmentSortUtil { /** * ç®åæåºæ¹æ³ - æç §æ¨çè¦æ±å¤çJSONæ°æ® * @param data JSONArrayæ°æ® * @return æåºåçJSONArray */ public static JSONArray sortDepartments(JSONArray data) { if (data == null || data.isEmpty()) { return new JSONArray(); } // 1. åç¦»æ ¹èç¹ï¼æ²¡æparentIdçï¼ååèç¹ List<JSONObject> rootNodes = new ArrayList<>(); List<JSONObject> childNodes = new ArrayList<>(); for (int i = 0; i < data.size(); i++) { JSONObject item = data.getJSONObject(i); if(item.getString("name").endsWith("å ¬å¸")){ item.put("parentId",null); } if (item.getString("parentId") == null) { rootNodes.add(item); } else { childNodes.add(item); } } // 2. æ ¹èç¹æorderNumæåº rootNodes.sort((a, b) -> { int orderA = a.getInteger("orderNum") != null ? a.getInteger("orderNum") : Integer.MAX_VALUE; int orderB = b.getInteger("orderNum") != null ? b.getInteger("orderNum") : Integer.MAX_VALUE; return Integer.compare(orderA, orderB); }); // 3. åèç¹æparentIdåç»ï¼ç¶åæ¯ç»æorderNumæåº Map<String, List<JSONObject>> childrenByParent = new HashMap<>(); for (JSONObject child : childNodes) { String parentId = child.getString("parentId"); childrenByParent.computeIfAbsent(parentId, k -> new ArrayList<>()).add(child); } // 对æ¯ä¸ªç¶èç¹ä¸çåèç¹æåº for (List<JSONObject> children : childrenByParent.values()) { children.sort((a, b) -> { int orderA = a.getInteger("orderNum") != null ? a.getInteger("orderNum") : Integer.MAX_VALUE; int orderB = b.getInteger("orderNum") != null ? b.getInteger("orderNum") : Integer.MAX_VALUE; return Integer.compare(orderA, orderB); }); } // 4. æå»ºæç»ç»æï¼æ ¹èç¹ + æparentId顺åºçåèç¹ JSONArray result = new JSONArray(); // å æ·»å æææ ¹èç¹ result.addAll(rootNodes); // ç¶åææ ¹èç¹çé¡ºåºæ·»å åèªçåèç¹ for (JSONObject root : rootNodes) { String rootId = root.getString("id"); List<JSONObject> children = childrenByParent.get(rootId); if (children != null) { result.addAll(children); } } // 5. å¤çå¯è½åå¨çå ¶ä»åèç¹ï¼parentId对åºçæ ¹èç¹ä¸å¨å½åæ°æ®ä¸ï¼ Set<String> processedParents = new HashSet<>(); for (JSONObject root : rootNodes) { processedParents.add(root.getString("id")); } for (String parentId : childrenByParent.keySet()) { if (!processedParents.contains(parentId)) { List<JSONObject> children = childrenByParent.get(parentId); result.addAll(children); } } return result; } } jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
@@ -77,6 +77,7 @@ } // é ç½®ä¸ä¼è¢«æ¦æªç龿¥ 顺åºå¤æ filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //caséªè¯ç»å½ filterChainDefinitionMap.put("/sys/cas/client/validateLogout", "anon"); //cas注é filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //ç»å½éªè¯ç æ¥å£æé¤ filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //ç»å½éªè¯ç æ¥å£æé¤ filterChainDefinitionMap.put("/sys/login", "anon"); //ç»å½æ¥å£æé¤ jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/cas/controller/CasClientController.java
@@ -1,21 +1,38 @@ package org.jeecg.modules.cas.controller; import java.util.LinkedHashMap; import java.util.List; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import com.alibaba.fastjson.JSON; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.SimplePrincipalCollection; import org.apache.shiro.subject.support.DefaultSubjectContext; import org.jeecg.common.api.vo.Result; import org.jeecg.common.constant.CacheConstant; import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.sign.SM2Utils; import org.jeecg.common.system.util.JwtUtil; import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.util.Md5Util; import org.jeecg.common.util.RedisUtil; import org.jeecg.common.util.oConvertUtils; import org.jeecg.modules.base.service.BaseCommonService; import org.jeecg.modules.cas.util.CasServiceUtil; import org.jeecg.modules.cas.util.XmlUtils; import org.jeecg.modules.system.entity.SysDepart; import org.jeecg.modules.system.entity.SysUser; import org.jeecg.modules.system.service.ISysDepartService; import org.jeecg.modules.system.service.ISysDictService; import org.jeecg.modules.system.service.ISysUserService; import org.jeecg.modules.system.service.impl.SysBaseApiImpl; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; @@ -45,67 +62,239 @@ private ISysUserService sysUserService; @Autowired private ISysDepartService sysDepartService; @Resource private BaseCommonService baseCommonService; @Autowired private SysBaseApiImpl sysBaseApi; @Autowired private RedisUtil redisUtil; @Value("${cas.prefixUrl}") private String prefixUrl; @GetMapping("/validateLogin") @Value("${cas.systemCode}") private String systemCode; @Value("${cas.DATA_PUBLIC_KEY}") private String DATA_PUBLIC_KEY; @Value("${cas.DATA_PRIVATE_KEY}") private String DATA_PRIVATE_KEY; @Value("${cas.SIGN_PUBLIC_KEY}") private String SIGN_PUBLIC_KEY; @Value("${cas.SIGN_PRIVATE_KEY}") private String SIGN_PRIVATE_KEY; @Value("${cas.SSO_KEY}") private String SSO_KEY; @Autowired private ISysDictService sysDictService; @GetMapping("/validateLogin") public Object validateLogin(@RequestParam(name="ticket") String ticket, @RequestParam(name="service") String service, HttpServletRequest request, HttpServletResponse response) throws Exception { Result<JSONObject> result = new Result<JSONObject>(); log.info("Rest api login."); log.info("sso login."); try { String validateUrl = prefixUrl+"/p3/serviceValidate"; String res = CasServiceUtil.getStValidate(validateUrl, ticket, service); log.info("res."+res); final String error = XmlUtils.getTextForElement(res, "authenticationFailure"); if(StringUtils.isNotEmpty(error)) { throw new Exception(error); } final String principal = XmlUtils.getTextForElement(res, "user"); if (StringUtils.isEmpty(principal)) { throw new Exception("No principal was found in the response from the CAS server."); } String timestamp = String.valueOf(System.currentTimeMillis()); String validateUrl = prefixUrl+"/sso/checkTicket?"; String params ="client="+systemCode + "&nonce="+RandomStringUtils.randomAlphabetic(6) + "&ssoLogoutCall=http://localhost/" +"&ticket="+ ticket +"×tamp="+timestamp; String raw = params + "&key="+SSO_KEY; String sign = Md5Util.md5Encode(raw,"utf-8"); validateUrl += params +"&sign="+sign; String res = CasServiceUtil.getStValidate(validateUrl, ticket, service); if(StringUtils.isEmpty(res)){ return Result.error("ç»å½å¤±è´¥ï¼ssoè¿åå¼å¸¸"); } JSONObject jsonObject = JSON.parseObject(res); //æ¤ ticket æåç loginId String userId = jsonObject.getString("data"); if(!jsonObject.containsKey("code") || jsonObject.getInteger("code") != 200 || StringUtils.isEmpty(userId)){ return Result.error("ç»å½å¤±è´¥ï¼ssoè¿åå¼å¸¸"); } //æ¤è´¦å·å¨ sso-server 端çä¼è¯å©ä½æææï¼åä½ï¼sï¼ Integer remainSessionTimeout = jsonObject.getInteger("remainSessionTimeout"); // è·åç»å½ç¨æ·ä¿¡æ¯ String userRan = RandomStringUtils.randomAlphabetic(6); String userStamp = String.valueOf(System.currentTimeMillis()); String userRaw = "apiType=userinfo"+"&client="+systemCode +"&loginId="+userId + "&nonce="+userRan +"×tamp="+userStamp + "&key="+SSO_KEY; String userSign = Md5Util.md5Encode(userRaw,"utf-8"); String userUrl = prefixUrl+"/sso/getData?"; String userParams ="apiType=userinfo"+"&loginId="+userId +"×tamp="+userStamp + "&nonce="+userRan+ "&sign=" + userSign + "&client="+systemCode; userUrl += userParams ; String loginRes = CasServiceUtil.getRemote(userUrl); JSONObject userRes = JSON.parseObject(loginRes); JSONObject userData = userRes.getJSONObject("data").getJSONObject("user"); if(!userRes.containsKey("code") || userRes.getInteger("code") != 200 || userData.isEmpty()){ return Result.error("ç»å½å¤±è´¥ï¼ssoç¨æ·ä¿¡æ¯è¿åå¼å¸¸"); } // final String error = XmlUtils.getTextForElement(res, "authenticationFailure"); // if(StringUtils.isNotEmpty(error)) { // throw new Exception(error); // } // final String principal = XmlUtils.getTextForElement(res, "user"); // if (StringUtils.isEmpty(principal)) { // throw new Exception("No principal was found in the response from the CAS server."); // } String principal = userData.getString("workNo"); log.info("-------token----username---"+principal); //1. æ ¡éªç¨æ·æ¯å¦ææ SysUser sysUser = sysUserService.getUserByName(principal); sysUser.setSsouserid(userId); result = sysUserService.checkUserIsEffective(sysUser); if(!result.isSuccess()) { // TODO sso éåº return result; } String token = JwtUtil.sign(sysUser.getUsername(), sysUser.getPassword()); // è®¾ç½®è¶ æ¶æ¶é´ redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token); redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000); userInfo(sysUser,result,remainSessionTimeout); //è·åç¨æ·é¨é¨ä¿¡æ¯ JSONObject obj = new JSONObject(); List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId()); obj.put("departs", departs); if (departs == null || departs.size() == 0) { obj.put("multi_depart", 0); } else if (departs.size() == 1) { sysUserService.updateUserDepart(principal, departs.get(0).getOrgCode(),null); obj.put("multi_depart", 1); } else { obj.put("multi_depart", 2); } obj.put("token", token); obj.put("userInfo", sysUser); result.setResult(obj); result.success("ç»å½æå"); } catch (Exception e) { //e.printStackTrace(); LoginUser loginUser = new LoginUser(); BeanUtils.copyProperties(sysUser, loginUser); baseCommonService.addLog("ç¨æ·å: " + sysUser.getRealname() + ",ssoç»å½æåï¼", CommonConstant.LOG_TYPE_1, null,loginUser); // åæ¥æ´æ°ç¨æ·ç¼åï¼ç¡®ä¿ShiroRealm读åå°å¸¦æssoç¨æ·IDçLoginUser redisUtil.set(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, loginUser.getUsername()), loginUser); // 使ç¨JWT忬¡è§¦åShiroç»å½ï¼ä½¿å½å请æ±çSubjectææå å«ssouseridçPrincipal String token = result.getResult().getString("token"); try { SecurityUtils.getSubject().login(new org.jeecg.config.shiro.JwtToken(token)); LoginUser u = (LoginUser) SecurityUtils.getSubject().getPrincipal(); System.err.println(u); log.info("Shiro JWTç»å½æå"); } catch (AuthenticationException e) { log.error("Shiro认è¯å¤±è´¥: {}", e.getMessage()); return Result.error("Shiro认è¯å¤±è´¥"); } } catch (Exception e) { e.printStackTrace(); result.error500(e.getMessage()); ssoLogOut(); } return new HttpEntity<>(result); } /** * ç¨æ·ä¿¡æ¯ * * @param sysUser * @param result * @return */ private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result,int timeout) { String username = sysUser.getUsername(); String syspassword = sysUser.getPassword(); // è·åç¨æ·é¨é¨ä¿¡æ¯ JSONObject obj = new JSONObject(new LinkedHashMap<>()); //1.çætoken String token = JwtUtil.sign(username, syspassword); // 设置tokenç¼åæææ¶é´ redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token); redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, timeout); obj.put("token", token); //2.设置ç»å½ç§æ· Result<JSONObject> loginTenantError = sysUserService.setLoginTenant(sysUser, obj, username,result); if (loginTenantError != null) { return loginTenantError; } //3.设置ç»å½ç¨æ·ä¿¡æ¯ obj.put("userInfo", sysUser); //4.设置ç»å½é¨é¨ List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId()); obj.put("departs", departs); if (departs == null || departs.size() == 0) { obj.put("multi_depart", 0); } else if (departs.size() == 1) { sysUserService.updateUserDepart(username, departs.get(0).getOrgCode(),null); obj.put("multi_depart", 1); } else { //æ¥è¯¢å½åæ¯å¦æç»å½é¨é¨ // update-begin--Author:wangshuai Date:20200805 forï¼å¦æç¨æ¶ä¸ºéæ©é¨é¨ï¼æ°æ®åºä¸ºåå¨ä¸ä¸æ¬¡ç»å½é¨é¨ï¼åå䏿¡åè¿å» SysUser sysUserById = sysUserService.getById(sysUser.getId()); if(oConvertUtils.isEmpty(sysUserById.getOrgCode())){ sysUserService.updateUserDepart(username, departs.get(0).getOrgCode(),null); } // update-end--Author:wangshuai Date:20200805 forï¼å¦æç¨æ¶ä¸ºéæ©é¨é¨ï¼æ°æ®åºä¸ºåå¨ä¸ä¸æ¬¡ç»å½é¨é¨ï¼åå䏿¡åè¿å» obj.put("multi_depart", 2); } obj.put("sysAllDictItems", sysDictService.queryAllDictItems()); //SecurityUtils.getSubject().login(new org.jeecg.config.shiro.JwtToken(token)); result.setResult(obj); result.success("ç»å½æå"); return result; } @GetMapping("/validateLogout") public Result<Object> logout(HttpServletRequest request,HttpServletResponse response) { String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN); if(oConvertUtils.isEmpty(token)) { return Result.error("éåºç»å½å¤±è´¥ï¼"); } try { SecurityUtils.getSubject().login(new org.jeecg.config.shiro.JwtToken(token)); } catch (AuthenticationException e) { } JSONObject jsonObject = ssoLogOut(); if(!jsonObject.containsKey("code") || jsonObject.getInteger("code") != 200 ){ return Result.error("éåºç»å½å¤±è´¥ï¼sso注éå¼å¸¸"); } //æ¬ç³»ç»éåºé»è¾ //ç¨æ·éåºé»è¾ if(oConvertUtils.isEmpty(token)) { return Result.error("éåºç»å½å¤±è´¥ï¼"); } String username = JwtUtil.getUsername(token); LoginUser sysUser = sysBaseApi.getUserByName(username); if(sysUser!=null) { //update-begin--Author:wangshuai Date:20200714 forï¼ç»åºæ¥å¿æ²¡æè®°å½äººå baseCommonService.addLog("ç¨æ·å: "+sysUser.getRealname()+",éåºæåï¼", CommonConstant.LOG_TYPE_1, null,sysUser); //update-end--Author:wangshuai Date:20200714 forï¼ç»åºæ¥å¿æ²¡æè®°å½äººå log.info(" ç¨æ·å: "+sysUser.getRealname()+",éåºæåï¼ "); //æ¸ ç©ºç¨æ·ç»å½Tokenç¼å redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token); //æ¸ ç©ºç¨æ·ç»å½Shiroæéç¼å redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId()); //æ¸ ç©ºç¨æ·çç¼åä¿¡æ¯ï¼å æ¬é¨é¨ä¿¡æ¯ï¼ï¼ä¾å¦sys:cache:user::<username> redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername())); //è°ç¨shiroçlogout SecurityUtils.getSubject().logout(); return Result.ok("éåºç»å½æåï¼"); }else { return Result.error("Tokenæ æ!"); } } private JSONObject ssoLogOut(){ LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); //ssoéåºé»è¾ String userId = loginUser.getSsouserid(); String outRan = RandomStringUtils.randomAlphabetic(6); String outStamp = String.valueOf(System.currentTimeMillis()); String outRaw ="client="+systemCode + "&loginId="+userId + "&nonce="+outRan + "×tamp="+outStamp + "&key="+SSO_KEY; String outSign = Md5Util.md5Encode(outRaw,"utf-8"); String outUrl = prefixUrl+"/sso/signout?"; String outParams ="loginId="+userId +"×tamp="+outStamp + "&nonce="+outRan+ "&sign=" + outSign + "&client="+systemCode; outUrl += outParams ; String outRes = CasServiceUtil.getRemote(outUrl); return JSON.parseObject(outRes); } } jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/cas/util/CasServiceUtil.java
@@ -11,8 +11,10 @@ import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.socket.LayeredConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; @@ -37,7 +39,6 @@ */ public static String getStValidate(String url, String st, String service){ try { url = url+"?service="+service+"&ticket="+st; CloseableHttpClient httpclient = createHttpClientWithNoSsl(); HttpGet httpget = new HttpGet(url); HttpResponse response = httpclient.execute(httpget); @@ -49,7 +50,44 @@ return ""; } /** * 䏿¹getè¯·æ± * @param url * @return */ public static String getRemote(String url){ try { CloseableHttpClient httpclient = createHttpClientWithNoSsl(); HttpGet httpget = new HttpGet(url); HttpResponse response = httpclient.execute(httpget); String res = readResponse(response); return res == null ? null : (res == "" ? null : res); } catch (Exception e) { e.printStackTrace(); } return ""; } /** * 䏿¹postè¯·æ± * @param url * @return */ public static String postRemote(String url,String sign){ try { CloseableHttpClient httpclient = createHttpClientWithNoSsl(); HttpPost httpost = new HttpPost(url); httpost.setHeader("sign", sign); HttpResponse response = httpclient.execute(httpost); String res = readResponse(response); return res == null ? null : (res == "" ? null : res); } catch (Exception e) { e.printStackTrace(); } return ""; } /** * 读å response body å 容为å符串 * jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDepartController.java
@@ -193,7 +193,19 @@ return result; } /** @RequestMapping(value = "/syncTenantDept", method = RequestMethod.GET) public Result<?> syncTenantDept(){ try { return sysDepartService.syncTenantDept(); }catch (Exception e){ e.printStackTrace(); } return Result.error("æä½å¤±è´¥ï¼è¯·è系管çåï¼"); } /** * ç¼è¾æ°æ® ç¼è¾é¨é¨çé¨åæ°æ®,å¹¶ä¿åå°æ°æ®åº * * @param sysDepart jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysUserController.java
@@ -135,8 +135,7 @@ @RequestMapping(value = "/syncTenantUser", method = RequestMethod.GET) public Result<?> syncTenantUser(){ try { String message = sysUserService.syncTenantUser(); return Result.ok(message); return sysUserService.syncTenantUser(); }catch (Exception e){ e.printStackTrace(); } jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysUser.java
@@ -209,4 +209,10 @@ * æµç¨ç¶æ */ private String bpmStatus; /** * sso */ @TableField(exist = false) private String ssouserid; } jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ISysDepartService.java
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import org.jeecg.common.api.vo.Result; import org.jeecg.modules.system.entity.SysDepart; import org.jeecg.modules.system.model.DepartIdModel; import org.jeecg.modules.system.model.SysDepartTreeModel; @@ -34,6 +35,12 @@ */ List<SysDepartTreeModel> queryTreeList(); /** * åæ¥ç§æ·é¨é¨ * @return */ Result<Object> syncTenantDept(); /** * æ¥è¯¢ææé¨é¨ä¿¡æ¯,å¹¶åèç¹è¿è¡æ¾ç¤º jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ISysUserService.java
@@ -390,5 +390,9 @@ */ void editTenantUser(SysUser sysUser, String tenantId, String departs, String roles); String syncTenantUser(); /** * åæ¥ç§æ·ç¨æ· * @return */ Result<Object> syncTenantUser(); } jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysDepartServiceImpl.java
@@ -1,5 +1,6 @@ package org.jeecg.modules.system.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -11,15 +12,19 @@ import io.netty.util.internal.StringUtil; import org.apache.commons.lang.StringUtils; import org.apache.shiro.SecurityUtils; import org.jeecg.common.api.vo.Result; import org.jeecg.common.config.TenantContext; import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.constant.FillRuleConstant; import org.jeecg.common.constant.SymbolConstant; import org.jeecg.common.sign.SM2Utils; import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.util.DepartmentSortUtil; import org.jeecg.common.util.FillRuleUtil; import org.jeecg.common.util.YouBianCodeUtil; import org.jeecg.common.util.oConvertUtils; import org.jeecg.config.mybatis.MybatisPlusSaasConfig; import org.jeecg.modules.cas.util.CasServiceUtil; import org.jeecg.modules.system.entity.*; import org.jeecg.modules.system.mapper.*; import org.jeecg.modules.system.model.DepartIdModel; @@ -27,7 +32,9 @@ import org.jeecg.modules.system.service.ISysDepartService; import org.jeecg.modules.system.util.FindsDepartsChildrenUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.Cacheable; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +67,18 @@ private SysUserMapper sysUserMapper; @Autowired private SysDepartMapper departMapper; @Lazy @Autowired private ISysDepartService departService; @Value("${cas.prefixUrl}") private String prefixUrl; @Value("${cas.systemCode}") private String systemCode; @Value("${cas.SIGN_PRIVATE_KEY}") private String SIGN_PRIVATE_KEY; @Override public List<SysDepartTreeModel> queryMyDeptTreeList(String departIds) { @@ -118,7 +137,85 @@ return listResult; } /** @Override public Result<Object> syncTenantDept() { LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0); if(tenantId == 0){ return Result.error("请ç»å½ç§æ·ç®¡çåå忥é¨é¨ï¼"); } //ç»ç»æºæ String orgStamp = String.valueOf(System.currentTimeMillis()); String orgRaw = "systemCode="+ systemCode + "×tamp="+ orgStamp; String orgSign = SM2Utils.getInstance().sign(orgRaw,SIGN_PRIVATE_KEY); String orgUrl = prefixUrl+"/api/org/list?"; String orgParams = "systemCode="+ systemCode +"×tamp="+ orgStamp; orgUrl += orgParams; String orgRes = CasServiceUtil.postRemote(orgUrl,orgSign); if(orgRes == null){ return Result.error("忥æ¥å£æªè¿åæ°æ®ï¼"); } JSONObject jsonObject = JSON.parseObject(orgRes); JSONArray data = jsonObject.getJSONArray("data"); if(jsonObject.getInteger("code") != 200 || data.isEmpty()){ return Result.error("忥æ¥å£è¿åç©ºæ°æ®ï¼"); } LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<SysDepart>(); queryWrapper.eq(SysDepart::getTenantId, tenantId); List<SysDepart> existDeptList = departService.list(queryWrapper); Map<String, SysDepart> deptMap = existDeptList.stream() .collect(Collectors.toMap(SysDepart::getId, dept -> dept)); JSONArray jsonArray = DepartmentSortUtil.sortDepartments(data); for (int i = 0; i < jsonArray.size(); i++) { JSONObject obj = jsonArray.getJSONObject(i); SysDepart depart = new SysDepart(); String name = obj.getString("name"); String parentId = obj.getString("parentId"); if(!StringUtils.isEmpty(name) && name.endsWith("å ¬å¸")){ depart.setOrgCategory("1"); depart.setParentId(null); }else { depart.setOrgCategory("2"); depart.setParentId(parentId); } depart.setDepartName(name); depart.setId(obj.getString("id")); JSONObject formData = new JSONObject(); formData.put("parentId",parentId); String[] codeArray = (String[]) FillRuleUtil.executeRule(FillRuleConstant.DEPART,formData); //æparentId使°æ®åºæ¾ä¸å°parenIdçåèç¹æ æ³æå ¥ if(codeArray == null){ continue; } //update-end--Author:baihailong Date:20191209 forï¼é¨é¨ç¼ç è§åçæå¨åæå ¬ç¨é ç½® depart.setOrgCode(codeArray[0]); depart.setCreateBy(sysUser.getUsername()); String orgType = codeArray[1]; depart.setOrgType(String.valueOf(orgType)); depart.setCreateTime(new Date()); depart.setDelFlag(CommonConstant.DEL_FLAG_0.toString()); depart.setDepartOrder(obj.getInteger("orderNum")); depart.setTenantId(tenantId); depart.setIzLeaf(1); if(!deptMap.containsKey(depart.getId())){ departMapper.insert(depart); if (StringUtils.isNotBlank(parentId)) { //å°ç¶é¨é¨ç设æä¸æ¯å¶åç»ç¹ departMapper.setMainLeaf(depart.getParentId(),CommonConstant.NOT_LEAF); } } } return Result.ok("æä½æåï¼"); } /** * queryTreeList æ ¹æ®é¨é¨idæ¥è¯¢,åç«¯åæ¾è°ç¨ */ @Override jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysUserServiceImpl.java
@@ -24,11 +24,13 @@ import org.jeecg.common.constant.enums.RoleIndexConfigEnum; import org.jeecg.common.desensitization.annotation.SensitiveEncode; import org.jeecg.common.exception.JeecgBootException; import org.jeecg.common.sign.SM2Utils; import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.system.vo.SysUserCacheInfo; import org.jeecg.common.util.*; import org.jeecg.config.mybatis.MybatisPlusSaasConfig; import org.jeecg.modules.base.service.BaseCommonService; import org.jeecg.modules.cas.util.CasServiceUtil; import org.jeecg.modules.system.bo.TenantUserBo; import org.jeecg.modules.system.entity.*; import org.jeecg.modules.system.mapper.*; @@ -42,6 +44,7 @@ import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.context.annotation.Lazy; @@ -99,6 +102,15 @@ private SysUserTenantMapper relationMapper; @Autowired private SysUserTenantMapper userTenantMapper; @Value("${cas.prefixUrl}") private String prefixUrl; @Value("${cas.systemCode}") private String systemCode; @Value("${cas.SIGN_PRIVATE_KEY}") private String SIGN_PRIVATE_KEY; @Override public Result<IPage<SysUser>> queryPageList(HttpServletRequest req, QueryWrapper<SysUser> queryWrapper, Integer pageSize, Integer pageNo) { @@ -647,14 +659,14 @@ //update-begin---author:wangshuai ---date:20230112 forï¼ç¨æ·åå»ºçæ¶åå¢å 临æ¶è§è² test------------ //å¼å¯ç§æ·saasæ¨¡å¼ if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) { String testRoleId = "ee8626f80f7c2619917b6236f3a7f02b"; //妿åå°æ²¡æä¼ éè§è²æè ä¼ è¿æ¥çå«è²æ²¡æä¸´æ¶è§è²,é£ä¹é»è®¤ä¸´æ¶è§è² test if (oConvertUtils.isEmpty(selectedRoles) || !selectedRoles.contains(testRoleId)) { SysUserRole userRole = new SysUserRole(user.getId(), testRoleId); sysUserRoleMapper.insert(userRole); } } // if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) { // String testRoleId = "ee8626f80f7c2619917b6236f3a7f02b"; // //妿åå°æ²¡æä¼ éè§è²æè ä¼ è¿æ¥çå«è²æ²¡æä¸´æ¶è§è²,é£ä¹é»è®¤ä¸´æ¶è§è² test // if (oConvertUtils.isEmpty(selectedRoles) || !selectedRoles.contains(testRoleId)) { // SysUserRole userRole = new SysUserRole(user.getId(), testRoleId); // sysUserRoleMapper.insert(userRole); // } // } //update-end---author:wangshuai ---date:20230112 forï¼ç¨æ·åå»ºçæ¶åå¢å 临æ¶è§è² test------------ //step.3 ä¿åæå±é¨é¨ @@ -1232,24 +1244,54 @@ } @Override @Transactional(rollbackFor = Exception.class) public String syncTenantUser() { public Result<Object> syncTenantUser() { LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0); if(tenantId == 0){ return "请ç»å½ç§æ·ç®¡çåååæ¥ç¨æ·ï¼"; return Result.error("请ç»å½ç§æ·ç®¡çåååæ¥ç¨æ·ï¼"); } // æ¨¡ææ¥å£æ°æ® TODOä½¿ç¨æ¥å£æ°æ® String json = "{\"code\":200,\"msg\":\"å¤çæå\",\"data\":[{\"id\":\"621466726\",\"name\":\"ç³ä¸\",\"birthday\":\"1992-08-19\",\"rank\":\"bad0f40d-6ed9-4d7a-82f8-95af7d9f47d5\",\"firstOrgName\":\"ä¿¡æ¯é¨\",\"firstOrgId\":\"1632356\",\"orgName\":\"ä¿¡æ¯é¨\",\"orgId\":\"1632356\",\"post\":null,\"postId\":null,\"status\":\"\",\"jobStatus\":\"\",\"workNo\":\"6518\",\"mobile\":\"13658340793\",\"leaderId\":\"619347944\",\"leader\":\"ç¨äºé£\"},{\"id\":\"621466727\",\"name\":\"å¼ ä¸\",\"birthday\":\"1993-05-15\",\"rank\":\"bad0f40d-6ed9-4d7a-82f8-95af7d9f47d6\",\"firstOrgName\":\"ææ¯é¨\",\"firstOrgId\":\"1632357\",\"orgName\":\"ææ¯é¨\",\"orgId\":\"1632357\",\"post\":\"å·¥ç¨å¸\",\"postId\":\"1001\",\"status\":\"å¨è\",\"jobStatus\":\"æ£å¸¸\",\"workNo\":\"6519\",\"mobile\":\"13658340794\",\"leaderId\":\"619347945\",\"leader\":\"æå\"},{\"id\":\"621466728\",\"name\":\"çäº\",\"birthday\":\"1991-12-20\",\"rank\":\"bad0f40d-6ed9-4d7a-82f8-95af7d9f47d7\",\"firstOrgName\":\"å¸åºé¨\",\"firstOrgId\":\"1632358\",\"orgName\":\"å¸åºé¨\",\"orgId\":\"1632358\",\"post\":\"ç»ç\",\"postId\":\"1002\",\"status\":\"å¨è\",\"jobStatus\":\"æ£å¸¸\",\"workNo\":\"6520\",\"mobile\":\"13658340795\",\"leaderId\":\"619347946\",\"leader\":\"èµµå \"}]}"; JSONObject jsonObject = JSON.parseObject(json); // æ¨¡ææ¥å£æ°æ® // String json = "{\"code\":200,\"msg\":\"å¤çæå\",\"data\":[{\"id\":\"621466726\",\"name\":\"ç³ä¸\",\"birthday\":\"1992-08-19\",\"rank\":\"bad0f40d-6ed9-4d7a-82f8-95af7d9f47d5\",\"firstOrgName\":\"ä¿¡æ¯é¨\",\"firstOrgId\":\"1632356\",\"orgName\":\"ä¿¡æ¯é¨\",\"orgId\":\"1632356\",\"post\":null,\"postId\":null,\"status\":\"\",\"jobStatus\":\"\",\"workNo\":\"6518\",\"mobile\":\"13658340793\",\"leaderId\":\"619347944\",\"leader\":\"ç¨äºé£\"},{\"id\":\"621466727\",\"name\":\"å¼ ä¸\",\"birthday\":\"1993-05-15\",\"rank\":\"bad0f40d-6ed9-4d7a-82f8-95af7d9f47d6\",\"firstOrgName\":\"ææ¯é¨\",\"firstOrgId\":\"1632357\",\"orgName\":\"ææ¯é¨\",\"orgId\":\"1632357\",\"post\":\"å·¥ç¨å¸\",\"postId\":\"1001\",\"status\":\"å¨è\",\"jobStatus\":\"æ£å¸¸\",\"workNo\":\"6519\",\"mobile\":\"13658340794\",\"leaderId\":\"619347945\",\"leader\":\"æå\"},{\"id\":\"621466728\",\"name\":\"çäº\",\"birthday\":\"1991-12-20\",\"rank\":\"bad0f40d-6ed9-4d7a-82f8-95af7d9f47d7\",\"firstOrgName\":\"å¸åºé¨\",\"firstOrgId\":\"1632358\",\"orgName\":\"å¸åºé¨\",\"orgId\":\"1632358\",\"post\":\"ç»ç\",\"postId\":\"1002\",\"status\":\"å¨è\",\"jobStatus\":\"æ£å¸¸\",\"workNo\":\"6520\",\"mobile\":\"13658340795\",\"leaderId\":\"619347946\",\"leader\":\"èµµå \"}]}"; //ç¨æ·å表 String ulStamp = String.valueOf(System.currentTimeMillis()); String ulRaw = "systemCode="+ systemCode + "×tamp="+ ulStamp; String ulSign = SM2Utils.getInstance().sign(ulRaw,SIGN_PRIVATE_KEY); String ulUrl = prefixUrl+"/api/user/list?"; String ulParams = "systemCode="+ systemCode + "×tamp="+ ulStamp; ulUrl += ulParams; String ulRes = CasServiceUtil.postRemote(ulUrl, ulSign); if(ulRes == null){ return Result.error("忥æ¥å£æªè¿åæ°æ®ï¼"); } JSONObject jsonObject = JSON.parseObject(ulRes); JSONArray data = jsonObject.getJSONArray("data"); List<TenantUserBo> remoteTenantUserList = data.toJavaList(TenantUserBo.class); System.err.println(remoteTenantUserList); if(jsonObject.getInteger("code") != 200 || data.isEmpty()){ return Result.error("忥æ¥å£è¿åç©ºæ°æ®ï¼"); } List<TenantUserBo> remoteTenantUserList = data.toJavaList(TenantUserBo.class) .stream() .filter(user -> { String workNo = user.getWorkNo(); return workNo != null && !workNo.trim().isEmpty(); }) .collect(Collectors.toMap( user -> user.getWorkNo().trim().toUpperCase(), // å»é¤é¦å°¾ç©ºæ ¼ user -> user, (existing, replacement) -> { // å¯ä»¥å¨è¿éæ·»å æ¥å¿æ¥çé夿 åµ System.out.println("åç°éå¤workNo: " + replacement.getWorkNo()); return replacement; } )) .values() .stream() .collect(Collectors.toList()); // æ¥è¯¢ç§æ·ä¸ç¨æ· List<String> tenantUserIds = userTenantMapper.getUserIdsByTenantId(tenantId); LambdaQueryWrapper<SysUser> userQueryWrapper = new LambdaQueryWrapper<>(); userQueryWrapper.in(SysUser::getId, tenantUserIds); userQueryWrapper.in(SysUser::getTenantId, tenantId); List<SysUser> tenantUserList = this.baseMapper.selectList(userQueryWrapper); @@ -1269,40 +1311,57 @@ .collect(Collectors.toList()); AtomicInteger successCount = new AtomicInteger(0); AtomicInteger failedCount = new AtomicInteger(0); for (int i = 0; i <remoteNotInTenant.size() ; i++) { TenantUserBo tenantUserBo = remoteNotInTenant.get(i); addUser(tenantUserBo,tenantId,successCount,failedCount); } addUser(remoteNotInTenant,tenantId,successCount,failedCount); if(remoteTenantUserList.size()>0){ return "忥"+remoteTenantUserList.size()+"æ¡æ°æ®ï¼å·²åå¨"+remoteInTenant.size() +"æ¡ï¼æåæ°å¢"+successCount.get()+"æ¡ï¼å¤±è´¥"+failedCount.get()+"æ¡"; return Result.ok("æ¥å°"+remoteTenantUserList.size()+"æ¡æ°æ®ï¼å·²åå¨"+remoteInTenant.size() +"æ¡ï¼æåæ°å¢"+successCount.get()+"æ¡ï¼"); } return "忥æ¥å£æªè¿åæ°æ®ï¼"; return Result.error("忥æ¥å£æªè¿åæ°æ®ï¼"); } private void addUser(TenantUserBo tenantUserBo,Integer tenantId,AtomicInteger successCount, AtomicInteger failedCount) { SysUser user = new SysUser(); user.setLoginTenantId(tenantId); user.setTenantId(tenantId); user.setCreateTime(new Date());// 设置å建æ¶é´ String salt = oConvertUtils.randomGen(8); String passwordEncode = PasswordUtil.encrypt(tenantUserBo.getWorkNo(), "123456", salt); user.setSalt(salt); user.setUsername(tenantUserBo.getWorkNo()); user.setRealname(tenantUserBo.getName()); user.setPassword(passwordEncode); user.setPhone(tenantUserBo.getMobile()); user.setStatus(CommonConstant.USER_UNFREEZE); user.setDelFlag(CommonConstant.DEL_FLAG_0); user.setActivitiSync(CommonConstant.ACT_SYNC_0); boolean save = this.save(user); private void addUser(List<TenantUserBo> remoteNotInTenantList,Integer tenantId,AtomicInteger successCount, AtomicInteger failedCount) { if(save){ this.saveUserTenant(user.getId(),String.valueOf(tenantId)); LambdaQueryWrapper<SysDepart> departQueryWrapper = new LambdaQueryWrapper<>(); departQueryWrapper.eq(SysDepart::getTenantId, tenantId); List<SysDepart> departList = sysDepartMapper.selectList(departQueryWrapper); // ææé¨é¨ Map<String, String> departMap = departList.stream() .collect(Collectors.toMap( SysDepart::getDepartName, SysDepart::getId, (existing, replacement) -> existing )); LambdaQueryWrapper<SysRole> roleLambdaQueryWrapper = new LambdaQueryWrapper<>(); roleLambdaQueryWrapper.eq(SysRole::getRoleCode, "TJT-PT"); roleLambdaQueryWrapper.eq(SysRole::getTenantId, tenantId); SysRole role = sysRoleMapper.selectOne(roleLambdaQueryWrapper); for (int i = 0; i <remoteNotInTenantList.size() ; i++) { TenantUserBo tenantUserBo = remoteNotInTenantList.get(i); SysUser user = new SysUser(); user.setId(tenantUserBo.getId()); user.setLoginTenantId(tenantId); user.setTenantId(tenantId); user.setCreateTime(new Date());// 设置å建æ¶é´ String salt = oConvertUtils.randomGen(8); String passwordEncode = PasswordUtil.encrypt(tenantUserBo.getWorkNo(), "123456", salt); user.setSalt(salt); user.setUsername(tenantUserBo.getWorkNo()); user.setRealname(tenantUserBo.getName()); user.setPassword(passwordEncode); user.setPhone(tenantUserBo.getMobile()); user.setStatus(CommonConstant.USER_UNFREEZE); user.setDelFlag(CommonConstant.DEL_FLAG_0); user.setActivitiSync(CommonConstant.ACT_SYNC_0); user.setWorkNo(tenantUserBo.getWorkNo()); successCount.incrementAndGet(); }else { failedCount.incrementAndGet(); String depart = departMap.get(tenantUserBo.getOrgName()) ; this.saveUser(user,role.getId(),depart,tenantId+""); } } /**