diff --git a/common/pom.xml b/common/pom.xml index b43adc5..f97fd06 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -57,6 +57,24 @@ spring-kafka 2.7.6 + + org.springframework + spring-webmvc + 5.2.9.RELEASE + compile + + + org.apache.tomcat.embed + tomcat-embed-core + 9.0.38 + compile + + + org.apache.tomcat.embed + tomcat-embed-core + 9.0.38 + compile + \ No newline at end of file diff --git a/common/src/main/java/cn/org/gitlink/notification/common/exceptions/ForbiddenException.java b/common/src/main/java/cn/org/gitlink/notification/common/exceptions/ForbiddenException.java new file mode 100644 index 0000000..e8d4bc6 --- /dev/null +++ b/common/src/main/java/cn/org/gitlink/notification/common/exceptions/ForbiddenException.java @@ -0,0 +1,12 @@ +package cn.org.gitlink.notification.common.exceptions; + +/** + * 网关拦截非白名单用户异常类 + * @author zengwei + * @date 2021/09/07 + * */ +public class ForbiddenException extends Exception{ + public ForbiddenException(String message) { + super(message); + } +} diff --git a/common/src/main/java/cn/org/gitlink/notification/common/interceptor/ExceptionInterceptor.java b/common/src/main/java/cn/org/gitlink/notification/common/interceptor/ExceptionInterceptor.java new file mode 100644 index 0000000..11fe313 --- /dev/null +++ b/common/src/main/java/cn/org/gitlink/notification/common/interceptor/ExceptionInterceptor.java @@ -0,0 +1,42 @@ +package cn.org.gitlink.notification.common.interceptor; + +import cn.org.gitlink.notification.common.exceptions.ForbiddenException; +import cn.org.gitlink.notification.common.response.DataPacketUtil; +import cn.org.gitlink.notification.common.response.ResponseData; +import cn.org.gitlink.notification.common.utils.CommonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import javax.servlet.http.HttpServletRequest; + +/** + * web请求异常全局处理类,在使用的模块内继承此类,然后加上ControllerAdvice注解,example: + * @ControllerAdvice + * public class ReaderExceptionInterceptor extends ExceptionInterceptor {} + * @author zengwei + * @date 2021/09/07 + * */ +public class ExceptionInterceptor { + private static final Logger logger = LoggerFactory.getLogger(ExceptionInterceptor.class); + private static String logTemplate = "request page url{}, error:{}"; + + @ResponseBody + @ResponseStatus(HttpStatus.OK) + @ExceptionHandler({ForbiddenException.class}) + public ResponseData handle(HttpServletRequest request, ForbiddenException e) { + logger.warn("非法求请, ip:{}", CommonUtils.getIPAddress(request)); + return DataPacketUtil.jsonFailResult(e.getMessage()); + } + + @ResponseBody + @ResponseStatus(HttpStatus.OK) + @ExceptionHandler({Exception.class}) + public ResponseData handle(HttpServletRequest request, Exception e) { + logger.error(logTemplate, request.getRequestURI(), e); + return DataPacketUtil.jsonFailResult("服务器异常,请联系管理员处理!", e); + } +} \ No newline at end of file diff --git a/common/src/main/java/cn/org/gitlink/notification/common/interceptor/GitLinkInterceptor.java b/common/src/main/java/cn/org/gitlink/notification/common/interceptor/GitLinkInterceptor.java new file mode 100644 index 0000000..3f4f94e --- /dev/null +++ b/common/src/main/java/cn/org/gitlink/notification/common/interceptor/GitLinkInterceptor.java @@ -0,0 +1,42 @@ +package cn.org.gitlink.notification.common.interceptor; + +import cn.org.gitlink.notification.common.exceptions.ForbiddenException; +import cn.org.gitlink.notification.common.utils.CommonUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * GitLink统一拦截类,example: + * @Configuration + * public class ReaderWebConfig implements WebMvcConfigurer { + * @Autowired + * private GitLinkInterceptor gitLinkInterceptor; + * @Override + * public void addInterceptors(InterceptorRegistry registry) { + * registry.addInterceptor(gitLinkInterceptor).addPathPatterns("/**"); + * } + * } + * + * @author zengwei + * @date 2021/09/07 + * */ +@Component +public class GitLinkInterceptor implements HandlerInterceptor { + @Value(value = "${white-list:''}") + private String whiteList; + @Override + public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception { + if (null == httpServletRequest || whiteList.contains("*")) { + return true; + } + + if (!whiteList.contains(CommonUtils.getIPAddress(httpServletRequest))) { + throw new ForbiddenException("没有权限访问,请向管理员申请访问权限!"); + } + return true; + } +} diff --git a/common/src/main/java/cn/org/gitlink/notification/common/response/DataPacketUtil.java b/common/src/main/java/cn/org/gitlink/notification/common/response/DataPacketUtil.java new file mode 100644 index 0000000..38b7dcf --- /dev/null +++ b/common/src/main/java/cn/org/gitlink/notification/common/response/DataPacketUtil.java @@ -0,0 +1,53 @@ +package cn.org.gitlink.notification.common.response; + + +import java.util.HashMap; +import java.util.List; + +public class DataPacketUtil +{ + public static final String RESULT_KEY_SUCCESS = "请求成功"; + public static final String RESULT_KEY_FAIL = "请求失败"; + public static final Integer SUCCESS_CODE = 1; + public static final Integer FAIL_CODE = 0; + public static final String NOT_FOUND_MESSAGE = "资源不存在"; + public static final String FORBIDDEN_MESSAGE = "您无权限进行此操作!"; + + public static ResponseData jsonResult(String msg, Integer code, Object data) + { + return new ResponseData(msg, code, data); + } + + public static ResponseData jsonSuccessResult() { + return jsonResult(RESULT_KEY_SUCCESS, SUCCESS_CODE, new HashMap<>()); + } + + public static ResponseData jsonSuccessResult(Object data) { + return jsonResult(RESULT_KEY_SUCCESS, SUCCESS_CODE, data); + } + + public static ResponseData jsonSuccessResult(String msg) { + return jsonResult(msg, SUCCESS_CODE, new HashMap<>()); + } + + public static ResponseData jsonSuccessResult(String msg, Object data) { + return jsonResult(msg, SUCCESS_CODE, data); + } + + public static ResponseData jsonFailResult() { + return jsonResult( RESULT_KEY_FAIL, FAIL_CODE, new HashMap<>()); + } + + public static ResponseData jsonFailResult(String msg) { + return jsonResult( msg, FAIL_CODE, new HashMap<>()); + } + + public static ResponseData jsonFailResult(Object data) { + return jsonResult( RESULT_KEY_FAIL, FAIL_CODE, data); + } + + public static ResponseData jsonFailResult(String msg, Object data) { + return jsonResult( msg, FAIL_CODE, data); + } +} + diff --git a/common/src/main/java/cn/org/gitlink/notification/common/response/PageData.java b/common/src/main/java/cn/org/gitlink/notification/common/response/PageData.java new file mode 100644 index 0000000..473cb4a --- /dev/null +++ b/common/src/main/java/cn/org/gitlink/notification/common/response/PageData.java @@ -0,0 +1,34 @@ +package cn.org.gitlink.notification.common.response; + +import java.io.Serializable; + +public class PageData implements Serializable { + private long total; + + private java.util.List rows; + + public PageData(long total, java.util.List rows) { + this.total = total; + this.rows = rows; + } + + public long getTotal() { + return this.total; + } + + public void setTotal(long total) { + this.total = total; + } + + public java.util.List getRows() { + return this.rows; + } + + public void setRows(java.util.List rows) { + this.rows = rows; + } + + public PageData() { + } +} + diff --git a/common/src/main/java/cn/org/gitlink/notification/common/response/ResponseData.java b/common/src/main/java/cn/org/gitlink/notification/common/response/ResponseData.java new file mode 100644 index 0000000..f51368a --- /dev/null +++ b/common/src/main/java/cn/org/gitlink/notification/common/response/ResponseData.java @@ -0,0 +1,65 @@ +package cn.org.gitlink.notification.common.response; + +import org.apache.kafka.common.protocol.types.Field; + +import java.io.Serializable; + +public class ResponseData implements Serializable { + + /** + * 响应状态 + */ + protected Integer code; + + /** + * 响应消息 + */ + protected String message; + + /** + * 响应数据 + */ + private T data; + + public void setMessage(String message) { + this.message = message; + } + + public void setCode(Integer code) { this.code = code; } + + public String toString() { + return "ResponseData(message=" + getMessage() + ", data=" + getData() + ")"; + } + + public String getMessage() { + return this.message; + } + + public Integer getCode() { return this.code; } + + + public ResponseData(T data) { + this.data = data; + } + + public ResponseData(String message) { + this.message = message; + } + + public ResponseData(String message, Integer code, T data) { + this.message = message; + this.code = code; + this.data = data; + } + + public T getData() { + return this.data; + } + + public void setData(T data) { + this.data = data; + } + + public ResponseData() { + } +} diff --git a/common/src/main/java/cn/org/gitlink/notification/common/utils/CommonUtils.java b/common/src/main/java/cn/org/gitlink/notification/common/utils/CommonUtils.java new file mode 100644 index 0000000..b52df68 --- /dev/null +++ b/common/src/main/java/cn/org/gitlink/notification/common/utils/CommonUtils.java @@ -0,0 +1,52 @@ +package cn.org.gitlink.notification.common.utils; + +import org.apache.commons.lang3.StringUtils; + +import javax.servlet.http.HttpServletRequest; + +/** + * 公共工具类 + * @author zengwei + * @date 2021/09/07 + * */ +public class CommonUtils { + + /** + * 根据request获取ip + * @author zengwei + * @data 2021/07/09 + * */ + public static String getIPAddress(HttpServletRequest request) { + String Xip = request.getHeader("X-Real-IP"); + String XFor = request.getHeader("X-Forwarded-For"); + if (StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) { + //多次反向代理后会有多个ip值,第一个ip才是真实ip + int index = XFor.indexOf(","); + if (index != -1) { + return XFor.substring(0,index); + } else { + return XFor; + } + } + XFor = Xip; + if (StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) { + return XFor; + } + if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) { + XFor = request.getHeader("Proxy-Client-IP"); + } + if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) { + XFor = request.getHeader("WL-Proxy-Client-IP"); + } + if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) { + XFor = request.getHeader("HTTP_CLIENT_IP"); + } + if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) { + XFor = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) { + XFor = request.getRemoteAddr(); + } + return XFor; + } +} diff --git a/pom.xml b/pom.xml index d89cbf9..32a8eb8 100644 --- a/pom.xml +++ b/pom.xml @@ -51,6 +51,16 @@ knife4j-spring-boot-starter 2.0.5 + + cn.hutool + hutool-all + 5.4.3 + + + org.apache.commons + commons-lang3 + 3.10 + \ No newline at end of file diff --git a/reader/src/main/java/cn/org/gitlink/notification/reader/config/ReaderExceptionInterceptor.java b/reader/src/main/java/cn/org/gitlink/notification/reader/config/ReaderExceptionInterceptor.java new file mode 100644 index 0000000..b8b5c36 --- /dev/null +++ b/reader/src/main/java/cn/org/gitlink/notification/reader/config/ReaderExceptionInterceptor.java @@ -0,0 +1,7 @@ +package cn.org.gitlink.notification.reader.config; + +import cn.org.gitlink.notification.common.interceptor.ExceptionInterceptor; +import org.springframework.web.bind.annotation.ControllerAdvice; + +@ControllerAdvice +public class ReaderExceptionInterceptor extends ExceptionInterceptor {} diff --git a/reader/src/main/java/cn/org/gitlink/notification/reader/config/ReaderWebConfig.java b/reader/src/main/java/cn/org/gitlink/notification/reader/config/ReaderWebConfig.java new file mode 100644 index 0000000..7ef08a2 --- /dev/null +++ b/reader/src/main/java/cn/org/gitlink/notification/reader/config/ReaderWebConfig.java @@ -0,0 +1,17 @@ +package cn.org.gitlink.notification.reader.config; + +import cn.org.gitlink.notification.common.interceptor.GitLinkInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class ReaderWebConfig implements WebMvcConfigurer { + @Autowired + private GitLinkInterceptor gitLinkInterceptor; + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(gitLinkInterceptor).addPathPatterns("/**"); + } +} diff --git a/reader/src/main/java/cn/org/gitlink/notification/reader/config/SwaggerConfig.java b/reader/src/main/java/cn/org/gitlink/notification/reader/config/SwaggerConfig.java index 71068a5..2ec6f20 100644 --- a/reader/src/main/java/cn/org/gitlink/notification/reader/config/SwaggerConfig.java +++ b/reader/src/main/java/cn/org/gitlink/notification/reader/config/SwaggerConfig.java @@ -16,14 +16,13 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 @EnableKnife4j -@Import({BeanValidatorPluginsConfiguration.class}) public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() - .apis(RequestHandlerSelectors.basePackage("com.gitlink.notification")).paths(PathSelectors.any()).build(); + .apis(RequestHandlerSelectors.basePackage("cn.org.gitlink.notification.reader")).paths(PathSelectors.any()).build(); } private ApiInfo apiInfo() { diff --git a/reader/src/main/java/cn/org/gitlink/notification/reader/controller/IndexController.java b/reader/src/main/java/cn/org/gitlink/notification/reader/controller/IndexController.java index 78461b4..b0fb217 100644 --- a/reader/src/main/java/cn/org/gitlink/notification/reader/controller/IndexController.java +++ b/reader/src/main/java/cn/org/gitlink/notification/reader/controller/IndexController.java @@ -1,5 +1,7 @@ package cn.org.gitlink.notification.reader.controller; +import cn.org.gitlink.notification.common.response.DataPacketUtil; +import cn.org.gitlink.notification.common.response.ResponseData; import cn.org.gitlink.notification.common.utils.RedisUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; @@ -10,8 +12,8 @@ public class IndexController { @Autowired private RedisUtil redisUtil; @GetMapping(value = "") - public String index() { + public ResponseData index() { redisUtil.set("hello", "Hello reader!"); - return redisUtil.get("hello").toString(); + return DataPacketUtil.jsonSuccessResult(redisUtil.get("hello").toString()); } } diff --git a/reader/src/main/resources/application.yml b/reader/src/main/resources/application.yml index 95e323d..079c435 100644 --- a/reader/src/main/resources/application.yml +++ b/reader/src/main/resources/application.yml @@ -1,6 +1,9 @@ server: port: 8080 +logging: + config: classpath:logback.xml + spring: redis: # Redis数据库索引(默认为0) @@ -22,3 +25,6 @@ spring: min-idle: 0 # 连接超时时间(毫秒) timeout: 1000 + +#ip白名单列表,多个ip用逗号隔开,允许所有用*号 +white-list: '*' \ No newline at end of file diff --git a/reader/src/main/resources/logback.xml b/reader/src/main/resources/logback.xml new file mode 100644 index 0000000..0d01ff2 --- /dev/null +++ b/reader/src/main/resources/logback.xml @@ -0,0 +1,29 @@ + + + + logback + + + + + %d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n + + + + + ${log.path} + + ${log.path}.%d{yyyy-MM-dd}.zip + + + %date %level [%thread] %logger{36} [%file : %line] %msg%n + + + + + + + + + + \ No newline at end of file diff --git a/writer/src/main/java/cn/org/gitlink/notification/writer/config/SwaggerConfig.java b/writer/src/main/java/cn/org/gitlink/notification/writer/config/SwaggerConfig.java index 922a2b5..2ae0ae2 100644 --- a/writer/src/main/java/cn/org/gitlink/notification/writer/config/SwaggerConfig.java +++ b/writer/src/main/java/cn/org/gitlink/notification/writer/config/SwaggerConfig.java @@ -16,14 +16,13 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 @EnableKnife4j -@Import({BeanValidatorPluginsConfiguration.class}) public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() - .apis(RequestHandlerSelectors.basePackage("com.gitlink.notification")).paths(PathSelectors.any()).build(); + .apis(RequestHandlerSelectors.basePackage("cn.org.gitlink.notification.writer")).paths(PathSelectors.any()).build(); } private ApiInfo apiInfo() { diff --git a/writer/src/main/java/cn/org/gitlink/notification/writer/config/WriterExceptionInterceptor.java b/writer/src/main/java/cn/org/gitlink/notification/writer/config/WriterExceptionInterceptor.java new file mode 100644 index 0000000..ea9b979 --- /dev/null +++ b/writer/src/main/java/cn/org/gitlink/notification/writer/config/WriterExceptionInterceptor.java @@ -0,0 +1,7 @@ +package cn.org.gitlink.notification.writer.config; + +import cn.org.gitlink.notification.common.interceptor.ExceptionInterceptor; +import org.springframework.web.bind.annotation.ControllerAdvice; + +@ControllerAdvice +public class WriterExceptionInterceptor extends ExceptionInterceptor {} diff --git a/writer/src/main/java/cn/org/gitlink/notification/writer/config/WriterWebConfig.java b/writer/src/main/java/cn/org/gitlink/notification/writer/config/WriterWebConfig.java new file mode 100644 index 0000000..1d066e6 --- /dev/null +++ b/writer/src/main/java/cn/org/gitlink/notification/writer/config/WriterWebConfig.java @@ -0,0 +1,17 @@ +package cn.org.gitlink.notification.writer.config; + +import cn.org.gitlink.notification.common.interceptor.GitLinkInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WriterWebConfig implements WebMvcConfigurer { + @Autowired + private GitLinkInterceptor gitLinkInterceptor; + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(gitLinkInterceptor).addPathPatterns("/**"); + } +} diff --git a/writer/src/main/resources/application.yml b/writer/src/main/resources/application.yml index 29d2c7d..1915669 100644 --- a/writer/src/main/resources/application.yml +++ b/writer/src/main/resources/application.yml @@ -1,6 +1,9 @@ server: port: 8082 +logging: + config: classpath:logback.xml + spring: #kafka配置 kafka: @@ -32,4 +35,7 @@ spring: #密钥的反序列化器类,实现类实现了接口org.apache.kafka.common.serialization.Deserializer key-deserializer: org.apache.kafka.common.serialization.StringDeserializer #值的反序列化器类,实现类实现了接口org.apache.kafka.common.serialization.Deserializer - value-deserializer: org.apache.kafka.common.serialization.StringDeserializer \ No newline at end of file + value-deserializer: org.apache.kafka.common.serialization.StringDeserializer + +#ip白名单列表,多个ip用逗号隔开,允许所有用*号 +white-list: '*' \ No newline at end of file diff --git a/writer/src/main/resources/logback.xml b/writer/src/main/resources/logback.xml new file mode 100644 index 0000000..aa9c5cf --- /dev/null +++ b/writer/src/main/resources/logback.xml @@ -0,0 +1,29 @@ + + + + logback + + + + + %d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n + + + + + ${log.path} + + ${log.path}.%d{yyyy-MM-dd}.zip + + + %date %level [%thread] %logger{36} [%file : %line] %msg%n + + + + + + + + + + \ No newline at end of file