add 新增 请求加密传输 合并优化 !pr377

This commit is contained in:
疯狂的狮子Li
2023-07-10 18:20:05 +08:00
parent 10b5b0e82a
commit af08632c37
19 changed files with 98 additions and 402 deletions

View File

@ -0,0 +1,32 @@
package org.dromara.common.encrypt.config;
import jakarta.servlet.DispatcherType;
import org.dromara.common.encrypt.filter.CryptoFilter;
import org.dromara.common.encrypt.properties.ApiDecryptProperties;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
/**
* api 解密自动配置
*
* @author wdhcr
*/
@AutoConfiguration
@EnableConfigurationProperties(ApiDecryptProperties.class)
@ConditionalOnProperty(value = "api-decrypt.enabled", havingValue = "true")
public class ApiDecryptAutoConfiguration {
@Bean
public FilterRegistrationBean<CryptoFilter> cryptoFilterRegistration(ApiDecryptProperties properties) {
FilterRegistrationBean<CryptoFilter> registration = new FilterRegistrationBean<>();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new CryptoFilter(properties));
registration.addUrlPatterns("/*");
registration.setName("cryptoFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
return registration;
}
}

View File

@ -0,0 +1,48 @@
package org.dromara.common.encrypt.filter;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.encrypt.properties.ApiDecryptProperties;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import java.io.IOException;
import java.util.Objects;
/**
* Crypto 过滤器
*
* @author wdhcr
*/
public class CryptoFilter implements Filter {
private final ApiDecryptProperties properties;
public CryptoFilter(ApiDecryptProperties properties) {
this.properties = properties;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
HttpServletRequest servletRequest = (HttpServletRequest) request;
// 是否为 json 请求
if (StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
// 是否为 put 或者 post 请求
if (HttpMethod.PUT.matches(servletRequest.getMethod()) || HttpMethod.POST.matches(servletRequest.getMethod())) {
// 是否存在加密标头
String headerValue = servletRequest.getHeader(properties.getHeaderFlag());
if (StringUtils.isNotBlank(headerValue)) {
requestWrapper = new DecryptRequestBodyWrapper(servletRequest, properties.getPublicKey(), properties.getPrivateKey(), properties.getHeaderFlag());
}
}
}
chain.doFilter(Objects.requireNonNullElse(requestWrapper, request), response);
}
@Override
public void destroy() {
}
}

View File

@ -0,0 +1,94 @@
package org.dromara.common.encrypt.filter;
import cn.hutool.core.io.IoUtil;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.encrypt.utils.EncryptUtils;
import org.springframework.http.MediaType;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
/**
* 解密请求参数工具类
*
* @author wdhcr
*/
public class DecryptRequestBodyWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public DecryptRequestBodyWrapper(HttpServletRequest request, String publicKey, String privateKey, String headerFlag) throws IOException {
super(request);
// 获取 AES 密码 采用 RSA 加密
String headerRsa = request.getHeader(headerFlag);
String decryptAes = EncryptUtils.decryptByRsa(headerRsa, privateKey);
// 解密 AES 密码
String aesPassword = EncryptUtils.decryptByBase64(decryptAes);
request.setCharacterEncoding(Constants.UTF8);
byte[] readBytes = IoUtil.readBytes(request.getInputStream(), false);
String requestBody = new String(readBytes, StandardCharsets.UTF_8);
// 解密 body 采用 AES 加密
String decryptBody = EncryptUtils.decryptByAes(requestBody, aesPassword);
body = decryptBody.getBytes(StandardCharsets.UTF_8);
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public int getContentLength() {
return body.length;
}
@Override
public long getContentLengthLong() {
return body.length;
}
@Override
public String getContentType() {
return MediaType.APPLICATION_JSON_VALUE;
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() {
return bais.read();
}
@Override
public int available() {
return body.length;
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}

View File

@ -0,0 +1,34 @@
package org.dromara.common.encrypt.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* api解密属性配置类
* @author wdhcr
*/
@Data
@ConfigurationProperties(prefix = "api-decrypt")
public class ApiDecryptProperties {
/**
* 加密开关
*/
private Boolean enabled;
/**
* 头部标识
*/
private String headerFlag;
/**
* 公钥
*/
private String publicKey;
/**
* 私钥
*/
private String privateKey;
}

View File

@ -1 +1,3 @@
org.dromara.common.encrypt.config.EncryptorAutoConfiguration
org.dromara.common.encrypt.config.ApiDecryptAutoConfiguration