Commit 5bea093f authored by 以墨为白's avatar 以墨为白 🎧

优化

parent 744dd937
package com.zksy.szpt.config; package com.zksy.szpt.config;
import com.zksy.szpt.filter.SignatureVerificationFilter; import com.zksy.szpt.filter.SignatureVerificationFilter;
import com.zksy.szpt.filter.SignatureVerificationFilter1;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
@Component @Component
public class WebConfig implements WebMvcConfigurer { public class WebConfig implements WebMvcConfigurer {
...@@ -55,6 +54,7 @@ public class WebConfig implements WebMvcConfigurer { ...@@ -55,6 +54,7 @@ public class WebConfig implements WebMvcConfigurer {
* @return * @return
*/ */
@Bean @Bean
@ConditionalOnBean(name = "signatureVerificationFilter")
public FilterRegistrationBean getFilter1Registration(@Qualifier("signatureVerificationFilter") SignatureVerificationFilter signatureVerificationFilter) { public FilterRegistrationBean getFilter1Registration(@Qualifier("signatureVerificationFilter") SignatureVerificationFilter signatureVerificationFilter) {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(signatureVerificationFilter); filterRegistrationBean.setFilter(signatureVerificationFilter);
...@@ -66,4 +66,17 @@ public class WebConfig implements WebMvcConfigurer { ...@@ -66,4 +66,17 @@ public class WebConfig implements WebMvcConfigurer {
return filterRegistrationBean; return filterRegistrationBean;
} }
@Bean
@ConditionalOnBean(name = "signatureVerificationFilter1")
public FilterRegistrationBean getFilter1Registration(@Qualifier("signatureVerificationFilter1") SignatureVerificationFilter1 signatureVerificationFilter) {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(signatureVerificationFilter);
//设置过滤器名称和路径,在过滤器类写了的话,这里不用重复写
filterRegistrationBean.setName("filter");
filterRegistrationBean.addUrlPatterns("/rest/*");
//设置过滤器执行顺序,数字越小,越早进行过滤,也可设置为负数
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
} }
package com.zksy.szpt.domain;
public class CommonRequestDTO {
private String deptCode;
private String content;
private String appId;
private String nonce;
private String timestamp;
private String sign;
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getNonce() {
return nonce;
}
public void setNonce(String nonce) {
this.nonce = nonce;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getDeptCode() {
return deptCode;
}
public void setDeptCode(String deptCode) {
this.deptCode = deptCode;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
package com.zksy.szpt.filter;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* 该类用于包装HttpServletRequest,以便在读取请求体后仍可重复读取
*/
public class ReusableBodyRequestWrapper1 extends HttpServletRequestWrapper {
//参数字节数组,用于存储请求体的字节数据
private byte[] requestBody;
/**
* 构造函数,初始化包装类
* @param request 原始HttpServletRequest对象
* @throws IOException 如果读取请求体时发生IO错误
*/
public ReusableBodyRequestWrapper1(HttpServletRequest request, String body) throws IOException {
super(request);
this.requestBody = body.getBytes(StandardCharsets.UTF_8);
}
// 构造方法:从请求中读取 body 并缓存
public ReusableBodyRequestWrapper1(HttpServletRequest request) throws IOException {
super(request);
this.requestBody = request.getReader().lines()
.reduce("", (accumulator, actual) -> accumulator + actual)
.getBytes(StandardCharsets.UTF_8);
}
/**
* 重写getInputStream方法,实现请求体的重复读取
* @return 包含请求体数据的ServletInputStream对象
* @throws IOException 如果读取请求体时发生IO错误
*/
@Override
public ServletInputStream getInputStream() throws IOException {
//创建一个 ByteArrayInputStream 对象,用于重复读取requestBody
final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);
return new ServletInputStream() {
@Override
public boolean isFinished() {
//始终返回false,表示数据流未完成
return false;
}
@Override
public boolean isReady() {
//始终返回false,表示数据流未准备好
return false;
}
@Override
public void setReadListener(ReadListener listener) {
//不执行任何操作,因为该数据流不支持异步操作
}
@Override
public int read() {
//从ByteArrayInputStream中读取数据
return bais.read();
}
};
}
/**
* 重写getReader方法,返回一个基于getInputStream的BufferedReader
* @return 包含请求体数据的BufferedReader对象
* @throws IOException 如果读取请求体时发生IO错误
*/
@Override
public BufferedReader getReader() throws IOException {
//基于getInputStream创建BufferedReader
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
// 获取请求体的字符串
public String getBody() {
return new String(requestBody, StandardCharsets.UTF_8);
}
}
\ No newline at end of file
...@@ -33,6 +33,9 @@ import java.nio.charset.StandardCharsets; ...@@ -33,6 +33,9 @@ import java.nio.charset.StandardCharsets;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* body {单位, 房间, 人员信息数组} 请求头加nonce timestamp appId sign(body[遍历按照key按照顺序&拼接] 加 nonece timestamp appId 用$符号拼接)
*/
@Component @Component
public class SignatureVerificationFilter extends OncePerRequestFilter { public class SignatureVerificationFilter extends OncePerRequestFilter {
......
package com.zksy.szpt.filter;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zksy.szpt.domain.CommonRequestDTO;
import com.zksy.szpt.domain.CurrentUserInfo;
import com.zksy.szpt.domain.HttpResult;
import com.zksy.szpt.domain.HttpResultState;
import com.zksy.szpt.domain.po.AppStore;
import com.zksy.szpt.service.AppStoreService;
import com.zksy.szpt.util.EncryptUtil;
import com.zksy.szpt.util.RedisKeyValidator;
import com.zksy.szpt.util.SignatureUtil;
import com.zksy.szpt.util.UserContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 请求body { appkey , method , hotelCode , content(根据密钥[md5]对dto的json加密aes), sign(前面的参数一起哈希运算)} 。 无其他参数
* 数据获取到json解密后转发到对应的controller
*/
//@Component(value = "signatureVerificationFilter1")
public class SignatureVerificationFilter1 extends OncePerRequestFilter {
public Logger logger = LoggerFactory.getLogger(SignatureVerificationFilter1.class);
@Resource
ObjectMapper objectMapper;
AppStore appStore;
@Resource
private RedisTemplate<String, Object> redisTemplate;
private final AppStoreService appStoreService;
public SignatureVerificationFilter1(AppStoreService appStoreService) {
this.appStoreService = appStoreService;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 对request进行包装,支持重复读取body
ReusableBodyRequestWrapper1 requestWrapper = new ReusableBodyRequestWrapper1(request);
String body = requestWrapper.getBody();
String result = this.verifySignature(body);
// 校验签名
if (result != null) {
this.write(response, result);
} else {
CommonRequestDTO commonRequestDTO = objectMapper.readValue(body, CommonRequestDTO.class);
String content = EncryptUtil.getInstance().AESDecode(commonRequestDTO.getContent(), appStore.getAppSecret());
ReusableBodyRequestWrapper1 requestWrapper1 = new ReusableBodyRequestWrapper1(request, content);
addUserInfo(requestWrapper1);
filterChain.doFilter(requestWrapper1, response);
}
}
/**
* 校验签名
*
* @return 签名验证结果
* @throws IOException 如果读取请求体失败
*/
public String verifySignature(String body) throws IOException {
// post请求body
CommonRequestDTO commonRequestDTO = objectMapper.readValue(body, CommonRequestDTO.class);
// 签名
String appId = commonRequestDTO.getAppId();
// 签名
String sign = commonRequestDTO.getSign();
// 随机数
String nonce = commonRequestDTO.getNonce();
// 时间戳
String timestampStr = commonRequestDTO.getTimestamp();
String deptCode = commonRequestDTO.getDeptCode();
if (!StringUtils.hasText(appId) || !StringUtils.hasText(sign) || !StringUtils.hasText(nonce) || !StringUtils.hasText(timestampStr)) {
logger.warn("缺少参数appId:{},sign:{},nonce{},timestampStr:{}", appId, sign, nonce, timestampStr);
return "请求缺少参数,appId:" + appId + ",sign:" + sign + ",nonce:" + nonce + ",timestamp:" + timestampStr;
}
// 验证nonce和timestamp合法性
if (!RedisKeyValidator.isValidString(nonce)) {
return "不是合法的由数字和字母以及下划线组成的nonce:" + nonce;
}
if (!RedisKeyValidator.isValidTimestamp(timestampStr)) {
return "不是合法的十位秒级时间戳timestamp:" + timestampStr;
}
// timestamp 10分钟内有效
long timestamp = Long.parseLong(timestampStr);
long currentTimestamp = System.currentTimeMillis() / 1000;
if (Math.abs(currentTimestamp - timestamp) > 600) {
return "请求已过期";
}
// 防止请求重放,nonce只能用一次,放在redis中,有效期 20分钟
String nonceKey = "api_signature:nonce:" + nonce;
if (Boolean.FALSE.equals(this.redisTemplate.opsForValue().setIfAbsent(nonceKey, "1", 20, TimeUnit.MINUTES))) {
return "nonce无效:" + nonce;
}
// 校验appId
appStore = this.appStoreService.getAppSecretInfo(appId);
String appSecret = appStore.getAppSecret();
if (!StringUtils.hasText(appSecret)) {
return "appId无效:" + appId;
}
//验证单位
if (deptCode != null && !deptCode.startsWith(appStore.getDeptCode().replaceAll("0+$", ""))) {
return "AppId和传入的单位不匹配,appId:" + appId + ",deptCode:" + deptCode;
}
String data = String.format("%s%s%s%s%s", appId, nonce, timestampStr, commonRequestDTO.getContent(), deptCode);
String generatedSignature = DigestUtil.md5Hex(data);
if (!generatedSignature.equals(sign)) {
logger.warn("签名有误,generatedSignature:{},sign:{},appId:{},nonce:{},timestampStr:{},deptCode:{}", generatedSignature, sign, appId, nonce, timestampStr, deptCode);
return "签名有误,sign: " + sign + ",appId:" + appId + ",nonce:" + nonce + ",timestamp:" + timestampStr + ",deptCode:" + deptCode;
}
// 签名验证通过
return null;
}
/**
* 向客户端写入响应信息
*
* @param response HTTP响应
* @param msg 响应信息
* @throws IOException 如果写入失败
*/
private void write(HttpServletResponse response, String msg) throws IOException {
HttpResultState httpResultState = HttpResultState.INVALID_SIGNATURE;
httpResultState.setMessage(msg);
HttpResult<String> httpResult = new HttpResult<>(httpResultState);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.getWriter().write(JSONUtil.toJsonStr(httpResult));
}
/**
* 增加用户信息
*
* @param request
*/
private void addUserInfo(HttpServletRequest request) {
// 增加用户信息
String userId = request.getHeader(SignatureUtil.APPID);
String ip = request.getRemoteAddr();
CurrentUserInfo currentUserInfo = new CurrentUserInfo.CurrentUserInfoBuilder().userId(userId).userName(userId).ip(ip).build();
UserContextHolder.set(currentUserInfo);
}
private String getRequestBody(HttpServletRequest request) throws IOException {
try (BufferedReader reader = request.getReader()) {
return reader.lines().collect(Collectors.joining(System.lineSeparator()));
}
}
}
package com.zksy.szpt.filter;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zksy.szpt.domain.CommonRequestDTO;
import com.zksy.szpt.domain.CurrentUserInfo;
import com.zksy.szpt.domain.HttpResult;
import com.zksy.szpt.domain.HttpResultState;
import com.zksy.szpt.domain.po.AppStore;
import com.zksy.szpt.service.AppStoreService;
import com.zksy.szpt.util.EncryptUtil;
import com.zksy.szpt.util.RedisKeyValidator;
import com.zksy.szpt.util.SignatureUtil;
import com.zksy.szpt.util.UserContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 请求body { appkey , method , hotelCode , content(根据密钥[md5]对dto的json加密aes), sign(前面的参数一起哈希运算)} 。 无其他参数
* 请求数据直接转发到后端服务
*/
//@Component(value = "signatureVerificationFilter1")
public class SignatureVerificationFilter2 extends OncePerRequestFilter {
public Logger logger = LoggerFactory.getLogger(SignatureVerificationFilter2.class);
@Resource
ObjectMapper objectMapper;
AppStore appStore;
@Resource
private RedisTemplate<String, Object> redisTemplate;
private final AppStoreService appStoreService;
public SignatureVerificationFilter2(AppStoreService appStoreService) {
this.appStoreService = appStoreService;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 对request进行包装,支持重复读取body
ReusableBodyRequestWrapper1 requestWrapper = new ReusableBodyRequestWrapper1(request);
String body = requestWrapper.getBody();
String result = this.verifySignature(body);
// 校验签名
if (result != null) {
this.write(response, result);
} else {
filterChain.doFilter(requestWrapper, response);
}
}
/**
* 校验签名
*
* @return 签名验证结果
* @throws IOException 如果读取请求体失败
*/
public String verifySignature(String body) throws IOException {
// post请求body
CommonRequestDTO commonRequestDTO = objectMapper.readValue(body, CommonRequestDTO.class);
// 签名
String appId = commonRequestDTO.getAppId();
// 签名
String sign = commonRequestDTO.getSign();
// 随机数
String nonce = commonRequestDTO.getNonce();
// 时间戳
String timestampStr = commonRequestDTO.getTimestamp();
String deptCode = commonRequestDTO.getDeptCode();
if (!StringUtils.hasText(appId) || !StringUtils.hasText(sign) || !StringUtils.hasText(nonce) || !StringUtils.hasText(timestampStr)) {
logger.warn("缺少参数appId:{},sign:{},nonce{},timestampStr:{}", appId, sign, nonce, timestampStr);
return "请求缺少参数,appId:" + appId + ",sign:" + sign + ",nonce:" + nonce + ",timestamp:" + timestampStr;
}
// 验证nonce和timestamp合法性
if (!RedisKeyValidator.isValidString(nonce)) {
return "不是合法的由数字和字母以及下划线组成的nonce:" + nonce;
}
if (!RedisKeyValidator.isValidTimestamp(timestampStr)) {
return "不是合法的十位秒级时间戳timestamp:" + timestampStr;
}
// timestamp 10分钟内有效
long timestamp = Long.parseLong(timestampStr);
long currentTimestamp = System.currentTimeMillis() / 1000;
if (Math.abs(currentTimestamp - timestamp) > 600) {
return "请求已过期";
}
// 防止请求重放,nonce只能用一次,放在redis中,有效期 20分钟
String nonceKey = "api_signature:nonce:" + nonce;
if (Boolean.FALSE.equals(this.redisTemplate.opsForValue().setIfAbsent(nonceKey, "1", 20, TimeUnit.MINUTES))) {
return "nonce无效:" + nonce;
}
// 校验appId
appStore = this.appStoreService.getAppSecretInfo(appId);
String appSecret = appStore.getAppSecret();
if (!StringUtils.hasText(appSecret)) {
return "appId无效:" + appId;
}
//验证单位
if (deptCode != null && !deptCode.startsWith(appStore.getDeptCode().replaceAll("0+$", ""))) {
return "AppId和传入的单位不匹配,appId:" + appId + ",deptCode:" + deptCode;
}
String data = String.format("%s%s%s%s%s", appId, nonce, timestampStr, commonRequestDTO.getContent(), deptCode);
String generatedSignature = DigestUtil.md5Hex(data);
if (!generatedSignature.equals(sign)) {
logger.warn("签名有误,generatedSignature:{},sign:{},appId:{},nonce:{},timestampStr:{},deptCode:{}", generatedSignature, sign, appId, nonce, timestampStr, deptCode);
return "签名有误,sign: " + sign + ",appId:" + appId + ",nonce:" + nonce + ",timestamp:" + timestampStr + ",deptCode:" + deptCode;
}
// 签名验证通过
return null;
}
/**
* 向客户端写入响应信息
*
* @param response HTTP响应
* @param msg 响应信息
* @throws IOException 如果写入失败
*/
private void write(HttpServletResponse response, String msg) throws IOException {
HttpResultState httpResultState = HttpResultState.INVALID_SIGNATURE;
httpResultState.setMessage(msg);
HttpResult<String> httpResult = new HttpResult<>(httpResultState);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.getWriter().write(JSONUtil.toJsonStr(httpResult));
}
}
...@@ -151,7 +151,7 @@ public class EncryptUtil { ...@@ -151,7 +151,7 @@ public class EncryptUtil {
* @param res 需要解密的密文 * @param res 需要解密的密文
* @param key 秘钥 * @param key 秘钥
*/ */
private String AESDecode(String res, String key) { public String AESDecode(String res, String key) {
return keyGeneratorES(res, AES, key, keySizeAES, false); return keyGeneratorES(res, AES, key, keySizeAES, false);
} }
......
package com.zksy.szpt;
public class CommonUtil {
}
...@@ -3,6 +3,7 @@ package com.zksy.szpt; ...@@ -3,6 +3,7 @@ package com.zksy.szpt;
import cn.hutool.crypto.digest.DigestUtil; import cn.hutool.crypto.digest.DigestUtil;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.zksy.szpt.domain.CommonRequestDTO;
import com.zksy.szpt.domain.dto.*; import com.zksy.szpt.domain.dto.*;
import com.zksy.szpt.util.EncryptUtil; import com.zksy.szpt.util.EncryptUtil;
import com.zksy.szpt.util.SignatureUtil; import com.zksy.szpt.util.SignatureUtil;
...@@ -38,7 +39,7 @@ public class TestAppStore { ...@@ -38,7 +39,7 @@ public class TestAppStore {
Assertions.assertNotNull(appId, "appId不存在");//断言appId存在,为空直接抛出异常不进行下一步测试,提高测试效率 Assertions.assertNotNull(appId, "appId不存在");//断言appId存在,为空直接抛出异常不进行下一步测试,提高测试效率
//请求参数 //请求参数
AppStoreDTO appStoreDTO = new AppStoreDTO(); AppStoreDTO appStoreDTO = new AppStoreDTO();
appStoreDTO.setAppKey("us"); appStoreDTO.setAppKey("us2");
appStoreDTO.setAppSecret(DigestUtil.md5Hex("us")); appStoreDTO.setAppSecret(DigestUtil.md5Hex("us"));
appStoreDTO.setDeptCode("123456"); appStoreDTO.setDeptCode("123456");
String json = null; String json = null;
...@@ -62,7 +63,7 @@ public class TestAppStore { ...@@ -62,7 +63,7 @@ public class TestAppStore {
.header(SignatureUtil.NONCE, nonce) .header(SignatureUtil.NONCE, nonce)
.header(SignatureUtil.TIMESTAMP, timestampStr) .header(SignatureUtil.TIMESTAMP, timestampStr)
.header(SignatureUtil.SIGNATURE, generatedSignature) .header(SignatureUtil.SIGNATURE, generatedSignature)
.body(Mono.just(appStoreDTO), XxRwwcqkDTO.class) .body(Mono.just(appStoreDTO), AppStoreDTO.class)
.retrieve() .retrieve()
.bodyToMono(String.class) .bodyToMono(String.class)
.block(); .block();
...@@ -107,4 +108,53 @@ public class TestAppStore { ...@@ -107,4 +108,53 @@ public class TestAppStore {
.block(); .block();
System.out.println(response); System.out.println(response);
} }
/**
* 新增AppId
*/
@Test
@DisplayName("新增AppId1")
public void addAppId1() {
String deptCode = "330102";
timestampStr = String.valueOf(System.currentTimeMillis() / 1000);
nonce = String.valueOf(System.currentTimeMillis() / 1000);
appSecret = DigestUtil.md5Hex(appSecret);
Assertions.assertNotNull(appId, "appId不存在");//断言appId存在,为空直接抛出异常不进行下一步测试,提高测试效率
//请求参数
AppStoreDTO appStoreDTO = new AppStoreDTO();
appStoreDTO.setAppKey("us2");
appStoreDTO.setAppSecret(DigestUtil.md5Hex("us"));
appStoreDTO.setDeptCode(deptCode);
String json = null;
try {
json = objectMapper.writeValueAsString(appStoreDTO);
} catch (JsonProcessingException e) {
Assertions.fail("json序列化失败");
}
//请求体加密
json = EncryptUtil.getInstance().AESEncode(json, appSecret);
//签名appId+nonce+timestampStr+aes(body)+deptCode
String data = String.format("%s%s%s%s%s", appId, nonce, timestampStr, json, deptCode);
String generatedSignature = DigestUtil.md5Hex(data);
CommonRequestDTO commonRequestDTO = new CommonRequestDTO();
commonRequestDTO.setAppId(appId);
commonRequestDTO.setNonce(nonce);
commonRequestDTO.setTimestamp(timestampStr);
commonRequestDTO.setDeptCode(deptCode);
commonRequestDTO.setContent(json);
commonRequestDTO.setSign(generatedSignature);
//请求
WebClient webClient = WebClient.builder()
.baseUrl("http://localhost:8086")
.defaultHeader("Content-Type", "application/json")
.build();
String response = webClient.post().uri("/rest/appStore/insertAppStore")
.body(Mono.just(commonRequestDTO), CommonRequestDTO.class)
.retrieve()
.bodyToMono(String.class)
.block();
System.out.println(response);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment