后端代码提交
This commit is contained in:
parent
eccfdc99e8
commit
6f67f1b6e9
|
|
@ -16,7 +16,7 @@ public class BonusApplication
|
|||
{
|
||||
// System.setProperty("spring.devtools.restart.enabled", "false");
|
||||
SpringApplication.run(BonusApplication.class, args);
|
||||
System.out.println("(♥◠‿◠)ノ゙ 智慧图档启动成功 ლ(´ڡ`ლ)゙ \n" +
|
||||
System.out.println("(♥◠‿◠)ノ゙ 工程档案资料移交启动成功 ლ(´ڡ`ლ)゙ \n" +
|
||||
" .-------. ____ __ \n" +
|
||||
" | _ _ \\ \\ \\ / / \n" +
|
||||
" | ( ' ) | \\ _. / ' \n" +
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ public class SwaggerConfig
|
|||
// 用ApiInfoBuilder进行定制
|
||||
return new ApiInfoBuilder()
|
||||
// 设置标题
|
||||
.title("标题:若依管理系统_接口文档")
|
||||
.title("标题:管理系统_接口文档")
|
||||
// 描述
|
||||
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
|
||||
// 作者信息
|
||||
|
|
|
|||
|
|
@ -119,6 +119,28 @@
|
|||
<artifactId>javax.servlet-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.22</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-rsa</artifactId>
|
||||
<version>1.0.10.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.bonus.common.exception;
|
||||
|
||||
/**
|
||||
* 验证码错误异常类
|
||||
*
|
||||
* @author bonus
|
||||
*/
|
||||
public class CaptchaException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public CaptchaException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,332 @@
|
|||
package com.bonus.common.filter;
|
||||
|
||||
import com.bonus.common.exception.CaptchaException;
|
||||
import com.bonus.common.utils.encryption.Sm3Util;
|
||||
import com.bonus.common.utils.encryption.Sm4Utils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import javax.servlet.*;
|
||||
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 java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 请求内容存储 处理请求内容 内容放在gatewayContext中
|
||||
* 解决数据流被重复读取无数据的 问题
|
||||
* 对formData 数据进行解密
|
||||
*
|
||||
* @author bonus
|
||||
*/
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RequestCoverFilter implements Filter {
|
||||
|
||||
/**
|
||||
* 数据加密标志
|
||||
*/
|
||||
public static final String ENCRYPT = "encryptRequest";
|
||||
/**
|
||||
* 数据完整性校验标志
|
||||
*/
|
||||
public static final String INTEGRALITY = "checkIntegrity";
|
||||
/**
|
||||
* 完整性校验哈希值
|
||||
*/
|
||||
public static final String HMAC_HEADER_NAME = "Params-Hash";
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
// 初始化逻辑
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
// 获取请求头信息
|
||||
boolean integrality = "true".equalsIgnoreCase(httpRequest.getHeader(INTEGRALITY));
|
||||
boolean encrypt = "true".equalsIgnoreCase(httpRequest.getHeader(ENCRYPT));
|
||||
|
||||
String contentType = httpRequest.getContentType();
|
||||
|
||||
// 处理不同类型的请求
|
||||
if (contentType == null) {
|
||||
log.info("请求头中无Content-Type信息,处理URL参数。");
|
||||
handleUrlParams(httpRequest, response, chain, integrality, encrypt);
|
||||
} else if (contentType.contains(MediaType.APPLICATION_JSON_VALUE)) {
|
||||
handleBodyRequest(httpRequest, response, chain, integrality, encrypt);
|
||||
} else {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// 清理逻辑
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理请求体里的参数
|
||||
*/
|
||||
private void handleBodyRequest(HttpServletRequest request, ServletResponse response,
|
||||
FilterChain chain, boolean integrality, boolean encrypt)
|
||||
throws IOException, ServletException {
|
||||
|
||||
// 读取请求体内容
|
||||
String requestBody = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8);
|
||||
|
||||
if (ObjectUtils.isEmpty(requestBody)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// 去掉多余的引号(如果有)
|
||||
if (requestBody.startsWith("\"") && requestBody.endsWith("\"")) {
|
||||
requestBody = requestBody.substring(1, requestBody.length() - 1);
|
||||
}
|
||||
|
||||
try {
|
||||
// 解密请求体
|
||||
if (encrypt) {
|
||||
requestBody = Sm4Utils.decrypt(requestBody);
|
||||
}
|
||||
|
||||
if (ObjectUtils.isEmpty(requestBody)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// 校验数据完整性
|
||||
if (integrality) {
|
||||
String[] parts = requestBody.split("\\|");
|
||||
if (parts.length != 2) {
|
||||
log.error("解密后的请求体格式不正确: {}", requestBody);
|
||||
throw new CaptchaException("请求参数不正确");
|
||||
}
|
||||
integrityVerification(parts[1], parts[0]);
|
||||
requestBody = parts[0];
|
||||
}
|
||||
|
||||
if (ObjectUtils.isEmpty(requestBody)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建包装的请求对象
|
||||
HttpServletRequest wrappedRequest = new BodyCachingRequestWrapper(request, requestBody);
|
||||
chain.doFilter(wrappedRequest, response);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("处理请求体时发生错误: {}", e.getMessage(), e);
|
||||
throw new ServletException("请求处理失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理URL参数
|
||||
*/
|
||||
private void handleUrlParams(HttpServletRequest request, ServletResponse response,
|
||||
FilterChain chain, boolean integrality, boolean encrypt)
|
||||
throws IOException, ServletException {
|
||||
|
||||
try {
|
||||
HttpServletRequest updatedRequest = updateRequestParam(request, integrality, encrypt);
|
||||
chain.doFilter(updatedRequest != null ? updatedRequest : request, response);
|
||||
} catch (Exception e) {
|
||||
log.error("处理 GET 请求时发生错误: {}", e.getMessage(), e);
|
||||
throw new ServletException("请求处理失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新查询参数,解密和验证数据完整性
|
||||
*/
|
||||
private HttpServletRequest updateRequestParam(HttpServletRequest request,
|
||||
boolean integrality, boolean encrypt) {
|
||||
|
||||
String queryString = request.getQueryString();
|
||||
if (!ObjectUtils.isEmpty(queryString)) {
|
||||
try {
|
||||
// 解析 params 参数
|
||||
String encryptedParams = null;
|
||||
String[] queryParams = queryString.split("&");
|
||||
for (String param : queryParams) {
|
||||
if (param.startsWith("params=")) {
|
||||
encryptedParams = param.substring(7); // 去掉 "params="
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (encryptedParams == null) {
|
||||
log.warn("未找到加密参数,跳过解密处理");
|
||||
return null;
|
||||
}
|
||||
|
||||
// URL解码
|
||||
encryptedParams = java.net.URLDecoder.decode(encryptedParams, StandardCharsets.UTF_8.name());
|
||||
|
||||
String query = encryptedParams;
|
||||
|
||||
// 解密查询参数
|
||||
if (encrypt) {
|
||||
query = Sm4Utils.decrypt(query);
|
||||
}
|
||||
|
||||
// 校验数据完整性
|
||||
if (integrality) {
|
||||
String[] parts = query.split("\\|");
|
||||
if (parts.length != 2) {
|
||||
log.error("解密后的参数格式不正确: {}", query);
|
||||
throw new CaptchaException("请求参数不正确");
|
||||
}
|
||||
integrityVerification(parts[1], parts[0]);
|
||||
query = parts[0]; // 只保留原始参数部分
|
||||
}
|
||||
|
||||
if (ObjectUtils.isEmpty(query)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 创建新的请求对象
|
||||
return new QueryStringRequestWrapper(request, query);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("解密查询参数时发生错误: {}", e.getMessage(), e);
|
||||
throw new CaptchaException("请求参数不正确");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据完整性校验
|
||||
*/
|
||||
private void integrityVerification(String providedHmac, String query) {
|
||||
if (providedHmac == null) {
|
||||
log.error("完整性校验哈希值为空");
|
||||
throw new CaptchaException("请求参数不正确");
|
||||
}
|
||||
String calculatedHash = Sm3Util.encrypt(query);
|
||||
log.debug("计算出的哈希值: {}", calculatedHash);
|
||||
log.debug("提供的哈希值: {}", providedHmac);
|
||||
if (!calculatedHash.equals(providedHmac)) {
|
||||
log.error("参数完整性校验失败");
|
||||
throw new CaptchaException("请求参数不正确");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求体包装类
|
||||
*/
|
||||
private static class BodyCachingRequestWrapper extends HttpServletRequestWrapper {
|
||||
private final String body;
|
||||
|
||||
public BodyCachingRequestWrapper(HttpServletRequest request, String body) {
|
||||
super(request);
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
|
||||
return new ServletInputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return byteArrayInputStream.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return byteArrayInputStream.available() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener listener) {
|
||||
// 不需要实现
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() throws IOException {
|
||||
return new BufferedReader(new InputStreamReader(getInputStream()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询字符串包装类
|
||||
*/
|
||||
private static class QueryStringRequestWrapper extends HttpServletRequestWrapper {
|
||||
private final String queryString;
|
||||
|
||||
public QueryStringRequestWrapper(HttpServletRequest request, String queryString) {
|
||||
super(request);
|
||||
this.queryString = queryString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return queryString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String name) {
|
||||
// 解析queryString获取参数值
|
||||
if (queryString != null) {
|
||||
String[] pairs = queryString.split("&");
|
||||
for (String pair : pairs) {
|
||||
String[] keyValue = pair.split("=");
|
||||
if (keyValue.length == 2 && keyValue[0].equals(name)) {
|
||||
return keyValue[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getParameter(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
// 解析queryString为参数Map
|
||||
Map<String, String[]> parameterMap = new HashMap<>();
|
||||
if (queryString != null) {
|
||||
String[] pairs = queryString.split("&");
|
||||
for (String pair : pairs) {
|
||||
String[] keyValue = pair.split("=");
|
||||
if (keyValue.length == 2) {
|
||||
parameterMap.put(keyValue[0], new String[]{keyValue[1]});
|
||||
}
|
||||
}
|
||||
}
|
||||
return parameterMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getParameterNames() {
|
||||
Map<String, String[]> parameterMap = getParameterMap();
|
||||
return Collections.enumeration(parameterMap.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String name) {
|
||||
return getParameterMap().get(name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
package com.bonus.common.filter;
|
||||
|
||||
import com.bonus.common.utils.encryption.Sm4Utils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.util.ContentCachingResponseWrapper;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 对返回的 data数据进行加密
|
||||
*
|
||||
* @author 黑子
|
||||
*/
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class ResponseEncryptFilter implements Filter {
|
||||
|
||||
/**
|
||||
* 加密标识
|
||||
*/
|
||||
private static final String ENCRYPT_RESPONSE = "encryptResponse";
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
// 初始化逻辑
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
|
||||
// 检查请求头中是否包含加密标志
|
||||
if (shouldEncrypt(httpRequest)) {
|
||||
// 使用响应包装器来缓存响应内容
|
||||
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(httpResponse);
|
||||
|
||||
try {
|
||||
chain.doFilter(request, responseWrapper);
|
||||
|
||||
// 获取响应状态码
|
||||
int status = responseWrapper.getStatus();
|
||||
|
||||
// 只处理状态码为200 OK的响应
|
||||
if (status == HttpServletResponse.SC_OK) {
|
||||
// 获取响应内容
|
||||
byte[] responseBody = responseWrapper.getContentAsByteArray();
|
||||
|
||||
if (responseBody != null && responseBody.length > 0) {
|
||||
String responseData = new String(responseBody, StandardCharsets.UTF_8);
|
||||
|
||||
// 加密响应数据
|
||||
String encryptedData = Sm4Utils.encrypt(responseData);
|
||||
byte[] encryptedContent = encryptedData.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
// 设置加密后的响应
|
||||
responseWrapper.resetBuffer();
|
||||
responseWrapper.setContentLength(encryptedContent.length);
|
||||
responseWrapper.getOutputStream().write(encryptedContent);
|
||||
|
||||
// 添加响应头标识
|
||||
responseWrapper.setHeader(ENCRYPT_RESPONSE, "true");
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("响应加密处理时发生错误: {}", e.getMessage(), e);
|
||||
throw new ServletException("响应处理失败", e);
|
||||
} finally {
|
||||
// 确保响应被提交
|
||||
responseWrapper.copyBodyToResponse();
|
||||
}
|
||||
} else {
|
||||
// 不需要加密,直接继续处理链
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// 清理逻辑
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否需要对响应数据进行加密
|
||||
*
|
||||
* @param request 请求对象
|
||||
* @return 如果需要加密返回true,否则返回false
|
||||
*/
|
||||
private boolean shouldEncrypt(HttpServletRequest request) {
|
||||
String encryptHeader = request.getHeader(ENCRYPT_RESPONSE);
|
||||
return "true".equalsIgnoreCase(encryptHeader);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package com.bonus.common.utils.encryption;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.Security;
|
||||
|
||||
/**
|
||||
* AES加密工具类
|
||||
*
|
||||
* @author HeiZi
|
||||
*/
|
||||
@Slf4j
|
||||
public class AesCbcUtils {
|
||||
//使用AES-256-CBC加密模式,key需要为16位,key和iv可以相同!
|
||||
|
||||
/**
|
||||
* 密钥算法
|
||||
*/
|
||||
private static final String KEY_ALGORITHM = "AES";
|
||||
|
||||
/**
|
||||
* 加密/解密算法 / 工作模式 / 填充方式
|
||||
* Java 6支持PKCS5Padding填充方式
|
||||
* Bouncy Castle支持PKCS7Padding填充方式
|
||||
*/
|
||||
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
|
||||
|
||||
/**
|
||||
* 偏移量,只有CBC模式才需要
|
||||
*/
|
||||
private final static String IV_PARAMETER = "1234567812345678";
|
||||
|
||||
|
||||
/**
|
||||
* AES要求密钥长度为128位或192位或256位,java默认限制AES密钥长度最多128位
|
||||
*/
|
||||
public static String sKey = "zhgd@bonus@zhgd@bonus@1234567890";
|
||||
|
||||
/**
|
||||
* 编码格式导出
|
||||
*/
|
||||
public static final String ENCODING = "utf-8";
|
||||
|
||||
static {
|
||||
//如果是PKCS7Padding填充方式,则必须加上下面这行
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* AES加密
|
||||
* (CBC模式)
|
||||
*
|
||||
* @param source 源字符串
|
||||
* @param
|
||||
* @return 加密后的密文
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String encrypt(String source, String key, String encoding, String ivParameter, String cipherAlgorithm, String keyAlgorithm) {
|
||||
try {
|
||||
byte[] sourceBytes = source.getBytes(encoding);
|
||||
byte[] keyBytes = key.getBytes(encoding);
|
||||
Cipher cipher = Cipher.getInstance(cipherAlgorithm, "BC");
|
||||
IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes(encoding));
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, keyAlgorithm), iv);
|
||||
byte[] decrypted = cipher.doFinal(sourceBytes);
|
||||
return Base64.encodeBase64String(decrypted);
|
||||
} catch (Exception e) {
|
||||
log.error(e.toString(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// // String json="";
|
||||
//
|
||||
// String json="{\"username\":\"guest\",\"password\":\"admin@123\"}";
|
||||
// String data=encrypt(json);
|
||||
// System.err.println(data);
|
||||
// String jm=decrypt("\"yeCxaGhmdDt+zDsKPr1prukR15BfIMLMOYIFKdgffGpMV76qVD8ANU4zsLiRZ87+7hd1Yje182nHhUOp/TeYCRuuUPQzmuXH7ikYVEWR1Rmc8uLq3G/BTMU6wFMSRFDBXARRl+dvnpyfX+MleF0KB1OAeuOIKv1gQPskmvDiFAniUlowf/96ZzMl7Bokqc/Lse8lMV92IQB14yQNa0+u/2kvdirzrcq+HCt9K8Ot3C59mjDqg49WoM65LEmaHmZqzdmmjbQlGH7ZOAFTLvF5kPzUsMz5Uim1uNvByB3eLFohc1UgB28DWoTyh43sRMPpq3S1BB20gcrBf3uVra/4qehBr3z98CGhGRyKHbjsCKl0Ri6YO1rp5aMRd9Y3wbOJFrZXFag5iifQx+ooDBeu6h1KCb5JfCjyAmw9+pgEL6X3eELPzK13XjblDyEikjx2Edv45MGsC0DUcjvz/Sb4E/8rn3o1Ep7W31xNCdn5mzZ8VO9POhE3DMK6woeN2C7TW+7YO/Zs9e4zKLS4vThvk5urCn2Ff2HkVBzoPtP2imuqQrY8898sbLllyaJEG0DPSrCf985ZgVa03JsO/EkMr3KAiHV5SHBZS1XEXqjdpL+YEdOnlfBXUk83kJhLj9rhUrTFza7ednQSzjq4XpIJJVy2aJhhj1chsmIM1Xl//0Dbak9Lb6VUq5Xr2IFAjNTgyxwtcFCdEvp4YZCSP6kqWgEpeAVlejyYOcNckUnWkjeHjtfgwvVsvUjWzyIRFCa7m/oY28xBV16RmW/r4XXquqKVdbPtATzrmf7pJCynXZ3IPd9ZGc1OTLnss9Ln9XNTH0E/I4Ma95fn9uxA+sOQkQ==\"");
|
||||
// String jiemi=decrypt(data);
|
||||
// System.err.println(jm);
|
||||
// System.err.println(jiemi);
|
||||
// }
|
||||
|
||||
/**
|
||||
* AES解密
|
||||
* (CBC模式)
|
||||
*
|
||||
* @param data 加密后的密文
|
||||
* @param
|
||||
* @return 源字符串
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String decrypt(String data, String key, String encoding, String ivParameter, String cipherAlgorithm, String keyAlgorithm) {
|
||||
try {
|
||||
String encryptStr = "";
|
||||
if (StringUtils.isNotEmpty(data)) {
|
||||
encryptStr = data.replace(" ", "+");
|
||||
}
|
||||
byte[] sourceBytes = Base64.decodeBase64(encryptStr);
|
||||
byte[] keyBytes = key.getBytes(encoding);
|
||||
Cipher cipher = Cipher.getInstance(cipherAlgorithm, "BC");
|
||||
IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes(encoding));
|
||||
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, keyAlgorithm), iv);
|
||||
byte[] decoded = cipher.doFinal(sourceBytes);
|
||||
return new String(decoded, encoding);
|
||||
} catch (Exception e) {
|
||||
log.info("------------------->请求加密参数不正确");
|
||||
log.error(e.toString(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package com.bonus.common.utils.encryption;
|
||||
|
||||
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 org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
||||
|
||||
|
||||
/**
|
||||
* @author 黑子
|
||||
* SM2加解密
|
||||
*/
|
||||
public class Sm2Util {
|
||||
|
||||
static SM2 sm2 = SmUtil.sm2();
|
||||
/**
|
||||
* 获取公钥
|
||||
* @return
|
||||
*/
|
||||
public static String getPublicKey(){
|
||||
return HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取私钥
|
||||
* @return
|
||||
*/
|
||||
public static String getPrivateKey(){
|
||||
return HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey()));
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// String privateKey = getPrivateKey();
|
||||
// String publicKey = getPublicKey();
|
||||
// String msg= encrypt(publicKey,"1234567890");
|
||||
//// String msg2= decrypt(privateKey,msg);
|
||||
// System.err.println(msg);
|
||||
//// System.err.println(msg2);
|
||||
// }
|
||||
/**
|
||||
* 加密
|
||||
*公钥加密
|
||||
* @param publicKey 公钥
|
||||
* @param data 明文
|
||||
* @return 密文
|
||||
*/
|
||||
public static String encrypt(String publicKey, String data) {
|
||||
return SmUtil.sm2(null, publicKey)
|
||||
.encryptHex(data.getBytes(), KeyType.PublicKey)
|
||||
// 加密后,密文前面会有04,需要去掉
|
||||
.substring(2);
|
||||
}
|
||||
/**
|
||||
* 解密
|
||||
* 私钥解密
|
||||
* @param privateKey 私钥
|
||||
* @param data 密文
|
||||
* @return 明文
|
||||
*/
|
||||
public static String decrypt(String privateKey, String data) {
|
||||
// 前端加密是没有04的,所以解析的时候要加04
|
||||
data = "04" + data;
|
||||
return SmUtil.sm2(privateKey, null)
|
||||
.decryptStr(data, KeyType.PrivateKey);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.bonus.common.utils.encryption;
|
||||
|
||||
import cn.hutool.crypto.SmUtil;
|
||||
import cn.hutool.crypto.digest.SM3;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
/**
|
||||
* @author weiweiw
|
||||
* SM3加解密
|
||||
*/
|
||||
public class Sm3Util {
|
||||
|
||||
static SM3 sm3 = SmUtil.sm3WithSalt("2cc0c5f9f1749f1632efa9f63e902323".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
|
||||
public static String encrypt(String data) {
|
||||
return Sm3Util.sm3.digestHex(data);
|
||||
}
|
||||
|
||||
public static String encrypt(InputStream data) {
|
||||
return Sm3Util.sm3.digestHex(data);
|
||||
}
|
||||
|
||||
public static String encrypt(File dataFile) {
|
||||
return Sm3Util.sm3.digestHex(dataFile);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package com.bonus.common.utils.encryption;
|
||||
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.crypto.Mode;
|
||||
import cn.hutool.crypto.Padding;
|
||||
import cn.hutool.crypto.symmetric.SM4;
|
||||
|
||||
/**
|
||||
* @author bonus
|
||||
*/
|
||||
public class Sm4Utils {
|
||||
/**
|
||||
* 必须是16字节
|
||||
*/
|
||||
private static final String KEY = "78d1295afa99449b99d6f83820e6965c";
|
||||
|
||||
private static final String IV = "f555adf6c01d0ab0761e626a2dae34a2";
|
||||
/**
|
||||
* 加密数据,使用固定盐
|
||||
*
|
||||
* @param plainText 明文,待加密的字符串
|
||||
* @return 加密后的密文(包含盐),Hex 编码格式,如果加密异常就返回传入的字符串
|
||||
*/
|
||||
public static String encrypt(String plainText) {
|
||||
try {
|
||||
SM4 sm4 = new SM4(Mode.CBC, Padding.PKCS5Padding, HexUtil.decodeHex(KEY),HexUtil.decodeHex(IV));
|
||||
// 加密带盐的明文
|
||||
byte[] encryptedData = sm4.encrypt(plainText);
|
||||
// 返回带盐的加密结果(Hex编码)
|
||||
return HexUtil.encodeHexStr(encryptedData);
|
||||
} catch (Exception e) {
|
||||
return plainText; // 发生异常时返回传入字符串
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密数据,使用固定盐
|
||||
*
|
||||
* @param cipherText 密文(包含盐),Hex 编码格式的字符串
|
||||
* @return 解密后的明文字符串,如果解密异常就返回传入的字符串
|
||||
*/
|
||||
public static String decrypt(String cipherText) {
|
||||
try {
|
||||
// 初始化SM4解密工具
|
||||
SM4 sm4 = new SM4(Mode.CBC, Padding.PKCS5Padding, HexUtil.decodeHex(KEY),HexUtil.decodeHex(IV));
|
||||
// 解密数据
|
||||
byte[] decryptedData = sm4.decrypt(cipherText);
|
||||
return new String(decryptedData);
|
||||
} catch (Exception e) {
|
||||
return cipherText; // 发生异常时返回传入字符串
|
||||
}
|
||||
}
|
||||
|
||||
// 测试方法,演示加密和解密过程
|
||||
public static void main(String[] args) {
|
||||
String plainText = "15398187429";
|
||||
System.out.println("原文: " + plainText);
|
||||
|
||||
// 加密明文
|
||||
String encryptedText = Sm4Utils.encrypt(plainText);
|
||||
System.out.println("加密后: " + encryptedText);
|
||||
|
||||
// 解密密文
|
||||
String decryptedText = Sm4Utils.decrypt(plainText);
|
||||
System.out.println("解密后: " + decryptedText);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package com.bonus.common.utils.global;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @Author: meng
|
||||
* @Description: 常用变量
|
||||
* @Date: 2023/3/30 10:29
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Component
|
||||
public class CommonConstant {
|
||||
|
||||
/**
|
||||
* jwt token
|
||||
*/
|
||||
public static final String JWT_TOKEN = "jwt-token";
|
||||
|
||||
/**
|
||||
* 请求头中的token
|
||||
*/
|
||||
public static final String X_TOKEN = "X-TOKEN";
|
||||
|
||||
/**
|
||||
* 请求头中的sign
|
||||
*/
|
||||
public static final String X_SIGN = "X-SIGN";
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static final String X_APPID = "X-APPID";
|
||||
|
||||
public static final String APPLICATION_JSON_UTF8_VALUE = "application/json;charset=UTF-8";
|
||||
|
||||
public static final String CODE = "code";
|
||||
|
||||
public static final String MESSAGE = "message";
|
||||
|
||||
public static final String MSG = "msg";
|
||||
|
||||
public static final String UTF8 = "UTF-8";
|
||||
|
||||
public static final String RSA_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFJIl4il6nDBlF/3byWB/KXRqfEXkviz7ZvO7TU7JBfh7sFqfgLtJFDSA33+qTHOtYTCjCrwl6oWWX7Aff39HiFW1IBnhKjYdSK5/8ruQY+Y2xbpBMgslA0m2euOv3XPJUXWh0JGBqPllgzvtbtUA1iBELAHVYBACuQPYP2VcPeQIDAQAB";
|
||||
public static final String RSA_PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMUkiXiKXqcMGUX/dvJYH8pdGp8ReS+LPtm87tNTskF+HuwWp+Au0kUNIDff6pMc61hMKMKvCXqhZZfsB9/f0eIVbUgGeEqNh1Irn/yu5Bj5jbFukEyCyUDSbZ646/dc8lRdaHQkYGo+WWDO+1u1QDWIEQsAdVgEAK5A9g/ZVw95AgMBAAECgYABvRrBR2ciTgcDCQfBh2lwXXXYpUzOUIoTXYk1r+1IipY3OtPsND2CgmUgWQc2mPCybKmHXgfVXwsIVfqTzOOK+PEMVGYNflUdXgV3hNffRzl/nfPdpqhb2ALu8ftPwiGq5QN2PqaRgY9kM67Ye/cCjFzm/kLIqsNuXLKiQc1ioQJBAO7g4ZBcG/D0IxtiR4RdXYtr4wQc+cmscSKj5RPNBwn0bh9psOSg2loS/wWUmCnYSncsLGgMzPl+yPkTLwGryH0CQQDTRduiOzu6bFdOw6tI6eOxHB5h0kfcim4VT/Huh5RyP+GC7kLBmknbBO/tQXxSDVaG81Pkr+INHxJmctfKik+tAkEAtBIrl0IIAhRXnp3wYXRsPtxeLkyVc5SdWEqKNen5Y2Sx2tY2dbJXx0zIl3FTXz/fqoRPGUSFA5Kydygh6DWRlQJBAMmOfOHB9tJ8Z7LJ85AFKucdt1KFpW8eVbVZZqq0iAeTMBaULfW7tzgO9sJ3Vh6FgQYP//pNXbA883XvnDUrTKUCQQDgLO7mThmy7iqqo0be4a2ycy9fvORFYzSq1t6mTd+gr73CMCy2bTmyv/Qp4QsuPIKea0iE+HA/la5zlM8eAxOq";
|
||||
|
||||
/**
|
||||
* 公共返回方法
|
||||
* @param exchange
|
||||
* @param code
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
public static Mono<Void> buildResponse(ServerWebExchange exchange, int code, String message) {
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
response.getHeaders().add(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON_UTF8_VALUE);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put(CODE, code);
|
||||
jsonObject.put(MSG, message);
|
||||
DataBuffer bodyDataBuffer = response.bufferFactory().wrap(jsonObject.toJSONString().getBytes());
|
||||
return response.writeWith(Mono.just(bodyDataBuffer));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package com.bonus.common.utils.global;
|
||||
|
||||
/**
|
||||
* @author 黑子
|
||||
* 全局变量
|
||||
*/
|
||||
public class SystemGlobal {
|
||||
public final static String TEXT_FIX=".text";
|
||||
/**
|
||||
* true
|
||||
*/
|
||||
public static String TRUE_STR="true";
|
||||
/**
|
||||
* formData
|
||||
*/
|
||||
public static String FORM_DATA="formData";
|
||||
|
||||
/**
|
||||
*
|
||||
* 解密头
|
||||
*/
|
||||
public final static String KEY_DECRYPT="decrypt";
|
||||
/**
|
||||
* 加密头
|
||||
*/
|
||||
public final static String KEY_ENCRYPT ="encryption";
|
||||
/**
|
||||
* 成功的200 字符串
|
||||
*/
|
||||
public final static String SUCCESS_CODE_STR="200";
|
||||
|
||||
/**
|
||||
* POST 请求
|
||||
*/
|
||||
public final static String POST="POST";
|
||||
|
||||
/**
|
||||
* PUT 请求
|
||||
*/
|
||||
public final static String PUT="PUT";
|
||||
|
||||
/**
|
||||
* 成功数据数量
|
||||
*/
|
||||
public final static int SUCCESS_NUM=1;
|
||||
|
||||
/**
|
||||
* 异常日志
|
||||
*/
|
||||
public final static String LOG_ERR="2";
|
||||
|
||||
public final static int LOG_DEFEAT_SIZE=1;
|
||||
|
||||
|
||||
public final static String ERR_NUM="NAN";
|
||||
|
||||
//
|
||||
public final static String LOG_TYPE="1";
|
||||
|
||||
//身份证识别成功码
|
||||
public final static String IDCARD_RECORD_SUCCESS="20000";
|
||||
}
|
||||
|
|
@ -3,6 +3,9 @@ package com.bonus.framework.config;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
import com.bonus.common.filter.RequestCoverFilter;
|
||||
import com.bonus.common.filter.ResponseEncryptFilter;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
|
|
@ -11,6 +14,7 @@ import org.springframework.context.annotation.Configuration;
|
|||
import com.bonus.common.filter.RepeatableFilter;
|
||||
import com.bonus.common.filter.XssFilter;
|
||||
import com.bonus.common.utils.StringUtils;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* Filter配置
|
||||
|
|
@ -55,4 +59,27 @@ public class FilterConfig
|
|||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<RequestCoverFilter> requestCoverFilterRegistration() {
|
||||
FilterRegistrationBean<RequestCoverFilter> registration = new FilterRegistrationBean<>();
|
||||
registration.setFilter(new RequestCoverFilter());
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||
registration.setName("requestCoverFilter");
|
||||
return registration;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册响应加密过滤器
|
||||
*/
|
||||
@Bean
|
||||
public FilterRegistrationBean<ResponseEncryptFilter> responseEncryptFilterRegistration() {
|
||||
FilterRegistrationBean<ResponseEncryptFilter> registration = new FilterRegistrationBean<>();
|
||||
registration.setFilter(new ResponseEncryptFilter());
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setOrder(-5); // 设置过滤器顺序
|
||||
registration.setName("responseEncryptFilter");
|
||||
return registration;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
package com.bonus.framework.filter;
|
||||
|
||||
|
||||
import com.bonus.framework.interceptor.ReadHttpRequestWrapper;
|
||||
import com.bonus.common.utils.global.SystemGlobal;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author bonus
|
||||
*/
|
||||
@Component
|
||||
@WebFilter("/*")
|
||||
@Slf4j
|
||||
public class MyFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
log.debug("进入MyFilter过滤器,parameterMap");
|
||||
if (SystemGlobal.POST.equals(request.getMethod()) || SystemGlobal.PUT.equals(request.getMethod()) ){
|
||||
//去除文件上传
|
||||
String header = request.getHeader(HttpHeaders.CONTENT_TYPE);
|
||||
if(StringUtils.isNotEmpty(header)){
|
||||
if(header.contains(MediaType.MULTIPART_FORM_DATA_VALUE)){
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
//解决 无法流重复读取的问题
|
||||
ReadHttpRequestWrapper requestWrapper = new ReadHttpRequestWrapper(request, request.getParameterMap());
|
||||
filterChain.doFilter(requestWrapper, response);
|
||||
}else{
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package com.bonus.framework.interceptor;
|
||||
|
||||
|
||||
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 java.util.Map;
|
||||
|
||||
/**
|
||||
* 包装和增强原始的 HttpServletRequest 对象,允许多次读取请求体(body)的数据,特别是在处理请求时使用流读取数据的情况下
|
||||
* @author 黑子
|
||||
*/
|
||||
public class ReadHttpRequestWrapper extends HttpServletRequestWrapper {
|
||||
|
||||
private final String body;
|
||||
|
||||
private final Map<String, String[]> parameters;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param request
|
||||
*/
|
||||
public ReadHttpRequestWrapper(HttpServletRequest request,Map<String, String[]> parameters) throws IOException {
|
||||
super(request);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BufferedReader reader = request.getReader();
|
||||
String readCount = "";
|
||||
while((readCount = reader.readLine()) != null){
|
||||
sb.append(readCount);
|
||||
}
|
||||
this.parameters = parameters;
|
||||
body = sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() {
|
||||
return new BufferedReader(new InputStreamReader(this.getInputStream()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() {
|
||||
final ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body.getBytes());
|
||||
ServletInputStream servletIns = new ServletInputStream() {
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(javax.servlet.ReadListener listener) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() {
|
||||
return byteArrayIns.read();
|
||||
}
|
||||
};
|
||||
return servletIns;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
package com.bonus.framework.interceptor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
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 java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author GeYazhong
|
||||
* @date 2021/11/23 10:31
|
||||
*/
|
||||
@Slf4j
|
||||
public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||
|
||||
private byte[] body;
|
||||
|
||||
private String queryString;
|
||||
|
||||
private String streamParam;
|
||||
|
||||
private boolean checked;
|
||||
|
||||
public XssRequestWrapper(HttpServletRequest request) {
|
||||
super(request);
|
||||
getParameterMap();
|
||||
BufferedReader reader;
|
||||
try {
|
||||
reader = request.getReader();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
char[] buf = new char[1024];
|
||||
int rd;
|
||||
while ((rd = reader.read(buf)) != -1) {
|
||||
sb.append(buf, 0, rd);
|
||||
}
|
||||
reader.close();
|
||||
streamParam = xssClean(sb.toString());
|
||||
setChecked(xssCleanNew(sb.toString()) && xssCleanNew(request.getQueryString()));
|
||||
body = streamParam.getBytes();
|
||||
} catch (IOException e) {
|
||||
log.error(e.getLocalizedMessage(),e);
|
||||
}
|
||||
|
||||
queryString = xssClean(request.getQueryString());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return queryString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() throws IOException {
|
||||
return new BufferedReader(new InputStreamReader(getInputStream()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
|
||||
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
|
||||
return new ServletInputStream() {
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener listener) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
int read = bais.read();
|
||||
bais.close();
|
||||
return read;
|
||||
}
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
Map<String, String[]> requestMap = super.getParameterMap();
|
||||
if(requestMap!=null){
|
||||
Iterator iterator = requestMap.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry me = (Map.Entry) iterator.next();
|
||||
String[] values = (String[]) me.getValue();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (values[i] != null) {
|
||||
values[i] = xssClean(values[i]);
|
||||
}
|
||||
}
|
||||
}}
|
||||
return requestMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String paramString) {
|
||||
String[] arrayOfString1 = super.getParameterValues(paramString);
|
||||
if (arrayOfString1 == null){
|
||||
return null;
|
||||
}
|
||||
int i = arrayOfString1.length;
|
||||
String[] arrayOfString2 = new String[i];
|
||||
|
||||
for (int j = 0; j < i; j++) {
|
||||
if (arrayOfString1[j] != null) {
|
||||
arrayOfString2[j] = xssClean(arrayOfString1[j]);
|
||||
}
|
||||
}
|
||||
return arrayOfString2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String paramString) {
|
||||
String str = super.getParameter(paramString);
|
||||
if (str == null){
|
||||
return null;
|
||||
}
|
||||
return xssClean(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String paramString) {
|
||||
String str = super.getHeader(paramString);
|
||||
if (str == null){
|
||||
return null;
|
||||
}
|
||||
return xssClean(str);
|
||||
}
|
||||
String regex1="<script>(.*?)</script>";
|
||||
String regex2="src[\r\n]*=[\r\n]*'(.*?)'";
|
||||
String regex3="src[\r\n]*=[\r\n]*\"(.*?)\"";
|
||||
String regex4="</script>";
|
||||
String regex5="<script(.*?)>";
|
||||
String regex6="eval\\((.*?)\\)";
|
||||
String regex7="e-xpression\\((.*?)\\)";
|
||||
String regex8="javascript:";
|
||||
String regex9="vbscript:";
|
||||
String regex10="onload(.*?)=";
|
||||
private String xssClean(String value) {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
value = value.replaceAll("", "");
|
||||
|
||||
Pattern scriptPattern = Pattern.compile(regex1, Pattern.CASE_INSENSITIVE);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile(regex2, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile(regex3, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile(regex4, Pattern.CASE_INSENSITIVE);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile(regex5, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile(regex6, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile(regex7, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile(regex8, Pattern.CASE_INSENSITIVE);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile(regex9, Pattern.CASE_INSENSITIVE);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile(regex10, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
private boolean xssCleanNew(String value) {
|
||||
boolean find = false;
|
||||
if (value == null) {
|
||||
return true;
|
||||
}
|
||||
List<Pattern> patterns = new ArrayList<Pattern>();
|
||||
patterns.add(Pattern.compile(regex1, Pattern.CASE_INSENSITIVE));
|
||||
patterns.add(Pattern.compile(regex2, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||
patterns.add(Pattern.compile(regex3, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||
patterns.add(Pattern.compile(regex4, Pattern.CASE_INSENSITIVE));
|
||||
patterns.add(Pattern.compile(regex5, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||
patterns.add(Pattern.compile(regex6, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||
patterns.add(Pattern.compile(regex7, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||
patterns.add(Pattern.compile(regex8, Pattern.CASE_INSENSITIVE));
|
||||
patterns.add(Pattern.compile(regex9, Pattern.CASE_INSENSITIVE));
|
||||
patterns.add(Pattern.compile(regex10, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||
|
||||
for (Pattern pattern : patterns) {
|
||||
find = match(pattern, value) ;
|
||||
if (find) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return !find;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行正则表达式
|
||||
*
|
||||
* @param pattern
|
||||
* 表达式
|
||||
* @param str
|
||||
* 待验证字符串
|
||||
* @return 返回 <b>true </b>,否则为 <b>false </b>
|
||||
*/
|
||||
private static boolean match(Pattern pattern, String str) {
|
||||
Matcher m = pattern.matcher(str);
|
||||
return m.find();
|
||||
}
|
||||
|
||||
public String getReaderParam() {
|
||||
return streamParam;
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return checked;
|
||||
}
|
||||
|
||||
public void setChecked(boolean checked) {
|
||||
this.checked = checked;
|
||||
}
|
||||
}
|
||||
|
|
@ -215,7 +215,7 @@ public class GenUtils
|
|||
*/
|
||||
public static String replaceText(String text)
|
||||
{
|
||||
return RegExUtils.replaceAll(text, "(?:表|若依)", "");
|
||||
return RegExUtils.replaceAll(text, "(?:表|)", "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
4
pom.xml
4
pom.xml
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<name>bonus</name>
|
||||
<url>http://www.bonus.vip</url>
|
||||
<description>若依管理系统</description>
|
||||
<description>工程档案资料移交管理系统</description>
|
||||
|
||||
<properties>
|
||||
<bonus.version>3.9.0</bonus.version>
|
||||
|
|
@ -218,6 +218,8 @@
|
|||
<version>${bonus.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue