Procházet zdrojové kódy

后台添加公钥返回,以及前端传值密码解密加密

gt před 2 roky
rodič
revize
519f377bd5

+ 6 - 0
chuanyi_server/src/main/java/com/judong/chuanyiserver/controller/UserController.java

@@ -8,6 +8,7 @@ import com.judong.chuanyiserver.entity.User;
 import com.judong.chuanyiserver.enums.ResultEnum;
 import com.judong.chuanyiserver.service.UserService;
 import com.judong.chuanyiserver.util.Blank;
+import com.judong.chuanyiserver.util.RSAUtil;
 import com.judong.chuanyiserver.util.Result;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -19,6 +20,11 @@ public class UserController {
     @Autowired
     private UserService userService;
 
+    @GetMapping("/getPublicKey")
+    public Result getPublicKey() {
+        return Result.ok(RSAUtil.PUBLIC_KEY);
+    }
+
 
     /**
      * 前端用户登录

+ 11 - 0
chuanyi_server/src/main/java/com/judong/chuanyiserver/service/impl/UserServiceImpl.java

@@ -6,6 +6,7 @@ import com.judong.chuanyiserver.entity.Permission;
 import com.judong.chuanyiserver.entity.Role;
 import com.judong.chuanyiserver.entity.User;
 import com.judong.chuanyiserver.enums.ResultEnum;
+import com.judong.chuanyiserver.exception.CustomException;
 import com.judong.chuanyiserver.service.UserService;
 import com.judong.chuanyiserver.util.*;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -38,6 +39,11 @@ public class UserServiceImpl implements UserService {
      */
     @Override
     public Result frontUserLogin(String userName, String password) {
+        try {
+            password = RSAUtil.decrypt(password, "UTF-8");
+        } catch (Exception e) {
+            throw new CustomException(ResultEnum.SERVER_ERROR.getRespCode(), ResultEnum.SERVER_ERROR.getRespMsg());
+        }
         User user = userDao.getUserByNamePass(userName, EncryptUtils.StrToMD5(password));
         if (Blank.isEmpty(user)) {
             return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "用户名或密码错误");
@@ -67,6 +73,11 @@ public class UserServiceImpl implements UserService {
      */
     @Override
     public Result backUserLogin(String userName, String password) {
+        try {
+            password = RSAUtil.decrypt(password, "UTF-8");
+        } catch (Exception e) {
+            throw new CustomException(ResultEnum.SERVER_ERROR.getRespCode(), ResultEnum.SERVER_ERROR.getRespMsg());
+        }
         User user = userDao.getUserByNamePass(userName, EncryptUtils.StrToMD5(password));
         if (Blank.isEmpty(user)) {
             return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "用户名或密码错误");

+ 358 - 0
chuanyi_server/src/main/java/com/judong/chuanyiserver/util/Base64Util.java

@@ -0,0 +1,358 @@
+package com.judong.chuanyiserver.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Base64Util {
+
+	private static final int BASELENGTH = 128;
+	private static final int LOOKUPLENGTH = 64;
+	private static final int TWENTYFOURBITGROUP = 24;
+	private static final int EIGHTBIT = 8;
+	private static final int SIXTEENBIT = 16;
+	private static final int FOURBYTE = 4;
+	private static final int SIGN = -128;
+	private static final char PAD = '=';
+	private static final boolean fDebug = false;
+	private static final byte[] base64Alphabet = new byte[BASELENGTH];
+	private static final char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
+
+	static {
+		for (int i = 0; i < BASELENGTH; ++i) {
+			base64Alphabet[i] = -1;
+		}
+		for (int i = 'Z'; i >= 'A'; i--) {
+			base64Alphabet[i] = (byte) (i - 'A');
+		}
+		for (int i = 'z'; i >= 'a'; i--) {
+			base64Alphabet[i] = (byte) (i - 'a' + 26);
+		}
+		for (int i = '9'; i >= '0'; i--) {
+			base64Alphabet[i] = (byte) (i - '0' + 52);
+		}
+		base64Alphabet['+'] = 62;
+		base64Alphabet['/'] = 63;
+		for (int i = 0; i <= 25; i++) {
+			lookUpBase64Alphabet[i] = (char) ('A' + i);
+		}
+		for (int i = 26, j = 0; i <= 51; i++, j++) {
+			lookUpBase64Alphabet[i] = (char) ('a' + j);
+		}
+		for (int i = 52, j = 0; i <= 61; i++, j++) {
+			lookUpBase64Alphabet[i] = (char) ('0' + j);
+		}
+		lookUpBase64Alphabet[62] = (char) '+';
+		lookUpBase64Alphabet[63] = (char) '/';
+
+	}
+
+	private static boolean isWhiteSpace(char octect) {
+		return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
+	}
+
+	private static boolean isPad(char octect) {
+		return (octect == PAD);
+	}
+
+	private static boolean isData(char octect) {
+		return (octect < BASELENGTH && base64Alphabet[octect] != -1);
+	}
+
+	/**
+	 * Encodes hex octects into Base64
+	 *
+	 * @param binaryData Array containing binaryData
+	 * @return Encoded Base64 array
+	 */
+	public static String encode(byte[] binaryData) {
+		if (binaryData == null) {
+			return null;
+		}
+		int lengthDataBits = binaryData.length * EIGHTBIT;
+		if (lengthDataBits == 0) {
+			return "";
+		}
+		int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
+		int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
+		int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
+		char encodedData[] = null;
+		encodedData = new char[numberQuartet * 4];
+		byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
+		int encodedIndex = 0;
+		int dataIndex = 0;
+		if (fDebug) {
+			System.out.println("number of triplets = " + numberTriplets);
+		}
+		for (int i = 0; i < numberTriplets; i++) {
+			b1 = binaryData[dataIndex++];
+			b2 = binaryData[dataIndex++];
+			b3 = binaryData[dataIndex++];
+			if (fDebug) {
+				System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
+			}
+			l = (byte) (b2 & 0x0f);
+			k = (byte) (b1 & 0x03);
+			byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+			byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+			byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
+			if (fDebug) {
+				System.out.println("val2 = " + val2);
+				System.out.println("k4   = " + (k << 4));
+				System.out.println("vak  = " + (val2 | (k << 4)));
+			}
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
+		}
+
+		// form integral number of 6-bit groups
+		if (fewerThan24bits == EIGHTBIT) {
+			b1 = binaryData[dataIndex];
+			k = (byte) (b1 & 0x03);
+			if (fDebug) {
+				System.out.println("b1=" + b1);
+				System.out.println("b1<<2 = " + (b1 >> 2));
+			}
+			byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
+			encodedData[encodedIndex++] = PAD;
+			encodedData[encodedIndex++] = PAD;
+		} else if (fewerThan24bits == SIXTEENBIT) {
+			b1 = binaryData[dataIndex];
+			b2 = binaryData[dataIndex + 1];
+			l = (byte) (b2 & 0x0f);
+			k = (byte) (b1 & 0x03);
+			byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+			byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
+			encodedData[encodedIndex++] = PAD;
+		}
+		return new String(encodedData);
+	}
+
+	/**
+	 * Decodes Base64 data into octects
+	 *
+	 * @param encoded string containing Base64 data
+	 * @return Array containind decoded data.
+	 */
+	public static byte[] decode(String encoded) {
+		if (encoded == null) {
+			return null;
+		}
+		char[] base64Data = encoded.toCharArray();
+		// remove white spaces
+		int len = removeWhiteSpace(base64Data);
+		if (len % FOURBYTE != 0) {
+			return null;// should be divisible by four
+		}
+		int numberQuadruple = (len / FOURBYTE);
+		if (numberQuadruple == 0) {
+			return new byte[0];
+		}
+		byte decodedData[] = null;
+		byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
+		char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
+		int i = 0;
+		int encodedIndex = 0;
+		int dataIndex = 0;
+		decodedData = new byte[(numberQuadruple) * 3];
+		for (; i < numberQuadruple - 1; i++) {
+			if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
+					|| !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) {
+				return null;
+			} // if found "no data" just return null
+			b1 = base64Alphabet[d1];
+			b2 = base64Alphabet[d2];
+			b3 = base64Alphabet[d3];
+			b4 = base64Alphabet[d4];
+			decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+			decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+			decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+		}
+		if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
+			return null;// if found "no data" just return null
+		}
+		b1 = base64Alphabet[d1];
+		b2 = base64Alphabet[d2];
+		d3 = base64Data[dataIndex++];
+		d4 = base64Data[dataIndex++];
+		if (!isData((d3)) || !isData((d4))) {// Check if they are PAD characters
+			if (isPad(d3) && isPad(d4)) {
+				if ((b2 & 0xf) != 0)// last 4 bits should be zero
+				{
+					return null;
+				}
+				byte[] tmp = new byte[i * 3 + 1];
+				System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+				tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+				return tmp;
+			} else if (!isPad(d3) && isPad(d4)) {
+				b3 = base64Alphabet[d3];
+				if ((b3 & 0x3) != 0)// last 2 bits should be zero
+				{
+					return null;
+				}
+				byte[] tmp = new byte[i * 3 + 2];
+				System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+				tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+				tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+				return tmp;
+			} else {
+				return null;
+			}
+		} else { // No PAD e.g 3cQl
+			b3 = base64Alphabet[d3];
+			b4 = base64Alphabet[d4];
+			decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+			decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+			decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+		}
+
+		return decodedData;
+	}
+
+	/**
+	 * remove WhiteSpace from MIME containing encoded Base64 data.
+	 *
+	 * @param data the byte array of base64 data (with WS)
+	 * @return the new length
+	 */
+	private static int removeWhiteSpace(char[] data) {
+		if (data == null) {
+			return 0;
+		}
+		// count characters that's not whitespace
+		int newSize = 0;
+		int len = data.length;
+		for (int i = 0; i < len; i++) {
+			if (!isWhiteSpace(data[i])) {
+				data[newSize++] = data[i];
+			}
+		}
+		return newSize;
+	}
+
+	private static String base64hash = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+	/**
+	 * Matcher Check
+	 * 
+	 * @param inStr
+	 * @param reg
+	 * @return
+	 */
+	public static boolean isMatcher(String inStr, String reg) {
+		Pattern pattern = Pattern.compile(reg);
+		Matcher matcher = pattern.matcher(inStr);
+		if (matcher.matches()) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * btoa
+	 * 
+	 * @param inStr
+	 * @return
+	 */
+	public static String btoa(String inStr) {
+
+		// if (/([^\u0000-\u00ff])/.test(s)) {
+		// throw new Error('INVALID_CHARACTER_ERR');
+		// }
+		if (inStr == null || isMatcher(inStr, "([^\\u0000-\\u00ff])")) {
+			return null;
+		}
+
+		StringBuilder result = new StringBuilder();
+
+		int i = 0;
+		int mod = 0;
+		int ascii;
+		int prev = 0;
+		while (i < inStr.length()) {
+			ascii = inStr.charAt(i);
+			mod = i % 3;
+
+			switch (mod) {
+			case 0:
+				result.append(String.valueOf(base64hash.charAt(ascii >> 2)));
+				break;
+			case 1:
+
+				result.append(String.valueOf(base64hash.charAt((prev & 3) << 4 | (ascii >> 4))));
+				break;
+			case 2:
+				result.append(String.valueOf(base64hash.charAt((prev & 0x0f) << 2 | (ascii >> 6))));
+				result.append(String.valueOf(base64hash.charAt(ascii & 0x3f)));
+				break;
+
+			}
+
+			prev = ascii;
+			i++;
+		}
+
+		if (mod == 0) {
+			result.append(String.valueOf(base64hash.charAt((prev & 3) << 4)));
+			result.append("==");
+		} else if (mod == 1) {
+			result.append(String.valueOf(base64hash.charAt((prev & 0x0f) << 2)));
+			result.append("=");
+		}
+
+		return result.toString();
+	}
+
+	/**
+	 * atob
+	 * 
+	 * @param inStr
+	 * @return
+	 */
+	public static String atob(String inStr) {
+		if (inStr == null)
+			return null;
+		// s = s.replace(/\s|=/g, '');
+		inStr = inStr.replaceAll("\\s|=", "");
+		StringBuilder result = new StringBuilder();
+
+		int cur;
+		int prev = -1;
+		// Integer prev=null;
+		int mod;
+		int i = 0;
+
+		while (i < inStr.length()) {
+			cur = base64hash.indexOf(inStr.charAt(i));
+			mod = i % 4;
+			switch (mod) {
+			case 0:
+				break;
+			case 1:
+				result.append(String.valueOf((char) (prev << 2 | cur >> 4)));
+				break;
+			case 2:
+
+				result.append(String.valueOf((char) ((prev & 0x0f) << 4 | cur >> 2)));
+				break;
+			case 3:
+
+				result.append(String.valueOf((char) ((prev & 3) << 6 | cur)));
+				break;
+			}
+
+			prev = cur;
+			i++;
+		}
+
+		return result.toString();
+	}
+
+}

+ 7 - 6
chuanyi_server/src/main/java/com/judong/chuanyiserver/util/KeyStoreLoader.java

@@ -5,6 +5,7 @@ import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder;
 import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
 
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -13,7 +14,6 @@ import java.nio.file.Path;
 import java.security.*;
 import java.security.cert.X509Certificate;
 import java.util.regex.Pattern;
-
 public class KeyStoreLoader {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
@@ -27,13 +27,14 @@ public class KeyStoreLoader {
     private X509Certificate clientCertificate;
     // 密钥对对象
     private KeyPair clientKeyPair;
-    KeyStoreLoader load(Path baseDir) throws Exception {
+
+    public KeyStoreLoader load(Path baseDir) throws Exception {
         // 创建一个使用`PKCS12`加密标准的KeyStore。KeyStore在后面将作为读取和生成证书的对象。
         KeyStore keyStore = KeyStore.getInstance("PKCS12");
         // PKCS12的加密标准的文件后缀是.pfx,其中包含了公钥和私钥。
         // 而其他如.der等的格式只包含公钥,私钥在另外的文件中。
         Path serverKeyStore = baseDir.resolve("example-client.pfx");
-        logger.info("Loading KeyStore at {}", serverKeyStore);
+        logger.info("正在加载KeyStore: {}", serverKeyStore);
         // 如果文件不存在则创建.pfx证书文件。
         if (!Files.exists(serverKeyStore)) {
             keyStore.load(null, PASSWORD);
@@ -51,7 +52,7 @@ public class KeyStoreLoader {
                     .setApplicationUri("urn:eclipse:milo:examples:client")
                     .addDnsName("localhost")
                     .addIpAddress("127.0.0.1");
-            // Get as many hostnames and IP addresses as we can listed in the certificate.
+            // 获取证书中列出的尽可能多的主机名和IP地址。
             for (String hostname : HostnameUtil.getHostnames("0.0.0.0")) {
                 if (IP_ADDR_PATTERN.matcher(hostname).matches()) {
                     builder.addIpAddress(hostname);
@@ -86,11 +87,11 @@ public class KeyStoreLoader {
         return this;
     }
     // 返回证书
-    X509Certificate getClientCertificate() {
+    public X509Certificate getClientCertificate() {
         return clientCertificate;
     }
     // 返回密钥对
-    KeyPair getClientKeyPair() {
+    public KeyPair getClientKeyPair() {
         return clientKeyPair;
     }
 }

+ 204 - 0
chuanyi_server/src/main/java/com/judong/chuanyiserver/util/RSAUtil.java

@@ -0,0 +1,204 @@
+package com.judong.chuanyiserver.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+import javax.crypto.Cipher;
+
+public class RSAUtil {
+	
+	public static void main(String[] args) {
+		String a = "fsfdfdg汉字sfsf";
+		String b = encryptByPublic(a, PUBLIC_KEY);
+		System.out.println(b);
+		try {
+			String c = decrypt(b, "utf-8");
+			String d = decrypt("OE9zOA6Qlvwsq0fEY3/vmK7xWq6shHLVXdRLO3Dh/0W1WHDpDcT1u4AmtennAvGzP4plhHvlrjU6E66zaMFEeGKbr8ATGAxrExl0mBqgJB/IvSyzRpv35BrghgWMm3ng+IxQlCdA/0N2IxraEweUXkgyz4745zz4xExUbE0d/N4=", "utf-8");
+			System.out.println(c);
+			System.out.println(d);
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+	private static final int MAX_DECRYPT = 256;
+	private static final int MAX_DECRYPT_BLOCK = 245;
+
+	/**
+	 * @Title: decrypt
+	 * @Description: 使用私钥解密
+	 * @author: YJQ
+	 * @date: 2021年4月13日 下午9:27:31
+	 * @returnType String
+	 * @param content
+	 * @param private_key
+	 * @param input_charset
+	 * @return
+	 * @throws Exception
+	 */
+	public static String decrypt(String content, String private_key, String input_charset) throws Exception {
+		PrivateKey prikey = getPrivateKey(private_key);
+		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+		cipher.init(Cipher.DECRYPT_MODE, prikey);
+		InputStream ins = new ByteArrayInputStream(Base64Util.decode(content));
+		ByteArrayOutputStream writer = new ByteArrayOutputStream();
+		byte[] buf = new byte[MAX_DECRYPT];
+		int bufl;
+		while ((bufl = ins.read(buf)) != -1) {
+			byte[] block = null;
+			if (buf.length == bufl) {
+				block = buf;
+			} else {
+				block = new byte[bufl];
+				for (int i = 0; i < bufl; i++) {
+					block[i] = buf[i];
+				}
+			}
+			writer.write(cipher.doFinal(block));
+		}
+		return new String(writer.toByteArray(), input_charset);
+	}
+
+	/**
+	 * @Title: decrypt
+	 * @Description: 使用私钥解密
+	 * @author: YJQ
+	 * @date: 2021年4月13日 下午9:27:41
+	 * @returnType String
+	 * @param content
+	 * @param input_charset
+	 * @return
+	 * @throws Exception
+	 */
+	public static String decrypt(String content, String input_charset) throws Exception {
+		PrivateKey prikey = getPrivateKey(PRIVATE_KEY);
+		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+		cipher.init(Cipher.DECRYPT_MODE, prikey);
+		InputStream ins = new ByteArrayInputStream(Base64Util.decode(content));
+		ByteArrayOutputStream writer = new ByteArrayOutputStream();
+		byte[] buf = new byte[MAX_DECRYPT];
+		int bufl;
+		while ((bufl = ins.read(buf)) != -1) {
+			byte[] block = null;
+			if (buf.length == bufl) {
+				block = buf;
+			} else {
+				block = new byte[bufl];
+				for (int i = 0; i < bufl; i++) {
+					block[i] = buf[i];
+				}
+			}
+			writer.write(cipher.doFinal(block));
+		}
+		return new String(writer.toByteArray(), input_charset);
+	}
+
+	/**
+	 * @Title: getPrivateKey
+	 * @Description: 获得私钥
+	 * @author: YJQ
+	 * @date: 2021年4月13日 下午9:27:53
+	 * @returnType PrivateKey
+	 * @param key
+	 * @return
+	 * @throws Exception
+	 */
+	public static PrivateKey getPrivateKey(String key) throws Exception {
+		byte[] keyBytes;
+		keyBytes = Base64Util.decode(key);
+		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
+		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
+		return privateKey;
+	}
+
+	/**
+	 * @Title: getPublicKeyFromX509
+	 * @Description: 得到公钥
+	 * @author: YJQ
+	 * @date: 2021年4月13日 下午9:28:00
+	 * @returnType PublicKey
+	 * @param bysKey
+	 * @return
+	 * @throws NoSuchAlgorithmException
+	 * @throws Exception
+	 */
+	private static PublicKey getPublicKeyFromX509(String bysKey) throws NoSuchAlgorithmException, Exception {
+		byte[] decodedKey = Base64Util.decode(bysKey);
+		X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodedKey);
+		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+		return keyFactory.generatePublic(x509);
+	}
+
+	/**
+	 * @Title: encryptByPublic
+	 * @Description: 使用公钥加密
+	 * @author: YJQ
+	 * @date: 2021年4月13日 下午9:28:07
+	 * @returnType String
+	 * @param content
+	 * @param pub_key
+	 * @return
+	 */
+	public static String encryptByPublic(String content, String pub_key) {
+		try {
+			PublicKey pubkey = getPublicKeyFromX509(pub_key);
+			Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+			cipher.init(Cipher.ENCRYPT_MODE, pubkey);
+			// 分段加密
+			byte[] data = content.getBytes("UTF-8");
+			int inputLength = data.length;
+			ByteArrayOutputStream out = new ByteArrayOutputStream();
+			int offset = 0;
+			byte[] cache;
+			int i = 0;
+			while (inputLength - offset > 0) {
+				if (inputLength - offset > MAX_DECRYPT_BLOCK) {
+					cache = cipher.doFinal(data, offset, MAX_DECRYPT_BLOCK);
+				} else {
+					cache = cipher.doFinal(data, offset, inputLength - offset);
+				}
+				out.write(cache);
+				i++;
+				offset = i * MAX_DECRYPT_BLOCK;
+			}
+			byte[] decryptedData = out.toByteArray();
+			out.close();
+			return new String(Base64Util.encode(decryptedData));
+		} catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+	/* 私钥 */
+	public static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJszNAoIzCXk81ZJ\r\n"
+			+ "jmhfwWbW0HxnHSLKnekIyGgkfdgJpXtPe+ca9DSC5J4h2C6liZix0/kVnUcBa3F6\r\n"
+			+ "/H2C6222BObb5PLBqJhfrXry23tOA4PZDRhmtyzwDQHlvFLhJkaaKEp4/Wf5F2b6\r\n"
+			+ "1VJAvGGw35+YD+hHvsTvHQHxfVCbAgMBAAECgYAdNV+/27QAFbyuKp3AivTtE9Sc\r\n"
+			+ "9RMIrzVU3DBLWULN29LnCCh7cBkxoMjB8gCrlr/0mtMX97dn256K9uh5/p+r9R+j\r\n"
+			+ "30TUmLDa0fi0WNXHZ+FitYGdBhtcdaYiDsiDKIe87ItCKH/cfazgUOV9AjqaDlxp\r\n"
+			+ "x6qhsPDosA/O7JidcQJBAMvvI6YUJ2+PKPUKgWZ55JZMpSUAJXmP5OfvFb+hBmst\r\n"
+			+ "ErzVMMhoBUF7g/6NXWDz8fmDiy5s8/c4X742cIxsVScCQQDC0t4B9BTje7PZ+s5Y\r\n"
+			+ "PY1NOLR3xP+3uG89J+7JW87zXEKDHejrR7KNkjb3rWl8NJvdP+6iv1yERu6n/Hcm\r\n"
+			+ "udltAkA0ZHKvJzxeb9Qg6BsIfcZZSsWetOPr0CkJ4SWgPrlMbZ8Dvm2y/u5ivV3S\r\n"
+			+ "1vSnhOSkqsPmIH2pBOWsE4ZkvSw/AkEAjuPf5qjhhTMeZxrXqsqCT4fufQWk1FfW\r\n"
+			+ "ZpFaRp8qez1InygZxC7S25jI7gFnI6zmQHD6kq0tqurncZfuwB2BRQJAc5XbwsEj\r\n"
+			+ "lhvSnGHx2fe9c/BzaM7J575aJLtVPq3NrO3APMTwSGmK1kTiE+13041QHRVN25Ni\r\n"
+			+ "uaqJA3hsfOTwQA==";
+
+	/* 公钥 */
+	public static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbMzQKCMwl5PNWSY5oX8Fm1tB8\r\n"
+			+ "Zx0iyp3pCMhoJH3YCaV7T3vnGvQ0guSeIdgupYmYsdP5FZ1HAWtxevx9gutttgTm\r\n"
+			+ "2+TywaiYX6168tt7TgOD2Q0YZrcs8A0B5bxS4SZGmihKeP1n+Rdm+tVSQLxhsN+f\r\n"
+			+ "mA/oR77E7x0B8X1QmwIDAQAB";
+
+}

+ 53 - 48
chuanyi_server/src/main/java/com/judong/chuanyiserver/util/Test.java

@@ -1,82 +1,87 @@
 package com.judong.chuanyiserver.util;
 
+import com.judong.chuanyiserver.enums.ResultEnum;
+import com.judong.chuanyiserver.exception.CustomException;
 import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
 import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig;
 import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
-import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider;
-import org.eclipse.milo.opcua.sdk.client.nodes.UaNode;
-import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedDataItem;
-import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedSubscription;
-import org.eclipse.milo.opcua.stack.core.AttributeId;
-import org.eclipse.milo.opcua.stack.core.Identifiers;
+import org.eclipse.milo.opcua.stack.client.DiscoveryClient;
 import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
-import org.eclipse.milo.opcua.stack.core.types.builtin.*;
-import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
-import org.eclipse.milo.opcua.stack.core.types.enumerated.MonitoringMode;
-import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
+import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText;
+import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned;
 import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
-import org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemCreateRequest;
-import org.eclipse.milo.opcua.stack.core.types.structured.MonitoringParameters;
-import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
-import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
-
 public class Test {
 
     private final CompletableFuture<OpcUaClient> future = new CompletableFuture<>();
     private static Logger logger = LoggerFactory.getLogger(Test.class);
     private final static String endPointUrl = "opc.tcp://192.168.0.138:37800";
     private static AtomicInteger atomic = new AtomicInteger(1);
+    private final static String certPath = "C:/Users/Administrator/Desktop/";
 
     public static void main(String[] args) throws Exception {
-//        OpcUaClient opcUaClient = createClient();
 
-        //开启连接
-//        opcUaClient.connect().get();
     }
 
-    /**
-     * 创建OPC UA的服务连接对象
-     */
-//    private static OpcUaClient createClient() throws Exception {
-//        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
+//    private OpcUaClient createClient() throws Exception {
+//
+//        Path securityTempDir = Paths.get(certPath, "security");
+//
 //        Files.createDirectories(securityTempDir);
 //        if (!Files.exists(securityTempDir)) {
-//            throw new Exception("不能够创建安全路径: " + securityTempDir);
+//            throw new CustomException(ResultEnum.SERVER_ERROR.getRespCode(), "无法创建安全目录:" + securityTempDir);
+//        }
+//
+//        KeyStoreLoader loader = KeyStoreLoader.load(securityTempDir);
+//
+//        // 搜索OPC节点
+//        List<EndpointDescription> endpoints = null;
+//        try {
+//            endpoints = DiscoveryClient.getEndpoints(properties.getEndpointUrl()).get();
+//        } catch (Throwable e) {
+//            // try the explicit discovery endpoint as well
+//            String discoveryUrl = properties.getEndpointUrl();
+//
+//            if (!discoveryUrl.endsWith("/")) {
+//                discoveryUrl += "/";
+//            }
+//            discoveryUrl += "discovery";
+//
+//            log.info("Trying explicit discovery URL: {}", discoveryUrl);
+//            endpoints = DiscoveryClient.getEndpoints(discoveryUrl).get();
 //        }
-//        KeyStoreLoader loader = new KeyStoreLoader().load(securityTempDir);
-//        // 获取OPC UA的服务器端节点
-//        EndpointDescription[] endpoints =
-//                UaTcpStackClient.getEndpoints(endPointUrl).get();
-//        EndpointDescription endpoint = Arrays.stream(endpoints)
-//                .filter(e -> e.getEndpointUrl().equals(endPointUrl))
-//                .findFirst().orElseThrow(() -> new Exception("没有节点返回"));
-//        // 设置OPC UA的配置信息
-//        OpcUaClientConfig config =
-//                OpcUaClientConfig.builder()
-//                        .setApplicationName(LocalizedText.english("OPC UA SCREEN"))
-//                        .setApplicationUri("urn:DATA-TRANSFER:OPC UA SCREEN")
-//                        .setCertificate(loader.getClientCertificate())
-//                        .setKeyPair(loader.getClientKeyPair())
-//                        .setEndpoint(endpoint)
-//                        .setIdentityProvider(new UsernameProvider("Administrator", "123456"))
-//                        .setRequestTimeout(uint(5000))
-//                        .build();
-//        // 创建OPC UA客户端
-//        return new OpcUaClient(config);
+//
+//        EndpointDescription endpoint = endpoints.stream()
+//                .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri())).filter(endpointFilter())
+//                .findFirst().orElseThrow(() -> new Exception("no desired endpoints returned"));
+//
+//        OpcUaClientConfig config = OpcUaClientConfig.builder()
+//                .setApplicationName(LocalizedText.english("my"))
+//                .setApplicationUri("urn:Jellyleo:UnifiedAutomation:UaExpert@Jellyleo")
+//                .setCertificate(loader.getClientCertificate()).setKeyPair(loader.getClientKeyPair())
+//                .setEndpoint(endpoint)
+////				.setIdentityProvider(new UsernameProvider("jellyleo", "123456"))
+//                .setIdentityProvider(new AnonymousProvider()) // 匿名验证
+//                .setRequestTimeout(Unsigned.uint(5000)).build();
+//
+//        return OpcUaClient.create(config);
 //    }
+//
+//    public static void xxx() {
+//        OpcUaClient opcUaClient = null;
+//        if (Blank.isEmpty(opcUaClient)) {
+//            throw new CustomException(ResultEnum.SERVER_ERROR.getRespCode(), ResultEnum.SERVER_ERROR.getRespMsg());
+//        }
+//    }
+
 
 }