parent
2ef382c180
commit
b4a0a1c252
318 changed files with 5182 additions and 118 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,98 @@ |
|||||||
|
package com.huoran.iasf.common.advice; |
||||||
|
|
||||||
|
|
||||||
|
import com.huoran.iasf.common.annotation.Decrypt; |
||||||
|
import com.huoran.iasf.common.config.SecretKeyConfig; |
||||||
|
import com.huoran.iasf.common.exception.EncryptRequestException; |
||||||
|
import com.huoran.iasf.common.utils.Base64Util; |
||||||
|
import com.huoran.iasf.common.utils.JsonUtils; |
||||||
|
import com.huoran.iasf.common.utils.RSAUtil; |
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
import org.springframework.http.HttpHeaders; |
||||||
|
import org.springframework.http.HttpInputMessage; |
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* Author:Bobby |
||||||
|
* DateTime:2019/4/9 |
||||||
|
**/ |
||||||
|
public class DecryptHttpInputMessage implements HttpInputMessage { |
||||||
|
|
||||||
|
private Logger log = LoggerFactory.getLogger(this.getClass()); |
||||||
|
private HttpHeaders headers; |
||||||
|
private InputStream body; |
||||||
|
|
||||||
|
|
||||||
|
public DecryptHttpInputMessage(HttpInputMessage inputMessage, SecretKeyConfig secretKeyConfig, Decrypt decrypt) throws Exception { |
||||||
|
|
||||||
|
String privateKey = secretKeyConfig.getPrivateKey(); |
||||||
|
String charset = secretKeyConfig.getCharset(); |
||||||
|
boolean showLog = secretKeyConfig.isShowLog(); |
||||||
|
boolean timestampCheck = secretKeyConfig.isTimestampCheck(); |
||||||
|
|
||||||
|
if (StringUtils.isEmpty(privateKey)) { |
||||||
|
throw new IllegalArgumentException("privateKey is null"); |
||||||
|
} |
||||||
|
|
||||||
|
this.headers = inputMessage.getHeaders(); |
||||||
|
String content = new BufferedReader(new InputStreamReader(inputMessage.getBody())) |
||||||
|
.lines().collect(Collectors.joining(System.lineSeparator())); |
||||||
|
String decryptBody; |
||||||
|
// 未加密内容
|
||||||
|
if (content.startsWith("{")||StringUtils.isNumeric(content)||content.length()<10) { |
||||||
|
// 必须加密
|
||||||
|
if (decrypt.required()) { |
||||||
|
log.error("not support unencrypted content:{}", content); |
||||||
|
throw new EncryptRequestException("not support unencrypted content"); |
||||||
|
} |
||||||
|
log.info("Unencrypted without decryption:{}", content); |
||||||
|
decryptBody = content; |
||||||
|
} else { |
||||||
|
StringBuilder json = new StringBuilder(); |
||||||
|
content = content.replaceAll(" ", "+"); |
||||||
|
|
||||||
|
if (!StringUtils.isEmpty(content)) { |
||||||
|
String[] contents = content.split("\\|"); |
||||||
|
for (String value : contents) { |
||||||
|
value = new String(RSAUtil.decrypt(Base64Util.decode(value), privateKey), charset); |
||||||
|
json.append(value); |
||||||
|
} |
||||||
|
} |
||||||
|
decryptBody = json.toString(); |
||||||
|
if(showLog) { |
||||||
|
log.info("Encrypted data received:{},After decryption:{}", content, decryptBody); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 开启时间戳检查
|
||||||
|
if (timestampCheck) { |
||||||
|
// 容忍最小请求时间
|
||||||
|
long toleranceTime = System.currentTimeMillis() - decrypt.timeout(); |
||||||
|
long requestTime = JsonUtils.getNode(decryptBody, "timestamp").asLong(); |
||||||
|
// 如果请求时间小于最小容忍请求时间, 判定为超时
|
||||||
|
if (requestTime < toleranceTime) { |
||||||
|
log.error("Encryption request has timed out, toleranceTime:{}, requestTime:{}, After decryption:{}", toleranceTime, requestTime, decryptBody); |
||||||
|
throw new EncryptRequestException("request timeout"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
this.body = new ByteArrayInputStream(decryptBody.getBytes()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public InputStream getBody(){ |
||||||
|
return body; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public HttpHeaders getHeaders() { |
||||||
|
return headers; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
package com.huoran.iasf.common.advice; |
||||||
|
|
||||||
|
|
||||||
|
import com.huoran.iasf.common.annotation.Decrypt; |
||||||
|
import com.huoran.iasf.common.config.SecretKeyConfig; |
||||||
|
import com.huoran.iasf.common.exception.EncryptRequestException; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.core.MethodParameter; |
||||||
|
import org.springframework.http.HttpInputMessage; |
||||||
|
import org.springframework.http.converter.HttpMessageConverter; |
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice; |
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice; |
||||||
|
|
||||||
|
import java.lang.reflect.Method; |
||||||
|
import java.lang.reflect.Type; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* Author:Bobby |
||||||
|
* DateTime:2019/4/9 |
||||||
|
**/ |
||||||
|
@ControllerAdvice |
||||||
|
public class EncryptRequestBodyAdvice implements RequestBodyAdvice { |
||||||
|
|
||||||
|
private Logger log = LoggerFactory.getLogger(this.getClass()); |
||||||
|
|
||||||
|
private boolean encrypt; |
||||||
|
private Decrypt decryptAnnotation; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private SecretKeyConfig secretKeyConfig; |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) { |
||||||
|
Method method = methodParameter.getMethod(); |
||||||
|
if (Objects.isNull(method)) { |
||||||
|
encrypt = false; |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (method.isAnnotationPresent(Decrypt.class) && secretKeyConfig.isOpen()) { |
||||||
|
encrypt = true; |
||||||
|
decryptAnnotation = methodParameter.getMethodAnnotation(Decrypt.class); |
||||||
|
return true; |
||||||
|
} |
||||||
|
// 此处如果按照原逻辑直接返回encrypt, 会造成一次修改为true之后, 后续请求都会变成true, 在不支持时, 需要做修正
|
||||||
|
encrypt = false; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) { |
||||||
|
return body; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, |
||||||
|
Class<? extends HttpMessageConverter<?>> converterType){ |
||||||
|
if (encrypt) { |
||||||
|
try { |
||||||
|
return new DecryptHttpInputMessage(inputMessage, secretKeyConfig, decryptAnnotation); |
||||||
|
} catch (EncryptRequestException e) { |
||||||
|
throw e; |
||||||
|
} catch (Exception e) { |
||||||
|
log.error("Decryption failed", e); |
||||||
|
} |
||||||
|
} |
||||||
|
return inputMessage; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, |
||||||
|
Class<? extends HttpMessageConverter<?>> converterType) { |
||||||
|
return body; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
package com.huoran.iasf.common.advice; |
||||||
|
|
||||||
|
|
||||||
|
import com.huoran.iasf.common.annotation.Encrypt; |
||||||
|
import com.huoran.iasf.common.config.SecretKeyConfig; |
||||||
|
import com.huoran.iasf.common.utils.Base64Util; |
||||||
|
import com.huoran.iasf.common.utils.JsonUtils; |
||||||
|
import com.huoran.iasf.common.utils.RSAUtil; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.core.MethodParameter; |
||||||
|
import org.springframework.http.MediaType; |
||||||
|
import org.springframework.http.converter.HttpMessageConverter; |
||||||
|
import org.springframework.http.server.ServerHttpRequest; |
||||||
|
import org.springframework.http.server.ServerHttpResponse; |
||||||
|
import org.springframework.util.StringUtils; |
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice; |
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; |
||||||
|
|
||||||
|
import java.lang.reflect.Method; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* Author:Bobby |
||||||
|
* DateTime:2019/4/9 |
||||||
|
**/ |
||||||
|
@ControllerAdvice |
||||||
|
public class EncryptResponseBodyAdvice implements ResponseBodyAdvice<Object> { |
||||||
|
|
||||||
|
private Logger log = LoggerFactory.getLogger(this.getClass()); |
||||||
|
|
||||||
|
private boolean encrypt; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private SecretKeyConfig secretKeyConfig; |
||||||
|
|
||||||
|
private static ThreadLocal<Boolean> encryptLocal = new ThreadLocal<>(); |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { |
||||||
|
Method method = returnType.getMethod(); |
||||||
|
if (Objects.isNull(method)) { |
||||||
|
return encrypt; |
||||||
|
} |
||||||
|
encrypt = method.isAnnotationPresent(Encrypt.class) && secretKeyConfig.isOpen(); |
||||||
|
return encrypt; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, |
||||||
|
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { |
||||||
|
// EncryptResponseBodyAdvice.setEncryptStatus(false);
|
||||||
|
// Dynamic Settings Not Encrypted
|
||||||
|
Boolean status = encryptLocal.get(); |
||||||
|
if (null != status && !status) { |
||||||
|
encryptLocal.remove(); |
||||||
|
return body; |
||||||
|
} |
||||||
|
if (encrypt) { |
||||||
|
String publicKey = secretKeyConfig.getPublicKey(); |
||||||
|
try { |
||||||
|
String content = JsonUtils.writeValueAsString(body); |
||||||
|
if (!StringUtils.hasText(publicKey)) { |
||||||
|
throw new NullPointerException("Please configure rsa.encrypt.privatekeyc parameter!"); |
||||||
|
} |
||||||
|
byte[] data = content.getBytes(); |
||||||
|
byte[] encodedData = RSAUtil.encrypt(data, publicKey); |
||||||
|
String result = Base64Util.encode(encodedData); |
||||||
|
if(secretKeyConfig.isShowLog()) { |
||||||
|
log.info("Pre-encrypted data:{},After encryption:{}", content, result); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} catch (Exception e) { |
||||||
|
log.error("Encrypted data exception", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return body; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
package com.huoran.iasf.common.annotation; |
||||||
|
|
||||||
|
|
||||||
|
import com.huoran.iasf.common.exception.EncryptRequestException; |
||||||
|
|
||||||
|
import java.lang.annotation.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* Author:Bobby |
||||||
|
* DateTime:2019/4/9 16:45 |
||||||
|
**/ |
||||||
|
@Target(ElementType.METHOD) |
||||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||||
|
@Documented |
||||||
|
public @interface Decrypt{ |
||||||
|
|
||||||
|
/** |
||||||
|
* 请求参数一定要是加密内容 |
||||||
|
*/ |
||||||
|
boolean required() default true; |
||||||
|
|
||||||
|
/** |
||||||
|
* 请求数据时间戳校验时间差 |
||||||
|
* 超过(当前时间-指定时间)的数据认定为伪造 |
||||||
|
* 注意应用程序需要捕获 {@link EncryptRequestException} 异常 |
||||||
|
*/ |
||||||
|
long timeout() default 3000; |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package com.huoran.iasf.common.annotation; |
||||||
|
|
||||||
|
|
||||||
|
import com.huoran.iasf.common.advice.EncryptRequestBodyAdvice; |
||||||
|
import com.huoran.iasf.common.advice.EncryptResponseBodyAdvice; |
||||||
|
import com.huoran.iasf.common.config.SecretKeyConfig; |
||||||
|
import org.springframework.context.annotation.Import; |
||||||
|
|
||||||
|
import java.lang.annotation.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* Author:Bobby |
||||||
|
* DateTime:2019/4/9 16:44 |
||||||
|
**/ |
||||||
|
@Target({ElementType.TYPE}) |
||||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||||
|
@Inherited |
||||||
|
@Documented |
||||||
|
@Import({SecretKeyConfig.class, |
||||||
|
EncryptResponseBodyAdvice.class, |
||||||
|
EncryptRequestBodyAdvice.class}) |
||||||
|
public @interface EnableSecurity{ |
||||||
|
|
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package com.huoran.iasf.common.annotation; |
||||||
|
|
||||||
|
import java.lang.annotation.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* Author:Bobby |
||||||
|
* DateTime:2019/4/9 16:45 |
||||||
|
**/ |
||||||
|
@Target(ElementType.METHOD) |
||||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||||
|
@Documented |
||||||
|
public @interface Encrypt{ |
||||||
|
|
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
package com.huoran.iasf.common.config; |
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||||
|
import org.springframework.context.annotation.Configuration; |
||||||
|
|
||||||
|
/** |
||||||
|
* Author:Bobby |
||||||
|
* DateTime:2019/4/9 |
||||||
|
**/ |
||||||
|
@ConfigurationProperties(prefix = "rsa.encrypt") |
||||||
|
@Configuration |
||||||
|
public class SecretKeyConfig { |
||||||
|
|
||||||
|
private String privateKey; |
||||||
|
|
||||||
|
private String publicKey; |
||||||
|
|
||||||
|
private String charset = "UTF-8"; |
||||||
|
|
||||||
|
private boolean open = true; |
||||||
|
|
||||||
|
private boolean showLog = false; |
||||||
|
|
||||||
|
/** |
||||||
|
* 请求数据时间戳校验时间差 |
||||||
|
* 超过指定时间的数据认定为伪造 |
||||||
|
*/ |
||||||
|
private boolean timestampCheck = false; |
||||||
|
|
||||||
|
public String getPrivateKey() { |
||||||
|
return privateKey; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPrivateKey(String privateKey) { |
||||||
|
this.privateKey = privateKey; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPublicKey() { |
||||||
|
return publicKey; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPublicKey(String publicKey) { |
||||||
|
this.publicKey = publicKey; |
||||||
|
} |
||||||
|
|
||||||
|
public String getCharset() { |
||||||
|
return charset; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCharset(String charset) { |
||||||
|
this.charset = charset; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isOpen() { |
||||||
|
return open; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOpen(boolean open) { |
||||||
|
this.open = open; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isShowLog() { |
||||||
|
return showLog; |
||||||
|
} |
||||||
|
|
||||||
|
public void setShowLog(boolean showLog) { |
||||||
|
this.showLog = showLog; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isTimestampCheck() { |
||||||
|
return timestampCheck; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTimestampCheck(boolean timestampCheck) { |
||||||
|
this.timestampCheck = timestampCheck; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package com.huoran.iasf.common.exception; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @author imyzt |
||||||
|
* @date 2020/06/02 |
||||||
|
* @description 加密请求超时异常 |
||||||
|
*/ |
||||||
|
public class EncryptRequestException extends RuntimeException { |
||||||
|
|
||||||
|
public EncryptRequestException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
package com.huoran.iasf.common.filter; |
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils; |
||||||
|
import org.springframework.core.annotation.Order; |
||||||
|
|
||||||
|
import javax.servlet.*; |
||||||
|
import javax.servlet.annotation.WebFilter; |
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@WebFilter(filterName = "xssFilter", urlPatterns = "/*", asyncSupported = true) |
||||||
|
@Order(2) |
||||||
|
public class XSSFilter implements Filter { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void init(FilterConfig filterConfig1) throws ServletException { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) |
||||||
|
throws IOException, ServletException { |
||||||
|
|
||||||
|
//注入xss过滤器实例
|
||||||
|
if(arg2 != null){ |
||||||
|
HttpServletRequest req = (HttpServletRequest) arg0; |
||||||
|
String method = req.getMethod(); |
||||||
|
boolean methodB = false; |
||||||
|
if("POST".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method)){ |
||||||
|
methodB = true; |
||||||
|
} |
||||||
|
|
||||||
|
if (methodB && req.getContentType() != null && req.getContentType().startsWith("multipart/")) { |
||||||
|
// 过滤
|
||||||
|
arg2.doFilter(req, arg1); |
||||||
|
}else { |
||||||
|
HttpServletResponse response = (HttpServletResponse) arg1; |
||||||
|
XssHttpServletRequestWrapper reqW = new XssHttpServletRequestWrapper(req); |
||||||
|
//过滤
|
||||||
|
arg2.doFilter(reqW, response); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void destroy() { |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,224 @@ |
|||||||
|
package com.huoran.iasf.common.filter; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import com.huoran.iasf.common.exception.BusinessException; |
||||||
|
import com.huoran.iasf.common.exception.code.BaseResponseCode; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
|
||||||
|
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; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { |
||||||
|
|
||||||
|
/** |
||||||
|
* post请求体 |
||||||
|
*/ |
||||||
|
private byte[] body; |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否是文件上传 |
||||||
|
*/ |
||||||
|
private boolean fileUpload = true; |
||||||
|
|
||||||
|
//富文本验证链接
|
||||||
|
private static final String[] whiteList = |
||||||
|
{"/iasf/sysContent/save", |
||||||
|
"/iasf/sysContent/update"}; |
||||||
|
|
||||||
|
/** |
||||||
|
* sql注入正则 |
||||||
|
*/ |
||||||
|
private static String badStrReg = |
||||||
|
"\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)"; |
||||||
|
|
||||||
|
/** |
||||||
|
* xss脚本正则 |
||||||
|
*/ |
||||||
|
private final static Pattern[] scriptPatterns = { |
||||||
|
Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE), |
||||||
|
Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), |
||||||
|
Pattern.compile("</script>", Pattern.CASE_INSENSITIVE), |
||||||
|
Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), |
||||||
|
Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), |
||||||
|
Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), |
||||||
|
Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE), |
||||||
|
Pattern.compile("script", Pattern.CASE_INSENSITIVE), |
||||||
|
Pattern.compile("ScriPT", Pattern.CASE_INSENSITIVE), |
||||||
|
Pattern.compile("meta", Pattern.CASE_INSENSITIVE), |
||||||
|
Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE), |
||||||
|
Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL) |
||||||
|
}; |
||||||
|
|
||||||
|
public XssHttpServletRequestWrapper() { |
||||||
|
super(null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 构造函数 - 获取post请求体 |
||||||
|
* @param httpservletrequest |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public XssHttpServletRequestWrapper(HttpServletRequest httpservletrequest) throws IOException { |
||||||
|
super(httpservletrequest); |
||||||
|
String sessionStream = getBodyString(httpservletrequest); |
||||||
|
body = sessionStream.getBytes(StandardCharsets.UTF_8); |
||||||
|
System.out.println(httpservletrequest.getRequestURI()); |
||||||
|
if(Arrays.asList(whiteList).contains(httpservletrequest.getRequestURI())){ |
||||||
|
fileUpload = false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 读取post请求体 |
||||||
|
* @param httpservletrequest |
||||||
|
* @return |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
private String getBodyString(HttpServletRequest httpservletrequest) throws IOException { |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
InputStream ins = httpservletrequest.getInputStream(); |
||||||
|
try (BufferedReader isr = new BufferedReader(new InputStreamReader(ins, StandardCharsets.UTF_8));) { |
||||||
|
String line = ""; |
||||||
|
while ((line = isr.readLine()) != null) { |
||||||
|
sb.append(line); |
||||||
|
} |
||||||
|
} catch (IOException e) { |
||||||
|
throw e; |
||||||
|
} |
||||||
|
return sb.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 过滤springmvc中的 @RequestParam 注解中的参数 |
||||||
|
* @param s |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public String[] getParameterValues(String s) { |
||||||
|
String[] str = super.getParameterValues(s); |
||||||
|
if (str == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
int i = str.length; |
||||||
|
String[] as1 = new String[i]; |
||||||
|
for (int j = 0; j < i; j++) { |
||||||
|
as1[j] = cleanXSS(cleanSQLInject(str[j])); |
||||||
|
} |
||||||
|
// log.info("XssHttpServletRequestWrapper净化后的请求为:========== {}", Arrays.toString(as1));
|
||||||
|
return as1; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 过滤request.getParameter的参数 |
||||||
|
* @param s |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public String getParameter(String s) { |
||||||
|
String s1 = super.getParameter(s); |
||||||
|
if (s1 == null) { |
||||||
|
return null; |
||||||
|
} else { |
||||||
|
String s2 = cleanXSS(cleanSQLInject(s1)); |
||||||
|
// log.info("XssHttpServletRequestWrapper净化后的请求为:========== {}", s2);
|
||||||
|
return s2; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 过滤请求体 json 格式的 |
||||||
|
* @return |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public ServletInputStream getInputStream() throws IOException { |
||||||
|
// 非文件上传进行过滤
|
||||||
|
if (!fileUpload) { |
||||||
|
// 获取body中的请求参数
|
||||||
|
JSONObject json = JSONObject.parseObject(new String(body)); |
||||||
|
// 校验并过滤xss攻击和sql注入
|
||||||
|
for (String k : json.keySet()) { |
||||||
|
cleanSQLInject(cleanXSS(json.getString(k))); |
||||||
|
} |
||||||
|
} |
||||||
|
// 将请求体参数流转 -- 流读取一次就会消失,所以我们事先读取之后就存在byte数组里边方便流转
|
||||||
|
final ByteArrayInputStream bais = new ByteArrayInputStream(body); |
||||||
|
return new ServletInputStream() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public int read() throws IOException { |
||||||
|
return bais.read(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isFinished() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isReady() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setReadListener(ReadListener readListener) { |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 清除xss |
||||||
|
* @param src 单个参数 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public String cleanXSS(String src) { |
||||||
|
if(StringUtils.isBlank(src)){ |
||||||
|
return src; |
||||||
|
} |
||||||
|
String temp = src; |
||||||
|
// 校验xss脚本
|
||||||
|
for (Pattern pattern : scriptPatterns) { |
||||||
|
temp = pattern.matcher(temp).replaceAll(""); |
||||||
|
} |
||||||
|
// 校验xss特殊字符 匹配一个空白字符(包括空格、制表符、换页符和换行符等)//这个可以不用,因为有写数据用富文本编辑的时候有换行
|
||||||
|
// temp = temp.replaceAll("\0|\n|\r", "");
|
||||||
|
temp = temp.replaceAll("<", "<").replaceAll(">", ">"); |
||||||
|
|
||||||
|
if (!temp.equals(src)) { |
||||||
|
|
||||||
|
log.error("xss攻击检查:参数含有非法攻击字符,已禁止继续访问!"); |
||||||
|
log.error("原始输入信息-->" + temp); |
||||||
|
|
||||||
|
throw new BusinessException(BaseResponseCode.XSS_FILTER); |
||||||
|
} |
||||||
|
|
||||||
|
return src; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 过滤sql注入 -- 需要增加通配,过滤大小写组合 |
||||||
|
* @param src 单个参数值 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public String cleanSQLInject(String src) { |
||||||
|
if(StringUtils.isBlank(src)){ |
||||||
|
return src; |
||||||
|
} |
||||||
|
// 非法sql注入正则
|
||||||
|
Pattern sqlPattern = Pattern.compile(badStrReg, Pattern.CASE_INSENSITIVE); |
||||||
|
if (sqlPattern.matcher(src.toLowerCase()).find()) { |
||||||
|
log.error("sql注入检查:输入信息存在SQL攻击!"); |
||||||
|
throw new BusinessException(BaseResponseCode.SQL_FILTER); |
||||||
|
} |
||||||
|
return src; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
package com.huoran.iasf.common.utils; |
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64; |
||||||
|
|
||||||
|
/** |
||||||
|
* Base64 |
||||||
|
* Author:Bobby |
||||||
|
* DateTime:2019/4/9 |
||||||
|
**/ |
||||||
|
public class Base64Util{ |
||||||
|
|
||||||
|
/** |
||||||
|
* Decoding to binary |
||||||
|
* @param base64 base64 |
||||||
|
* @return byte |
||||||
|
* @throws Exception Exception |
||||||
|
*/ |
||||||
|
public static byte[] decode(String base64) throws Exception { |
||||||
|
return Base64.decodeBase64(base64); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Binary encoding as a string |
||||||
|
* @param bytes byte |
||||||
|
* @return String |
||||||
|
* @throws Exception Exception |
||||||
|
*/ |
||||||
|
public static String encode(byte[] bytes) throws Exception { |
||||||
|
return new String(Base64.encodeBase64(bytes)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
package com.huoran.iasf.common.utils; |
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException; |
||||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author imyzt |
||||||
|
* @date 2020/06/08 |
||||||
|
* @description JSON 工具类 |
||||||
|
*/ |
||||||
|
public class JsonUtils { |
||||||
|
|
||||||
|
private JsonUtils() { |
||||||
|
} |
||||||
|
|
||||||
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); |
||||||
|
|
||||||
|
public static JsonNode getNode(String content, String key) throws IOException { |
||||||
|
JsonNode jsonNode = OBJECT_MAPPER.readTree(content); |
||||||
|
return jsonNode.get(key); |
||||||
|
} |
||||||
|
|
||||||
|
public static String writeValueAsString(Object body) throws JsonProcessingException { |
||||||
|
return OBJECT_MAPPER.writeValueAsString(body); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,103 @@ |
|||||||
|
package com.huoran.iasf.common.utils; |
||||||
|
|
||||||
|
import javax.crypto.Cipher; |
||||||
|
import java.io.ByteArrayOutputStream; |
||||||
|
import java.security.Key; |
||||||
|
import java.security.KeyFactory; |
||||||
|
import java.security.spec.PKCS8EncodedKeySpec; |
||||||
|
import java.security.spec.X509EncodedKeySpec; |
||||||
|
|
||||||
|
/** |
||||||
|
* RSA Util |
||||||
|
* Author:Bobby |
||||||
|
* DateTime:2019/4/9 |
||||||
|
**/ |
||||||
|
public class RSAUtil{ |
||||||
|
|
||||||
|
/** |
||||||
|
* encryption algorithm RSA |
||||||
|
*/ |
||||||
|
public static final String KEY_ALGORITHM = "RSA"; |
||||||
|
|
||||||
|
/** |
||||||
|
* RSA Maximum Encrypted Plaintext Size |
||||||
|
*/ |
||||||
|
private static final int MAX_ENCRYPT_BLOCK = 117; |
||||||
|
|
||||||
|
/** |
||||||
|
* RSA Maximum decrypted ciphertext size |
||||||
|
*/ |
||||||
|
private static final int MAX_DECRYPT_BLOCK = 256; |
||||||
|
|
||||||
|
/** |
||||||
|
* encryption |
||||||
|
* @param data data |
||||||
|
* @param publicKey publicKey |
||||||
|
* @return byte |
||||||
|
* @throws Exception Exception |
||||||
|
*/ |
||||||
|
public static byte[] encrypt(byte[] data, String publicKey) |
||||||
|
throws Exception { |
||||||
|
byte[] keyBytes = Base64Util.decode(publicKey); |
||||||
|
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); |
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); |
||||||
|
Key publicK = keyFactory.generatePublic(x509KeySpec); |
||||||
|
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); |
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, publicK); |
||||||
|
int inputLen = data.length; |
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
||||||
|
int offSet = 0; |
||||||
|
byte[] cache; |
||||||
|
int i = 0; |
||||||
|
// Sectional Encryption of Data
|
||||||
|
while (inputLen - offSet > 0) { |
||||||
|
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { |
||||||
|
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); |
||||||
|
} else { |
||||||
|
cache = cipher.doFinal(data, offSet, inputLen - offSet); |
||||||
|
} |
||||||
|
out.write(cache, 0, cache.length); |
||||||
|
i++; |
||||||
|
offSet = i * MAX_ENCRYPT_BLOCK; |
||||||
|
} |
||||||
|
byte[] encryptedData = out.toByteArray(); |
||||||
|
out.close(); |
||||||
|
return encryptedData; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Decrypt |
||||||
|
* @param text text |
||||||
|
* @param privateKey privateKey |
||||||
|
* @return byte |
||||||
|
* @throws Exception Exception |
||||||
|
*/ |
||||||
|
public static byte[] decrypt(byte[] text, String privateKey) |
||||||
|
throws Exception { |
||||||
|
byte[] keyBytes = Base64Util.decode(privateKey); |
||||||
|
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); |
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); |
||||||
|
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); |
||||||
|
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); |
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privateK); |
||||||
|
int inputLen = text.length; |
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
||||||
|
int offSet = 0; |
||||||
|
byte[] cache; |
||||||
|
int i = 0; |
||||||
|
// Sectional Encryption of Data
|
||||||
|
while (inputLen - offSet > 0) { |
||||||
|
if (inputLen - offSet > MAX_DECRYPT_BLOCK) { |
||||||
|
cache = cipher.doFinal(text, offSet, MAX_DECRYPT_BLOCK); |
||||||
|
} else { |
||||||
|
cache = cipher.doFinal(text, offSet, inputLen - offSet); |
||||||
|
} |
||||||
|
out.write(cache, 0, cache.length); |
||||||
|
i++; |
||||||
|
offSet = i * MAX_DECRYPT_BLOCK; |
||||||
|
} |
||||||
|
byte[] decryptedData = out.toByteArray(); |
||||||
|
out.close(); |
||||||
|
return decryptedData; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,119 @@ |
|||||||
|
package com.huoran.iasf.common.utils; |
||||||
|
|
||||||
|
import com.huoran.iasf.common.exception.BusinessException; |
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.util.HashMap; |
||||||
|
|
||||||
|
import static com.huoran.iasf.common.exception.code.BaseResponseCode.UPLOAD_FAILED; |
||||||
|
|
||||||
|
/** |
||||||
|
* 文件上传校验工具类 |
||||||
|
**/ |
||||||
|
public class fileUploadUtils { |
||||||
|
|
||||||
|
|
||||||
|
// 缓存文件魔数值
|
||||||
|
public static final HashMap<String, String> mFileTypes = new HashMap<String, String>(); |
||||||
|
|
||||||
|
static { |
||||||
|
mFileTypes.put("FFD8FFE0", "jpg"); |
||||||
|
mFileTypes.put("89504E47", "png"); |
||||||
|
mFileTypes.put("47494638", "gif"); |
||||||
|
// mFileTypes.put("49492A00", "tif");
|
||||||
|
// mFileTypes.put("424D", "bmp");
|
||||||
|
// mFileTypes.put("38425053", "psd");
|
||||||
|
// mFileTypes.put("3C3F786D6C", "xml");
|
||||||
|
// mFileTypes.put("68746D6C3E", "html");
|
||||||
|
mFileTypes.put("D0CF11E0", "doc"); |
||||||
|
mFileTypes.put("D0CF11E0", "xls");//excel2003版本文件
|
||||||
|
mFileTypes.put("6D6F6F76", "mov"); |
||||||
|
mFileTypes.put("504B0304", "xlsx");//excel2007以上版本文件
|
||||||
|
// mFileTypes.put("5374616E64617264204A", "mdb");
|
||||||
|
mFileTypes.put("255044462D312E", "pdf"); |
||||||
|
mFileTypes.put("504B0304", "docx"); |
||||||
|
mFileTypes.put("00000020667479706D70","MP4"); |
||||||
|
mFileTypes.put("49443303000000002176","MP3"); |
||||||
|
// mFileTypes.put("52617221", "rar");
|
||||||
|
// mFileTypes.put("41564920", "avi");
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 文件上传校验 |
||||||
|
* |
||||||
|
* @param file 上传的文件 |
||||||
|
* @param allowedExtension 允许上传的文件后缀集合 |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public static final void assertAllowed(MultipartFile file, String[] allowedExtension) throws Exception { |
||||||
|
|
||||||
|
//通过文件魔数获取文件的原始类型
|
||||||
|
String fileExtension = mFileTypes.get(getFileHeader(file)); |
||||||
|
//原始类型与允许类型集合进行比较,判断文件是否合法
|
||||||
|
if (!isAllowedExtension(fileExtension, allowedExtension)) { |
||||||
|
throw new BusinessException(UPLOAD_FAILED); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取文件魔数值 |
||||||
|
* |
||||||
|
* @param file |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String getFileHeader(MultipartFile file) { |
||||||
|
InputStream is = null; |
||||||
|
String value = null; |
||||||
|
try { |
||||||
|
is = file.getInputStream(); |
||||||
|
byte[] b = new byte[4]; |
||||||
|
is.read(b, 0, b.length); |
||||||
|
value = bytesToHexString(b); |
||||||
|
} catch (Exception e) { |
||||||
|
} finally { |
||||||
|
if (null != is) { |
||||||
|
try { |
||||||
|
is.close(); |
||||||
|
} catch (IOException e) { |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
private static String bytesToHexString(byte[] src) { |
||||||
|
StringBuilder builder = new StringBuilder(); |
||||||
|
if (src == null || src.length <= 0) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
String hv; |
||||||
|
for (int i = 0; i < src.length; i++) { |
||||||
|
hv = Integer.toHexString(src[i] & 0xFF).toUpperCase(); |
||||||
|
if (hv.length() < 2) { |
||||||
|
builder.append(0); |
||||||
|
} |
||||||
|
builder.append(hv); |
||||||
|
} |
||||||
|
System.out.println("文件魔数值为:" + builder.toString()); |
||||||
|
return builder.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 判断MIME类型是否是允许的MIME类型 |
||||||
|
* |
||||||
|
* @param extension |
||||||
|
* @param allowedExtension |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static final boolean isAllowedExtension(String extension, String[] allowedExtension) { |
||||||
|
for (String str : allowedExtension) { |
||||||
|
if (str.equalsIgnoreCase(extension)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
package com.huoran.iasf.controller; |
||||||
|
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil; |
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
||||||
|
import com.huoran.iasf.common.aop.annotation.LogAnnotation; |
||||||
|
import com.huoran.iasf.common.utils.R; |
||||||
|
import com.huoran.iasf.entity.Seo; |
||||||
|
import com.huoran.iasf.entity.Site; |
||||||
|
import com.huoran.iasf.service.SeoService; |
||||||
|
import com.huoran.iasf.service.SiteService; |
||||||
|
import io.swagger.annotations.Api; |
||||||
|
import io.swagger.annotations.ApiOperation; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.util.StringUtils; |
||||||
|
import org.springframework.web.bind.annotation.*; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* 前端控制器 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author cheney |
||||||
|
* @since 2023-08-24 |
||||||
|
*/ |
||||||
|
@Api(tags = "seo管理") |
||||||
|
@RestController |
||||||
|
@RequestMapping("/seo") |
||||||
|
public class SeoController { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private SeoService seoService; |
||||||
|
|
||||||
|
@PostMapping("/add") |
||||||
|
@ApiOperation(value = "新增seo") |
||||||
|
public R addUserGroup(@RequestBody Seo seo) { |
||||||
|
Seo one = seoService.getOne(new QueryWrapper<Seo>(). |
||||||
|
eq("title", seo.getTitle())); |
||||||
|
if (ObjectUtil.isNotNull(one)){ |
||||||
|
R.fail("seo已存在"); |
||||||
|
} |
||||||
|
boolean save = seoService.save(seo); |
||||||
|
return save ? R.success() : R.fail("添加失败"); |
||||||
|
} |
||||||
|
|
||||||
|
@PostMapping("/delete") |
||||||
|
@ApiOperation(value = "删除seo") |
||||||
|
public R deleted(@RequestParam Integer id) { |
||||||
|
boolean remove = seoService.removeById(id); |
||||||
|
return remove ? R.success() : R.fail("删除失败"); |
||||||
|
} |
||||||
|
|
||||||
|
@PostMapping("/update") |
||||||
|
@ApiOperation(value = "更新seo") |
||||||
|
public R update(@RequestBody Seo seo) { |
||||||
|
boolean update = seoService.updateById(seo); |
||||||
|
return update ? R.success() : R.fail("更新失败"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/list") |
||||||
|
@ApiOperation(value = "站点seo列表") |
||||||
|
public R list(@RequestParam Integer siteId) { |
||||||
|
QueryWrapper<Seo> queryWrapper = new QueryWrapper<>(); |
||||||
|
queryWrapper.eq("site_id",siteId); |
||||||
|
List<Seo> list = seoService.list(queryWrapper); |
||||||
|
return R.success(list); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
@ -0,0 +1,44 @@ |
|||||||
|
package com.huoran.iasf.entity; |
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName; |
||||||
|
import com.baomidou.mybatisplus.annotation.IdType; |
||||||
|
import com.baomidou.mybatisplus.annotation.TableId; |
||||||
|
import java.io.Serializable; |
||||||
|
import io.swagger.annotations.ApiModel; |
||||||
|
import io.swagger.annotations.ApiModelProperty; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.EqualsAndHashCode; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author cheney |
||||||
|
* @since 2023-08-24 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@EqualsAndHashCode(callSuper = false) |
||||||
|
@TableName("sys_seo") |
||||||
|
@ApiModel(value="Seo对象", description="") |
||||||
|
public class Seo implements Serializable { |
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L; |
||||||
|
|
||||||
|
@ApiModelProperty(value = "主键") |
||||||
|
@TableId(value = "id", type = IdType.AUTO) |
||||||
|
private Integer id; |
||||||
|
|
||||||
|
@ApiModelProperty(value = "标题") |
||||||
|
private String title; |
||||||
|
|
||||||
|
@ApiModelProperty(value = "关键词") |
||||||
|
private String keyword; |
||||||
|
|
||||||
|
@ApiModelProperty(value = "描述") |
||||||
|
private String description; |
||||||
|
|
||||||
|
@ApiModelProperty(value = "站点") |
||||||
|
private Integer siteId; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package com.huoran.iasf.mapper; |
||||||
|
|
||||||
|
import com.huoran.iasf.entity.Seo; |
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* Mapper 接口 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author cheney |
||||||
|
* @since 2023-08-24 |
||||||
|
*/ |
||||||
|
public interface SeoMapper extends BaseMapper<Seo> { |
||||||
|
|
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||||
|
<mapper namespace="com.huoran.iasf.mapper.SeoMapper"> |
||||||
|
|
||||||
|
</mapper> |
@ -0,0 +1,16 @@ |
|||||||
|
package com.huoran.iasf.service; |
||||||
|
|
||||||
|
import com.huoran.iasf.entity.Seo; |
||||||
|
import com.baomidou.mybatisplus.extension.service.IService; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* 服务类 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author cheney |
||||||
|
* @since 2023-08-24 |
||||||
|
*/ |
||||||
|
public interface SeoService extends IService<Seo> { |
||||||
|
|
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.huoran.iasf.service.impl; |
||||||
|
|
||||||
|
import com.huoran.iasf.entity.Seo; |
||||||
|
import com.huoran.iasf.mapper.SeoMapper; |
||||||
|
import com.huoran.iasf.service.SeoService; |
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* 服务实现类 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author cheney |
||||||
|
* @since 2023-08-24 |
||||||
|
*/ |
||||||
|
@Service |
||||||
|
public class SeoServiceImpl extends ServiceImpl<SeoMapper, Seo> implements SeoService { |
||||||
|
|
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
package com.huoran.iasf.vo.req; |
||||||
|
|
||||||
|
import io.swagger.annotations.ApiParam; |
||||||
|
import lombok.Data; |
||||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||||
|
@Data |
||||||
|
public class AllTheQuery { |
||||||
|
|
||||||
|
@ApiParam(name = "siteId", value = "站点id", required = true) |
||||||
|
Integer siteId; |
||||||
|
@ApiParam(name = "templateId", value = "模板id", required = true) |
||||||
|
Integer templateId; |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
package com.huoran.iasf.vo.req; |
||||||
|
|
||||||
|
import io.swagger.annotations.ApiParam; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
@Data |
||||||
|
public class ArticleEnableOrDisable { |
||||||
|
@ApiParam(name = "id", value = "文章id", required = true) |
||||||
|
String id; |
||||||
|
@ApiParam(name = "isDisable", value = "是否禁用(0默认,0启用 1禁用)", required = true) |
||||||
|
String isDisable; |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
package com.huoran.iasf.vo.req; |
||||||
|
|
||||||
|
import io.swagger.annotations.ApiParam; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
@Data |
||||||
|
public class ArticleTopOperation { |
||||||
|
@ApiParam(name = "isTop", value = "是否置顶(默认为0 不置顶 1为置顶)", required = true) |
||||||
|
Integer isTop; |
||||||
|
@ApiParam(name = "articleId", value = "文章Id", required = true) |
||||||
|
Integer articleId; |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package com.huoran.iasf.vo.req; |
||||||
|
|
||||||
|
import io.swagger.annotations.ApiParam; |
||||||
|
import lombok.Data; |
||||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||||
|
@Data |
||||||
|
public class CheckForHeavy { |
||||||
|
|
||||||
|
@ApiParam(name = "siteId", value = "站点id", required = true) |
||||||
|
Integer siteId; |
||||||
|
@ApiParam(name = "classificationName", value = "分类名称", required = true) |
||||||
|
String classificationName; |
||||||
|
@ApiParam(name = "classificationId", value = "分类id(新增不传,编辑传)", required = false) |
||||||
|
Integer classificationId; |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package com.huoran.iasf.vo.req; |
||||||
|
|
||||||
|
import io.swagger.annotations.ApiParam; |
||||||
|
import lombok.Data; |
||||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||||
|
|
||||||
|
@Data |
||||||
|
public class LabelCheckForHeavy { |
||||||
|
|
||||||
|
@ApiParam(name = "siteId", value = "站点id", required = true) |
||||||
|
Integer siteId; |
||||||
|
@ApiParam(name = "labelName", value = "标签名称", required = true) |
||||||
|
String labelName; |
||||||
|
@ApiParam(name = "labelId", value = "标签id(新增不传,编辑传)", required = false) |
||||||
|
Integer labelId; |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
package com.huoran.iasf.vo.req; |
||||||
|
|
||||||
|
import io.swagger.annotations.ApiParam; |
||||||
|
import lombok.Data; |
||||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||||
|
|
||||||
|
@Data |
||||||
|
public class OneLevelChecksThemAll { |
||||||
|
|
||||||
|
@ApiParam(name = "id", value = "栏目id", required = true) |
||||||
|
Integer id; |
||||||
|
|
||||||
|
@ApiParam(name = "isSort", value = "判断是否为排序接口调用(1为排序接口调用 0我栏目管理列表调用)", required = true) |
||||||
|
Integer isSort; |
||||||
|
|
||||||
|
@ApiParam(name = "ids", value = "主键", required = true) |
||||||
|
Integer siteId; |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
package com.huoran.iasf.vo.req; |
||||||
|
|
||||||
|
import io.swagger.annotations.ApiParam; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
@Data |
||||||
|
public class SubLevelColumnsUnderALevel { |
||||||
|
|
||||||
|
@ApiParam(name = "id", value = "id", required = true) |
||||||
|
Integer id; |
||||||
|
@ApiParam(name = "siteId", value = "站点id", required = true) |
||||||
|
Integer siteId; |
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
{ |
||||||
|
"groups": [ |
||||||
|
{ |
||||||
|
"name": "file", |
||||||
|
"type": "com.huoran.iasf.common.config.FileUploadProperties", |
||||||
|
"sourceType": "com.huoran.iasf.common.config.FileUploadProperties" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "rsa.encrypt", |
||||||
|
"type": "com.huoran.iasf.common.config.SecretKeyConfig", |
||||||
|
"sourceType": "com.huoran.iasf.common.config.SecretKeyConfig" |
||||||
|
} |
||||||
|
], |
||||||
|
"properties": [ |
||||||
|
{ |
||||||
|
"name": "file.ip", |
||||||
|
"type": "java.lang.String", |
||||||
|
"sourceType": "com.huoran.iasf.common.config.FileUploadProperties" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "file.path", |
||||||
|
"type": "java.lang.String", |
||||||
|
"sourceType": "com.huoran.iasf.common.config.FileUploadProperties" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "file.url", |
||||||
|
"type": "java.lang.String", |
||||||
|
"sourceType": "com.huoran.iasf.common.config.FileUploadProperties" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "rsa.encrypt.charset", |
||||||
|
"type": "java.lang.String", |
||||||
|
"sourceType": "com.huoran.iasf.common.config.SecretKeyConfig", |
||||||
|
"defaultValue": "UTF-8" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "rsa.encrypt.open", |
||||||
|
"type": "java.lang.Boolean", |
||||||
|
"sourceType": "com.huoran.iasf.common.config.SecretKeyConfig", |
||||||
|
"defaultValue": true |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "rsa.encrypt.private-key", |
||||||
|
"type": "java.lang.String", |
||||||
|
"sourceType": "com.huoran.iasf.common.config.SecretKeyConfig" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "rsa.encrypt.public-key", |
||||||
|
"type": "java.lang.String", |
||||||
|
"sourceType": "com.huoran.iasf.common.config.SecretKeyConfig" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "rsa.encrypt.show-log", |
||||||
|
"type": "java.lang.Boolean", |
||||||
|
"sourceType": "com.huoran.iasf.common.config.SecretKeyConfig", |
||||||
|
"defaultValue": false |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "rsa.encrypt.timestamp-check", |
||||||
|
"type": "java.lang.Boolean", |
||||||
|
"description": "请求数据时间戳校验时间差 超过指定时间的数据认定为伪造", |
||||||
|
"sourceType": "com.huoran.iasf.common.config.SecretKeyConfig", |
||||||
|
"defaultValue": false |
||||||
|
} |
||||||
|
], |
||||||
|
"hints": [] |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
# 开发环境配置 |
||||||
|
spring: |
||||||
|
datasource: |
||||||
|
dynamic: |
||||||
|
primary: master #设置默认的数据源或者数据源组,默认值即为master |
||||||
|
datasource: |
||||||
|
master: |
||||||
|
username: root |
||||||
|
password: 123456 |
||||||
|
# password: iasf#2022 |
||||||
|
# password: HuoRan@2021 |
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver |
||||||
|
# url: jdbc:mysql://127.0.0.1:3306/iasf?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8 |
||||||
|
url: jdbc:mysql://192.168.31.136:3306/iasf?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8 |
||||||
|
# url: jdbc:mysql://139.9.47.170:3306/iasf?serverTimezone=GMT%2B8 |
||||||
|
cache: |
||||||
|
type: redis |
||||||
|
redis: |
||||||
|
host: 127.0.0.1 # Redis服务器地址 |
||||||
|
database: 0 # Redis数据库索引(默认为0) |
||||||
|
port: 6379 # Redis服务器连接端口 |
||||||
|
password: # Redis服务器连接密码(默认为空) |
||||||
|
jedis: |
||||||
|
pool: |
||||||
|
max-active: 8 # 连接池最大连接数(使用负值表示没有限制) |
||||||
|
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) |
||||||
|
max-idle: 8 # 连接池中的最大空闲连接 |
||||||
|
min-idle: 0 # 连接池中的最小空闲连接 |
||||||
|
timeout: 3000ms # 连接超时时间(毫秒) |
||||||
|
|
||||||
|
singleServerConfig: |
||||||
|
address: "redis://127.0.0.1:6379" |
||||||
|
password: |
||||||
|
|
||||||
|
file: |
||||||
|
#文件上传目录 绝对路径 末尾请加 / windows |
||||||
|
path: C:/files/ |
||||||
|
#文件预览url |
||||||
|
url: /iasf/sysFiles/preview/ |
||||||
|
# ip: http://10.10.11.7 |
||||||
|
ip: https://new.iasf.ac.cn |
||||||
|
#knife4j: |
||||||
|
# production: true #生成环境禁用查看文档 |
||||||
|
|
||||||
|
#本地开启 |
||||||
|
# url: :10000/iasf/sysFiles/preview/ |
@ -0,0 +1,39 @@ |
|||||||
|
# 生产环境配置 |
||||||
|
spring: |
||||||
|
datasource: |
||||||
|
dynamic: |
||||||
|
primary: master #设置默认的数据源或者数据源组,默认值即为master |
||||||
|
datasource: |
||||||
|
master: |
||||||
|
username: root |
||||||
|
password: HuoRan@2021 |
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver |
||||||
|
url: jdbc:mysql://139.9.47.170:3306/tmp_iasf?serverTimezone=GMT%2B8 |
||||||
|
cache: |
||||||
|
type: redis |
||||||
|
redis: |
||||||
|
host: 127.0.0.1 # Redis服务器地址 |
||||||
|
database: 1 # Redis数据库索引(默认为0) |
||||||
|
port: 6379 # Redis服务器连接端口 |
||||||
|
password: HuoRan@2021 # Redis服务器连接密码(默认为空) |
||||||
|
jedis: |
||||||
|
pool: |
||||||
|
max-active: 8 # 连接池最大连接数(使用负值表示没有限制) |
||||||
|
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) |
||||||
|
max-idle: 8 # 连接池中的最大空闲连接 |
||||||
|
min-idle: 0 # 连接池中的最小空闲连接 |
||||||
|
timeout: 3000ms # 连接超时时间(毫秒) |
||||||
|
|
||||||
|
singleServerConfig: |
||||||
|
address: "redis://127.0.0.1:6379" |
||||||
|
password: HuoRan@2021 |
||||||
|
|
||||||
|
file: |
||||||
|
#文件上传目录 绝对路径 末尾请加 / linux |
||||||
|
path: /usr/local/huoran/tmp_website/files/ |
||||||
|
#文件预览url |
||||||
|
url: /iasf/sysFiles/preview/ |
||||||
|
ip: http://139.159.254.212 |
||||||
|
|
||||||
|
knife4j: |
||||||
|
production: true #生成环境禁用查看文档 |
@ -0,0 +1,30 @@ |
|||||||
|
# 开发环境配置 |
||||||
|
spring: |
||||||
|
datasource: |
||||||
|
dynamic: |
||||||
|
primary: master #设置默认的数据源或者数据源组,默认值即为master |
||||||
|
datasource: |
||||||
|
master: |
||||||
|
username: root |
||||||
|
password: HuoRan@2021 |
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver |
||||||
|
url: jdbc:mysql://139.9.47.170:3306/iasf?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8 |
||||||
|
redis: |
||||||
|
host: localhost # Redis服务器地址 |
||||||
|
database: 0 # Redis数据库索引(默认为0) |
||||||
|
port: 6379 # Redis服务器连接端口 |
||||||
|
password: # Redis服务器连接密码(默认为空) |
||||||
|
jedis: |
||||||
|
pool: |
||||||
|
max-active: 8 # 连接池最大连接数(使用负值表示没有限制) |
||||||
|
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) |
||||||
|
max-idle: 8 # 连接池中的最大空闲连接 |
||||||
|
min-idle: 0 # 连接池中的最小空闲连接 |
||||||
|
timeout: 3000ms # 连接超时时间(毫秒 |
||||||
|
|
||||||
|
file: |
||||||
|
#文件上传目录 绝对路径 末尾请加 / |
||||||
|
path: D:/files/ #windows |
||||||
|
#path: /data/files/ #linux |
||||||
|
#文件预览、下载的url, 末尾请勿加 / |
||||||
|
url: :10000/iasf/sysFiles/preview/ |
@ -0,0 +1,59 @@ |
|||||||
|
# 端口 |
||||||
|
server: |
||||||
|
port: 10000 |
||||||
|
servlet: |
||||||
|
context-path: /iasf |
||||||
|
|
||||||
|
rsa: |
||||||
|
encrypt: |
||||||
|
timestampCheck: false #是否开启超过指定时间的数据认定为伪造 |
||||||
|
open: true # 是否开启加密 true or false |
||||||
|
showLog: true # 是否打印加解密log true or false |
||||||
|
publicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA08Nz0zscnWtddmaNylIPt9v5ZO6U6pYyGochRrbpI+ocwoyV4E1uUu3J9/mmR8pyMBcYzE5KkBytlaiLnd6dMqo4R60aihN/TqfuI/03LzgAS/egT/Q4VB9yZSyZCmJhrgTtSX5kxotAbewp0gqsWpi+6BUYDuiwJ0WNlhDVV4FOQIppmvHh0RqYDhjiPNAuy7fEtytT+IY4rxm6LggvmNtIq5k2oLbDxEeI1GOyFHT6sLGMkmBLmHu7JYcrlyUGyGWsxh8hVame1zQsScivrZu757BTGhN4xObTivIdAbR7uFeeX4lp0X1JNtIe9TwB/aZzKJjZMPXeV7BJ01g3MQIDAQAB |
||||||
|
privateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDTw3PTOxyda112Zo3KUg+32/lk7pTqljIahyFGtukj6hzCjJXgTW5S7cn3+aZHynIwFxjMTkqQHK2VqIud3p0yqjhHrRqKE39Op+4j/TcvOABL96BP9DhUH3JlLJkKYmGuBO1JfmTGi0Bt7CnSCqxamL7oFRgO6LAnRY2WENVXgU5Aimma8eHRGpgOGOI80C7Lt8S3K1P4hjivGbouCC+Y20irmTagtsPER4jUY7IUdPqwsYySYEuYe7slhyuXJQbIZazGHyFVqZ7XNCxJyK+tm7vnsFMaE3jE5tOK8h0BtHu4V55fiWnRfUk20h71PAH9pnMomNkw9d5XsEnTWDcxAgMBAAECggEAUm5n3NbKycBsblV3ZkVRVwmq6A4zK6nxsP/fBS7YTCGqtlSRVvHtOxzTHNMyVgnJL00eWxEy1yxCqdolFvv8ByfZppUMmqkCSnT2L043OAs9mlS3M8hmUOC44AdfP3qSeXHziENKKTs1hlSC5v8+njmNPrxPVCZhw7fAaKT+1wOKE353QTNxacNua+dDx8zVO0xEznW+FKnYZ+ft2rHkiu1NkPRrWCpGHXZLXINT2FoQ7ECHkQUjD5IoRg2lvXNvjQPhs9BwnNsl3ODe/8PWbB0Lgtg9dLEmivyaNpTx/2Nl0QmFflIfp0rZs4SMnsJK56hQ8d5uhYbcpnn/gSbcAQKBgQD1gN/5oBxJAw2MVv3N8VcC/CWPHI4Er9vEVgrQSrO9QYBHSRX9/aoHmI4iK5opjHq6LYEt9JoGSdMPbRL2o16pkyZchuB/7Q5no9AD7iDSvvvt7qNqo2qkWpPA9pjodoWQaLAmC6M39ypNo3aSvrkuN11tOmU5bnaa94bofjoFcQKBgQDc0UgWiD0uTXSYCi1/GHCUuWi5X/HtsMS8Mz5SIln7x+X2rM0OECSQqYR4AGUZv81xh5mJetYDwJUvQXYGdaon8DP08VKD7uVEELF6SVf7woGVUSYxZdMss21cqksM3MXhyJ8QxO+eJSjGqwHf5AkB0KtMfnMKZqJIfXJsoVltwQKBgQDM3skJpSU1gIizznxqebWk1gn5zVhubNq2kx7fBxfLHXgRBNqHZEGZqSMjPMOfXI2mBAdC9FX8XWr1+o3SqC580EE5AY0i9A4LStZyESvu8lWGDpjsioaZtMSMSLz9cLqw8cvdU+TW9TmmJHz0pJggCy+50Ptb2+S6GUnJhlyg4QKBgDgiK4Uu1P60SfNsguxQNi5Yg7q8HTAjQ5/kFu+iM+XBh0AR5X6xs9niff5Te1/0VjGKGwnL5CPIDSSaK3qw5rSIZ2zY+/T2AeovpC5F/svNQkvG+UKNdAVlB2QLFlEKvnMLIQSOS6uUHq2CQ1O7EF8ZwLINYwk91fs/iJr82VMBAoGAEq3LN/LmOlB1OL6MaTTCEkvQq/wROt8poeLebycFcmZrsovR3MQKYuoY7IEjRw+ZvOauCJNM7mCpmeUVWAc3TPgWeQMzGALdb1X5u9xK8eq9WTutlSS/OSNGIYRJuSpO9efDdfoMHuR2Mleibs1yvxD4A2CXC10bSHE5huM07rY= |
||||||
|
spring: |
||||||
|
profiles: |
||||||
|
active: dev |
||||||
|
mvc: |
||||||
|
throw-exception-if-no-handler-found: true |
||||||
|
resources: |
||||||
|
add-mappings: false |
||||||
|
application: |
||||||
|
name: iasf |
||||||
|
jackson: |
||||||
|
date-format: yyyy-MM-dd HH:mm:ss |
||||||
|
time-zone: GMT+8 |
||||||
|
# 解决API 成批分配问题 |
||||||
|
serialization: |
||||||
|
# 某些类对象无法序列化的时候,是否报错 |
||||||
|
fail_on_empty_beans: true |
||||||
|
deserialization: |
||||||
|
# json对象中有不存在的属性时候,是否报错 |
||||||
|
fail_on_unknown_properties: true |
||||||
|
# 文件大小限制 |
||||||
|
servlet: |
||||||
|
multipart: |
||||||
|
max-file-size: 100MB |
||||||
|
max-request-size: 100MB |
||||||
|
# redis token信息 |
||||||
|
redis: |
||||||
|
key: |
||||||
|
prefix: |
||||||
|
userToken: "user:token:" |
||||||
|
passwordError: "user:password:error:" |
||||||
|
permissionRefresh: "user:token:permissionRefresh:" |
||||||
|
expire: |
||||||
|
userToken: 86400 # 1天 7*24*3600 |
||||||
|
passwordError: 360000 # 一个小时 |
||||||
|
permissionRefresh: 86400 # 1天 7*24*3600 |
||||||
|
allowMultipleLogin: true # 允许多处登陆 |
||||||
|
|
||||||
|
mybatis-plus: |
||||||
|
configuration: |
||||||
|
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl |
||||||
|
mapper-locations: classpath*:com/huoran/iasf/mapper/xml/*.xml |
||||||
|
global-config: |
||||||
|
db-config: |
||||||
|
logic-delete-value: 0 |
||||||
|
logic-not-delete-value: 1 |
||||||
|
logic-delete-field: deleted |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue