diff --git a/pom.xml b/pom.xml index 14a460f6..c8c22e27 100644 --- a/pom.xml +++ b/pom.xml @@ -368,6 +368,13 @@ redisson 3.6.0 + + + + org.bouncycastle + bcprov-jdk15on + 1.69 + diff --git a/src/main/java/com/glxp/api/aspect/BodyRequestWrapper.java b/src/main/java/com/glxp/api/aspect/BodyRequestWrapper.java new file mode 100644 index 00000000..c1e064bb --- /dev/null +++ b/src/main/java/com/glxp/api/aspect/BodyRequestWrapper.java @@ -0,0 +1,66 @@ +package com.glxp.api.aspect; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * 用来重新封装request + */ +public class BodyRequestWrapper extends HttpServletRequestWrapper { + + /** + * 存放JSON数据主体 + */ + private String body; + + public BodyRequestWrapper(HttpServletRequest request, String context) { + super(request); + body = context; + } + + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes("UTF-8")); + return new ServletInputStream() { + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener listener) { + + } + }; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(this.getInputStream())); + } +} diff --git a/src/main/java/com/glxp/api/aspect/RequestHandler.java b/src/main/java/com/glxp/api/aspect/RequestHandler.java new file mode 100644 index 00000000..b2d68b7a --- /dev/null +++ b/src/main/java/com/glxp/api/aspect/RequestHandler.java @@ -0,0 +1,53 @@ +package com.glxp.api.aspect; + +import com.alibaba.fastjson.JSON; +import com.glxp.api.util.Sm2Util; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + + +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * 请求加解密过滤器 + */ +@Slf4j +@Component +public class RequestHandler implements Filter { + /** + * 进行请求加密 + */ + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + // form-data不校验 + if ("application/x-www-form-urlencoded".equals(request.getContentType())) { + chain.doFilter(request, response); + return; + } + + // 拿到加密串 + String data = new RequestWrapper((HttpServletRequest) request).getBody(); + if (StringUtils.isEmpty(data)) { + chain.doFilter(request, response); + return; + } + + // 解析 + String body = Sm2Util.decrypt("00e36cfc8d61175584333e6160c645700f2a4659f5908c1bed5824423eab1a1626", JSON.parseObject(data).getString("data")); + log.info(body); + request = new BodyRequestWrapper((HttpServletRequest) request, body); + chain.doFilter(request, response); + } +} diff --git a/src/main/java/com/glxp/api/aspect/RequestWrapper.java b/src/main/java/com/glxp/api/aspect/RequestWrapper.java new file mode 100644 index 00000000..a4320003 --- /dev/null +++ b/src/main/java/com/glxp/api/aspect/RequestWrapper.java @@ -0,0 +1,95 @@ +package com.glxp.api.aspect; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.*; + + +/** + * 用来读取body + */ +public class RequestWrapper extends HttpServletRequestWrapper { + private final String body; + + public RequestWrapper(HttpServletRequest request) { + super(request); + StringBuilder stringBuilder = new StringBuilder(); + BufferedReader bufferedReader = null; + InputStream inputStream = null; + try { + inputStream = request.getInputStream(); + if (inputStream != null) { + bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + char[] charBuffer = new char[128]; + int bytesRead = -1; + while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { + stringBuilder.append(charBuffer, 0, bytesRead); + } + } else { + stringBuilder.append(""); + } + } catch (IOException ex) { + + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + body = stringBuilder.toString(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); + ServletInputStream servletInputStream = new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + } + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + return servletInputStream; + + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(this.getInputStream())); + } + + public String getBody() { + return this.body; + } +} diff --git a/src/main/java/com/glxp/api/controller/auth/LoginController.java b/src/main/java/com/glxp/api/controller/auth/LoginController.java index 77f65455..505be2ca 100644 --- a/src/main/java/com/glxp/api/controller/auth/LoginController.java +++ b/src/main/java/com/glxp/api/controller/auth/LoginController.java @@ -126,7 +126,7 @@ public class LoginController extends BaseController { Map claims = new HashMap<>(); claims.put("admin_id", authAdmin.getId()); - String token = JwtUtils.createToken(claims, 86400L); // 一天后过期 + String token = JwtUtils.createToken(claims, 1800L); // 一天后过期 Map map = new HashMap<>(); map.put("id", authAdmin.getId()); diff --git a/src/main/java/com/glxp/api/controller/sync/TestController.java b/src/main/java/com/glxp/api/controller/sync/TestController.java index 15c07b87..be259d9e 100644 --- a/src/main/java/com/glxp/api/controller/sync/TestController.java +++ b/src/main/java/com/glxp/api/controller/sync/TestController.java @@ -11,12 +11,10 @@ import com.glxp.api.constant.SocketMsgType; import com.glxp.api.entity.sync.SocketMsgEntity; import com.glxp.api.idc.utils.IDCUtils; import com.glxp.api.res.inout.IoCodeResponse; +import com.glxp.api.util.Sm2Util; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; @@ -67,4 +65,11 @@ public class TestController { return ResultVOUtils.success(socketMsgEntity); } + + @PostMapping("/sm2") + public BaseResponse sm2(@RequestParam String data) { + + return ResultVOUtils.success(Sm2Util.decrypt("00e36cfc8d61175584333e6160c645700f2a4659f5908c1bed5824423eab1a1626", data)); + } + } diff --git a/src/main/java/com/glxp/api/util/Sm2Util.java b/src/main/java/com/glxp/api/util/Sm2Util.java new file mode 100644 index 00000000..63ee8b87 --- /dev/null +++ b/src/main/java/com/glxp/api/util/Sm2Util.java @@ -0,0 +1,80 @@ +package com.glxp.api.util; + +import cn.hutool.core.util.HexUtil; +import cn.hutool.crypto.BCUtil; +import cn.hutool.crypto.SmUtil; +import cn.hutool.crypto.asymmetric.KeyType; +import cn.hutool.crypto.asymmetric.SM2; + +import java.util.HashMap; +import java.util.Map; + +/** + * 加解密工具类 + */ +import com.glxp.api.annotation.Log; +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.crypto.engines.SM2Engine; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; + + +/** + * @author 猴哥 + */ +@Slf4j +public class Sm2Util { + /** + * 生成秘钥对 + * + * @return 公钥和私钥 + */ + public static Map generator() { + SM2 sm2 = SmUtil.sm2(); + String publicKey = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false)).toUpperCase(); + String privateKey = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey())).toUpperCase(); + return new HashMap(2) {{ + put("publicKey", publicKey); + put("privateKey", privateKey); + }}; + } + + /** + * 加密 + * + * @param publicKey 公钥 + * @param data 明文 + * @return 密文 + */ + public static String encrypt(String publicKey, String data) { + return SmUtil.sm2(null, publicKey) + // 不写默认就是C1C3C2 + .setMode(SM2Engine.Mode.C1C3C2) + .encryptHex(data.getBytes(), KeyType.PublicKey) + // 加密后,密文前面会有04,需要去掉 + .substring(2); + } + + /** + * 解密 + * + * @param privateKey 私钥 + * @param data 密文 + * @return 明文 + */ + public static String decrypt(String privateKey, String data) { + // 确定前端不会加04,所以后端直接加(上面处理方式可能造成报错(Invalid point coordinates):原因前端加密后密文自带04开头) + data = "04" + data; + return SmUtil.sm2(privateKey, null) + // 不写默认就是C1C3C2 + .setMode(SM2Engine.Mode.C1C3C2) + .decryptStr(data, KeyType.PrivateKey); + } + + public static void main(String[] agrs) { + SM2 sm2 = SmUtil.sm2(); + String privateKey = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey())); + String publicKey = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false)); + log.info(privateKey); + log.info(publicKey); + } +}