REM:
1. 增加接口请求参数校验异常日志打印
This commit is contained in:
HuangXin 2020-10-14 14:12:20 +08:00
parent 4056250729
commit f7dee16f53
9 changed files with 286 additions and 18 deletions

View File

@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
@ -21,6 +22,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableAspectJAutoProxy @EnableAspectJAutoProxy
@EnableTransactionManagement @EnableTransactionManagement
@EnableEncryptableProperties @EnableEncryptableProperties
@ServletComponentScan
@MapperScan(basePackages = {"com.dispose.mapper"}) @MapperScan(basePackages = {"com.dispose.mapper"})
@Slf4j @Slf4j
public class PhoenixBootApplication { public class PhoenixBootApplication {

View File

@ -5,6 +5,11 @@ import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressSeqRange; import inet.ipaddr.IPAddressSeqRange;
import inet.ipaddr.IPAddressString; import inet.ipaddr.IPAddressString;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -169,4 +174,25 @@ public class Helper {
return false; return false;
} }
/**
* Input stream 2 string string.
*
* @param inputStream the input stream
* @return the string
*/
public static String inputStream2String(InputStream inputStream) {
StringBuilder sb = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.defaultCharset()))) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return sb.toString();
}
} }

View File

@ -88,7 +88,7 @@ public class RestfulLog {
} }
if (requestMap.containsKey(attributes.hashCode())) { if (requestMap.containsKey(attributes.hashCode())) {
log.debug("Interface [{}] request <{}> from {}, token = <{}>\n" + log.info("Interface [{}] request <{}> from {}, token = <{}>\n" +
"+++ Request: {}\n" + "+++ Request: {}\n" +
"--- Response: {}", "--- Response: {}",
reqType, reqPath, reqIp, reqToken, requestMap.get(attributes.hashCode()), reqType, reqPath, reqIp, reqToken, requestMap.get(attributes.hashCode()),
@ -118,7 +118,7 @@ public class RestfulLog {
} }
if (requestMap.containsKey(attributes.hashCode())) { if (requestMap.containsKey(attributes.hashCode())) {
log.debug("Interface [{}] request <{}> from {}, token = <{}>\n" + log.info("Interface [{}] request <{}> from {}, token = <{}>\n" +
"+++ Request: {}\n" + "+++ Request: {}\n" +
"--- Response Exception: {}", "--- Response Exception: {}",
reqType, reqPath, reqIp, reqToken, requestMap.get(attributes.hashCode()), ex.getMessage()); reqType, reqPath, reqIp, reqToken, requestMap.get(attributes.hashCode()), ex.getMessage());

View File

@ -1,6 +1,8 @@
package com.dispose.exception; package com.dispose.exception;
import com.dispose.common.ConstValue;
import com.dispose.common.ErrorCode; import com.dispose.common.ErrorCode;
import com.dispose.common.Helper;
import com.dispose.pojo.dto.protocol.base.BaseRespStatus; import com.dispose.pojo.dto.protocol.base.BaseRespStatus;
import com.dispose.pojo.dto.protocol.base.ProtocolRespDTO; import com.dispose.pojo.dto.protocol.base.ProtocolRespDTO;
import com.dispose.security.exception.SecurityProtocolException; import com.dispose.security.exception.SecurityProtocolException;
@ -10,6 +12,7 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -23,26 +26,44 @@ import java.util.concurrent.atomic.AtomicInteger;
@ControllerAdvice @ControllerAdvice
@Slf4j @Slf4j
public class GlobalExceptionHandler { public class GlobalExceptionHandler {
/** /**
* Handle exception protocol resp dto. * Handle exception protocol resp dto.
* *
* @param rsp the rsp * @param rsp the rsp
* @param req the req
* @param ex the ex * @param ex the ex
* @return the protocol resp dto * @return the protocol resp dto
*/ */
@ExceptionHandler(MethodArgumentNotValidException.class) @ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody @ResponseBody
public ProtocolRespDTO<BaseRespStatus> handleException(HttpServletResponse rsp, public ProtocolRespDTO<BaseRespStatus> handleException(HttpServletResponse rsp,
HttpServletRequest req,
MethodArgumentNotValidException ex) { MethodArgumentNotValidException ex) {
try {
String reqType = req.getMethod();
String reqPath = req.getRequestURI();
String reqIp = req.getRemoteAddr();
String reqToken = req.getHeader("Authorization");
if (reqToken != null && reqToken.length() > 0) {
reqToken = reqToken.replace(ConstValue.STRING_HTTP_AUTH_HEAD, "");
}
log.info("Interface [{}] request <{}> from {}, token = <{}>\n" +
"+++ Request: {}\n" +
"--- Verify params failed: {}",
reqType, reqPath, reqIp, reqToken, Helper.inputStream2String(req.getInputStream()),
ex.getMessage());
} catch (Exception ignored) {
}
log.debug("Argument Exception: ", ex); log.debug("Argument Exception: ", ex);
List<String> exMsg = new ArrayList<>(); List<String> exMsg = new ArrayList<>();
AtomicInteger idx = new AtomicInteger(); AtomicInteger idx = new AtomicInteger();
ex.getBindingResult() ex.getBindingResult()
.getAllErrors() .getAllErrors()
.forEach(v -> exMsg.add(idx.getAndIncrement() + ": " + v.getDefaultMessage())); .forEach(v -> exMsg.add(idx.getAndIncrement() + ": " + v.getDefaultMessage()));
rsp.setStatus(ErrorCode.ERR_PARAMEXCEPTION.getHttpCode()); rsp.setStatus(ErrorCode.ERR_PARAMEXCEPTION.getHttpCode());
@ -51,6 +72,54 @@ public class GlobalExceptionHandler {
exMsg.toArray(new String[0])); exMsg.toArray(new String[0]));
} }
/**
* Handle exception protocol resp dto.
*
* @param rsp the rsp
* @param req the req
* @param ex the ex
* @return the protocol resp dto
*/
@ExceptionHandler(SecurityProtocolException.class)
@ResponseBody
public ProtocolRespDTO<BaseRespStatus> handleException(HttpServletResponse rsp,
HttpServletRequest req,
SecurityProtocolException ex) {
try {
String reqType = req.getMethod();
String reqPath = req.getRequestURI();
String reqIp = req.getRemoteAddr();
String reqToken = req.getHeader("Authorization");
if (reqToken != null && reqToken.length() > 0) {
reqToken = reqToken.replace(ConstValue.STRING_HTTP_AUTH_HEAD, "");
}
log.info("Interface [{}] request <{}> from {}, token = <{}>\n" +
"+++ Request: {}\n" +
"--- Verify params failed: {}",
reqType, reqPath, reqIp, reqToken, Helper.inputStream2String(req.getInputStream()),
ex.getMessage());
} catch (Exception ignored) {
}
log.debug("SecurityProtocolException Exception: ", ex);
List<String> errMeg = new ArrayList<>();
rsp.setStatus(ErrorCode.ERR_PARAMEXCEPTION.getHttpCode());
errMeg.add(ex.getErr().getMsg());
if (ex.getDescription() != null && ex.getDescription().length() > 0) {
errMeg.add(ex.getDescription());
}
if (ex.getMessage() != null && ex.getMessage().length() > 0) {
errMeg.add(ex.getMessage());
}
return ProtocolRespDTO.result(ErrorCode.ERR_PARAMEXCEPTION,
ErrorCode.ERR_PARAMEXCEPTION.getHttpCode(),
errMeg.toArray(new String[0]));
}
/** /**
* Handle exception protocol resp dto. * Handle exception protocol resp dto.
* *
@ -61,22 +130,23 @@ public class GlobalExceptionHandler {
@ExceptionHandler(Throwable.class) @ExceptionHandler(Throwable.class)
@ResponseBody @ResponseBody
public ProtocolRespDTO<BaseRespStatus> handleException(HttpServletResponse rsp, Throwable ex) { public ProtocolRespDTO<BaseRespStatus> handleException(HttpServletResponse rsp, Throwable ex) {
List<String> errMeg = new ArrayList<>();
log.debug("Throwable Exception: ", ex); log.debug("Throwable Exception: ", ex);
rsp.setStatus(ErrorCode.ERR_PARAMEXCEPTION.getHttpCode()); rsp.setStatus(ErrorCode.ERR_PARAMEXCEPTION.getHttpCode());
if (ex instanceof SecurityProtocolException) { if (ex instanceof ControllerNotSupportException) {
return ProtocolRespDTO.result(ErrorCode.ERR_PARAMEXCEPTION, errMeg.add(((ControllerNotSupportException) ex).getErr().getMsg());
ErrorCode.ERR_PARAMEXCEPTION.getHttpCode(),
new String[]{((SecurityProtocolException) ex).getErr().getMsg(), ex.getMessage()});
} else if (ex instanceof ControllerNotSupportException) {
return ProtocolRespDTO.result(ErrorCode.ERR_PARAMEXCEPTION,
ErrorCode.ERR_PARAMEXCEPTION.getHttpCode(),
new String[]{((ControllerNotSupportException) ex).getErr().getMsg(), ex.getMessage()});
} else { } else {
return ProtocolRespDTO.result(ErrorCode.ERR_PARAMEXCEPTION, errMeg.add(ErrorCode.ERR_PARAMEXCEPTION.getMsg());
ErrorCode.ERR_PARAMEXCEPTION.getHttpCode(),
new String[]{ErrorCode.ERR_PARAMEXCEPTION.getMsg(), ex.getMessage()});
} }
if (ex.getMessage() != null && ex.getMessage().length() > 0) {
errMeg.add(ex.getMessage());
}
return ProtocolRespDTO.result(ErrorCode.ERR_PARAMEXCEPTION,
ErrorCode.ERR_PARAMEXCEPTION.getHttpCode(),
errMeg.toArray(new String[0]));
} }
} }

View File

@ -0,0 +1,106 @@
package com.dispose.interceptor;
import com.dispose.common.Helper;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
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.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
/**
* The type Request body cache wrapper.
*
* @author <huangxin@cmhi.chinamoblie.com>
*/
public class RequestBodyCacheWrapper extends HttpServletRequestWrapper {
/**
* The Body.
*/
private final byte[] body;
/**
* Instantiates a new Request body cache wrapper.
*
* @param request the request
*/
public RequestBodyCacheWrapper(HttpServletRequest request) {
super(request);
// 将body数据存储起来
String bodyStr = getBodyString(request);
body = bodyStr.getBytes(Charset.defaultCharset());
}
/**
* Gets body string.
*
* @param request the request
* @return the body string
*/
public String getBodyString(final ServletRequest request) {
try {
return Helper.inputStream2String(request.getInputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Gets body string.
*
* @return the body string
*/
public String getBodyString() {
final InputStream inputStream = new ByteArrayInputStream(body);
return Helper.inputStream2String(inputStream);
}
/**
* Gets reader.
*
* @return the reader
*/
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
/**
* Gets input stream.
*
* @return the input stream
*/
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream inputStream = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() {
return inputStream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}

View File

@ -0,0 +1,51 @@
package com.dispose.interceptor;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* The type Request body filter.
*
* @author <huangxin@cmhi.chinamoblie.com>
*/
@WebFilter(filterName = "RequestBodyFilter", urlPatterns = "/*")
public class RequestBodyFilter implements Filter {
/**
* Init.
*
* @param filterConfig the filter config
*/
@Override
public void init(FilterConfig filterConfig) {
}
/**
* Destroy.
*/
@Override
public void destroy() {
}
/**
* Do filter.
*
* @param request the request
* @param response the response
* @param filterChain the filter chain
* @throws IOException the io exception
* @throws ServletException the servlet exception
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
ServletRequest requestWrapper = new RequestBodyCacheWrapper((HttpServletRequest) request);
filterChain.doFilter(requestWrapper, response);
}
}

View File

@ -41,8 +41,8 @@ public class BaseProtocolDTO<T> {
allowableValues = "0, 1, 2", allowableValues = "0, 1, 2",
example = "0") example = "0")
@NotNull(message = "cryptoType 字段不能为空", groups = ValidGroups.ProtocolCommonValid.class) @NotNull(message = "cryptoType 字段不能为空", groups = ValidGroups.ProtocolCommonValid.class)
@Range(min = 0, max = 2, @Range(min = 0, max = 4,
message = "cryptoType 字段取值为 [0, 2]" message = "cryptoType 字段取值为 [0, 4]"
, groups = ValidGroups.ProtocolCommonValid.class) , groups = ValidGroups.ProtocolCommonValid.class)
private Integer cryptoType; private Integer cryptoType;

View File

@ -17,6 +17,8 @@ public class SecurityProtocolException extends RuntimeException {
*/ */
private ErrorCode err; private ErrorCode err;
private String description;
/** /**
* Instantiates a new Security exception. * Instantiates a new Security exception.
* *
@ -25,5 +27,12 @@ public class SecurityProtocolException extends RuntimeException {
public SecurityProtocolException(ErrorCode err) { public SecurityProtocolException(ErrorCode err) {
super(); super();
this.err = err; this.err = err;
this.description = null;
}
public SecurityProtocolException(ErrorCode err, String readme) {
super();
this.err = err;
this.description = readme;
} }
} }

View File

@ -56,6 +56,10 @@ public class ProtocolSecurityServiceImpl implements ProtocolSecurityService {
return ciphertext; return ciphertext;
} }
if (cryptoType > ProtoCryptoType.CRYPTO_AES256.getCode() || cryptoType < ProtoCryptoType.CRYPTO_NONE.getCode()) {
throw new SecurityProtocolException(ErrorCode.ERR_PARAMS, "cryptoType 字段取值为 [0, 4]");
}
// 反序列化为对象处理 // 反序列化为对象处理
ProtocolReqDTO<String> proReq = objectMapper ProtocolReqDTO<String> proReq = objectMapper
.readValue(ciphertext, new TypeReference<ProtocolReqDTO<String>>() { .readValue(ciphertext, new TypeReference<ProtocolReqDTO<String>>() {