Browse Source

:bookmark: v1.2.3

冷冷 7 years ago
commit
f185add546
100 changed files with 5451 additions and 0 deletions
  1. 22 0
      .editorconfig
  2. 58 0
      .gitignore
  3. 14 0
      LICENSE
  4. 51 0
      README.md
  5. BIN
      doc/PIGX.png
  6. 58 0
      doc/deploy.md
  7. 270 0
      doc/pigx.sql
  8. 64 0
      docker-compose.yml
  9. 13 0
      pigx-auth/Dockerfile
  10. 102 0
      pigx-auth/pom.xml
  11. 39 0
      pigx-auth/src/main/java/com/pig4cloud/pigx/auth/PigxAuthApplication.java
  12. 102 0
      pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfig.java
  13. 68 0
      pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/WebSecurityConfigurer.java
  14. 59 0
      pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/RevokeTokenEndpoint.java
  15. 81 0
      pigx-auth/src/main/java/com/pig4cloud/pigx/auth/service/PigxUserDetailsServiceImpl.java
  16. 26 0
      pigx-auth/src/main/resources/bootstrap.yml
  17. 99 0
      pigx-common/pigx-common-code/src/main/java/com/pig4cloud/pigx/common/code/config/KaptchaConfiguration.java
  18. 25 0
      pigx-common/pigx-common-code/src/main/java/com/pig4cloud/pigx/common/code/exception/ValidateCodeException.java
  19. 93 0
      pigx-common/pigx-common-code/src/main/java/com/pig4cloud/pigx/common/code/filter/ImageCodeGatewayFilter.java
  20. 77 0
      pigx-common/pigx-common-code/src/main/java/com/pig4cloud/pigx/common/code/handle/ImageCodeHandler.java
  21. 63 0
      pigx-common/pigx-common-core/pom.xml
  22. 77 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/config/RedisConfig.java
  23. 89 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/CommonConstant.java
  24. 57 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/MqQueueConstant.java
  25. 77 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java
  26. 37 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/ServiceNameConstant.java
  27. 45 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/EnumSmsChannel.java
  28. 50 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/EnumSmsChannelTemplate.java
  29. 48 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/exception/CheckedException.java
  30. 49 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/exception/PigDeniedException.java
  31. 48 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/exception/UnloginException.java
  32. 32 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/exception/ValidateCodeException.java
  33. 112 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/ClassUtils.java
  34. 71 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/R.java
  35. 102 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/SpringContextHolder.java
  36. 195 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/WebUtils.java
  37. 1 0
      pigx-common/pigx-common-core/src/main/resources/META-INF/spring-devtools.properties
  38. 3 0
      pigx-common/pigx-common-core/src/main/resources/META-INF/spring.factories
  39. 1 0
      pigx-common/pigx-common-core/src/main/resources/META-INF/spring.provides
  40. 51 0
      pigx-common/pigx-common-log/pom.xml
  41. 52 0
      pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/LogAutoConfiguration.java
  42. 40 0
      pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/annotation/SysLog.java
  43. 57 0
      pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java
  44. 34 0
      pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogEvent.java
  45. 47 0
      pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogListener.java
  46. 66 0
      pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/util/SysLogUtils.java
  47. 1 0
      pigx-common/pigx-common-log/src/main/resources/META-INF/spring-devtools.properties
  48. 2 0
      pigx-common/pigx-common-log/src/main/resources/META-INF/spring.factories
  49. 59 0
      pigx-common/pigx-common-security/pom.xml
  50. 61 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/compoent/PermissionService.java
  51. 74 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/compoent/PigAccessDeniedHandler.java
  52. 105 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/compoent/PigxWebResponseExceptionTranslator.java
  53. 62 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/compoent/ResourceAuthExceptionEntryPoint.java
  54. 43 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/ForbiddenException.java
  55. 40 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/InvalidException.java
  56. 42 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/MethodNotAllowed.java
  57. 34 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/PigxAuth2Exception.java
  58. 42 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/ServerErrorException.java
  59. 42 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/UnauthorizedException.java
  60. 44 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/interceptor/PigxFeignClientIntercept.java
  61. 94 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/SecurityUtils.java
  62. 1 0
      pigx-common/pigx-common-security/src/main/resources/META-INF/spring-devtools.properties
  63. 5 0
      pigx-common/pigx-common-security/src/main/resources/META-INF/spring.factories
  64. 1 0
      pigx-common/pigx-common-security/src/main/resources/META-INF/spring.provides
  65. 64 0
      pigx-common/pigx-common-security/src/main/resources/org/springframework/security/messages_zh_CN.properties
  66. 58 0
      pigx-common/pigx-common-swagger/pom.xml
  67. 36 0
      pigx-common/pigx-common-swagger/src/main/java/com/pig4cloud/pigx/common/swagger/annotation/EnablePigxSwagger2.java
  68. 93 0
      pigx-common/pigx-common-swagger/src/main/java/com/pig4cloud/pigx/common/swagger/config/SwaggerAutoConfiguration.java
  69. 42 0
      pigx-common/pom.xml
  70. 13 0
      pigx-config/Dockerfile
  71. 75 0
      pigx-config/pom.xml
  72. 38 0
      pigx-config/src/main/java/com/pig4cloud/pigx/config/PigxConfigApplication.java
  73. 29 0
      pigx-config/src/main/resources/bootstrap.yml
  74. 48 0
      pigx-config/src/main/resources/config/application-dev.yml
  75. 8 0
      pigx-config/src/main/resources/config/pigx-auth-dev.yml
  76. 49 0
      pigx-config/src/main/resources/config/pigx-gateway-dev.yml
  77. 40 0
      pigx-config/src/main/resources/config/pigx-upms-dev.yml
  78. 13 0
      pigx-eureka/Dockerfile
  79. 80 0
      pigx-eureka/pom.xml
  80. 39 0
      pigx-eureka/src/main/java/com/pig4cloud/pigx/eureka/PigxEurekaApplication.java
  81. 39 0
      pigx-eureka/src/main/java/com/pig4cloud/pigx/eureka/security/WebSecurityConfig.java
  82. 32 0
      pigx-eureka/src/main/resources/bootstrap.yml
  83. 13 0
      pigx-gateway/Dockerfile
  84. 88 0
      pigx-gateway/pom.xml
  85. 37 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/PigxGatewayApplication.java
  86. 41 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/FilterIgnorePropertiesConfig.java
  87. 89 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/KaptchaConfiguration.java
  88. 38 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/RateLimiterConfiguration.java
  89. 61 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/RouterFunctionConfiguration.java
  90. 67 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/SwaggerProvider.java
  91. 47 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/exception/CheckedException.java
  92. 25 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/exception/ValidateCodeException.java
  93. 186 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/ImageCodeGatewayFilter.java
  94. 97 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/PasswordDecoderFilter.java
  95. 53 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/SwaggerHeaderFilter.java
  96. 44 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handle/HystrixFallbackHandler.java
  97. 77 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handle/ImageCodeHandler.java
  98. 55 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handle/SwaggerResourceHandler.java
  99. 60 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handle/SwaggerSecurityHandler.java
  100. 0 0
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handle/SwaggerUiHandler.java

+ 22 - 0
.editorconfig

@@ -0,0 +1,22 @@
+root = true
+
+# 对所有文件生效
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.{java,xml}]
+indent_style = tab
+indent_size = 4
+
+[*.{yml,json}]
+indent_style = space
+indent_size = 2
+
+# 对后缀名为 md 的文件生效
+[*.md]
+trim_trailing_whitespace = false

+ 58 - 0
.gitignore

@@ -0,0 +1,58 @@
+### gradle ###
+.gradle
+/build/
+!gradle/wrapper/gradle-wrapper.jar
+
+### STS ###
+.settings/
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+bin/
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+rebel.xml
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+
+### maven ###
+target/
+*.war
+*.ear
+*.zip
+*.tar
+*.tar.gz
+
+### logs ####
+logs
+
+### temp ignore ###
+*.log
+*.cache
+*.diff
+*.patch
+*.tmp
+*.java~
+*.properties~
+*.xml~
+
+### system ignore ###
+.DS_Store
+Thumbs.db
+Servers
+.metadata
+upload
+gen_code

+ 14 - 0
LICENSE

@@ -0,0 +1,14 @@
+     Copyright (c) 2018-2025, lengleng All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ Neither the name of the pig4cloud.com developer nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+ Author: lengleng (wangiegie@gmail.com)

+ 51 - 0
README.md

@@ -0,0 +1,51 @@
+<p align="center">
+ <img src="https://img.shields.io/circleci/project/vuejs/vue/dev.svg" alt="Build Status">
+  <img src="https://img.shields.io/badge/Spring%20Cloud-Finchley.RELEASE-blue.svg" alt="Coverage Status">
+  <img src="https://img.shields.io/badge/Spring%20Boot-2.0.3.RELEASE-blue.svg" alt="Downloads">
+</p>
+
+<h2 align="center">Supporting Pig Developer Team</h2> 
+
+## 项目官网
+https://pig4cloud.com
+
+### 配套代码
+<a href="https://gitee.wang/pig/pigx-ui" target="_blank">pigx-ui</a>
+
+### pigx 和 pig 区别
+
+- 基于最新的Spring Cloud  Finchley.RELEASE 版本
+- 完整的oAuth 流程,资源服务器控制权限
+- 去除了部分对于开发不友好的中间件
+
+### 部署说明
+[部署说明](doc/deploy.md)
+
+## 协议和授权
+
+pigX并非一个开源软件,作者保留全部的权利。
+
+### 🌹权益
+
+1. 个人使用
+2. 允许用于学习、毕设等。
+
+### 🚫禁止  
+
+1. 将本项目的部分或全部代码和资源进行任何形式的再发行(尤其上传GitHub、Gitee )
+2. 利用本项目的部分或全部代码和资源进行`任何商业行为`
+3. 举报有奖,抢先体验`pigx 2.0`。
+
+## 贡献代码
+
+pigX并非一个开源项目,也不是社区共同创造,其全部功能由作者独立完成。
+
+如果你愿意放弃所有权利,并将权利无条件转让给pigX作者,欢迎您贡献代码,当然会给予不等金额奖励。
+
+## 提交反馈
+
+1. 欢迎提交 issue,请写清楚遇到问题的原因,浏览器和操作系统环境,重现的流程。
+如果有开发能力,建议在本地调试出出错的代码。
+
+2. 不接受`功能请求`的 issue,功能请求可能会被直接关闭,请谅解(正确的方式是打赏并附言)。
+

BIN
doc/PIGX.png


+ 58 - 0
doc/deploy.md

@@ -0,0 +1,58 @@
+### 写在最前
+**如果想快速部署pigX,请完全参考本篇文档,如果有个性化的修改(例如:oauth2配置、token 个性化需求),请参考本篇运行起来以后,自行修改。循序渐进**
+
+### 架构图
+![image](http://p0hpm86wj.bkt.clouddn.com/PIGX.png)
+### 一、项目下载
+
+```
+git https://www.gitee.wang/pig/pigx.git
+```
+
+### 二、配置数据库
+
+```
+版本: mysql5.7+
+
+```
+基本参数如下:
+![image](https://gitee.com/uploads/images/2018/0610/142651_72fad599_410595.png)
+
+
+### 三、pig配置修改
+pigx/pigx-config/src/main/resources/config/application-dev.yml
+
+```
+# redis 相关
+spring:
+  redis:
+    password:
+    host: localhost
+```
+pigx/pigx-config/src/main/resources/config/pigx-auth-dev.yml  
+pigx/pigx-config/src/main/resources/config/pigx-upms-dev.yml
+
+```
+# 数据源
+spring:
+  datasource:
+    type: com.zaxxer.hikari.HikariDataSource
+    driver-class-name: com.mysql.jdbc.Driver
+    username: root
+    password: lengleng
+    url: jdbc:mysql://127.0.0.1:3306/pigx?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false
+```
+
+
+### 四、pigx-ui:
+
+```
+git clone https://www.gitee.wang/pig/pigx-ui.git
+npm run dev
+```
+请确保启动顺序
+1.eureka   
+2.config  
+3.gateway  
+4.auth  
+5.upms  

File diff suppressed because it is too large
+ 270 - 0
doc/pigx.sql


+ 64 - 0
docker-compose.yml

@@ -0,0 +1,64 @@
+version: '2'
+services:
+  pigx-redis:
+    image: redis:4.0.10
+    ports:
+      - 6379:6379
+    restart: always
+
+  pigx-eureka:
+    build:
+      context: ./
+      dockerfile: ./pigx-eureka/Dockerfile
+    restart: always
+    ports:
+      - 1025:1025
+
+  pigx-config:
+    links:
+      - pigx-eureka
+    build:
+      context: ./
+      dockerfile: ./pigx-config/Dockerfile
+    restart: always
+
+  pigx-gateway:
+    links:
+      - pigx-eureka
+    build:
+      context: ./
+      dockerfile: ./pigx-gateway/Dockerfile
+    restart: always
+    ports:
+      - 9999:9999
+
+  pigx-auth:
+    links:
+      - pigx-eureka
+      - pigx-redis
+    build:
+      context: ./
+      dockerfile: ./pigx-auth/Dockerfile
+    restart: always
+    ports:
+      - 3000:3000
+
+  pig-upms:
+    links:
+      - pigx-eureka
+      - pigx-redis
+      - pigx-gateway
+    build:
+      context: ./
+      dockerfile: ./pigx-upms/pigx-upms-biz/Dockerfile
+    restart: always
+
+  pig-monitor:
+    links:
+      - pigx-eureka
+    build:
+      context: ./
+      dockerfile: ./pigx-monitor/Dockerfile
+    restart: always
+    ports:
+      - 5001:5001

+ 13 - 0
pigx-auth/Dockerfile

@@ -0,0 +1,13 @@
+FROM anapsix/alpine-java:8_server-jre_unlimited
+
+MAINTAINER wangiegie@gmail.com
+
+RUN mkdir -p /pigx/bin/com.pig4cloud/pigx-auth
+
+WORKDIR /pigx/bin/com.pig4cloud/pigx-auth
+
+EXPOSE 1025
+
+ADD ./pigx-auth/target/pigx-auth.jar ./
+
+CMD java -Djava.security.egd=file:/dev/./urandom -jar pigx-auth.jar

+ 102 - 0
pigx-auth/pom.xml

@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng (wangiegie@gmail.com)
+  ~
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx</artifactId>
+		<version>${pigx.version}</version>
+	</parent>
+
+	<artifactId>pigx-auth</artifactId>
+	<version>${pigx.version}</version>
+	<packaging>jar</packaging>
+
+	<name>pigx-auth</name>
+	<description>pigx 认证授权中心,基于 spring security oAuth2</description>
+
+	<dependencies>
+		<!--配置中心客户端-->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-config</artifactId>
+		</dependency>
+		<!--upms api、model 模块-->
+		<dependency>
+			<groupId>com.pig4cloud</groupId>
+			<artifactId>pigx-upms-api</artifactId>
+			<version>${pigx.version}</version>
+		</dependency>
+		<!--spring security 、oauth、jwt依赖-->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-security</artifactId>
+			<exclusions>
+				<!--旧版本 redis操作有问题-->
+				<exclusion>
+					<artifactId>spring-security-oauth2</artifactId>
+					<groupId>org.springframework.security.oauth</groupId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.security.oauth</groupId>
+			<artifactId>spring-security-oauth2</artifactId>
+			<version>${security.oauth.version}</version>
+		</dependency>
+		<!--数据库-->
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+		</dependency>
+		<!--web 模块-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+			<exclusions>
+				<!--排除tomcat依赖-->
+				<exclusion>
+					<artifactId>spring-boot-starter-tomcat</artifactId>
+					<groupId>org.springframework.boot</groupId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<!--undertow容器-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-undertow</artifactId>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<configuration>
+					<finalName>${project.name}</finalName>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

+ 39 - 0
pigx-auth/src/main/java/com/pig4cloud/pigx/auth/PigxAuthApplication.java

@@ -0,0 +1,39 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.auth;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.cloud.client.SpringCloudApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+/**
+ * @author lengleng
+ * @date 2018年06月21日
+ * 认证授权中心
+ */
+@SpringCloudApplication
+@EnableFeignClients({"com.pig4cloud.pigx.admin.api.feign"})
+public class PigxAuthApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(PigxAuthApplication.class, args);
+	}
+}

+ 102 - 0
pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfig.java

@@ -0,0 +1,102 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.auth.config;
+
+import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
+import com.pig4cloud.pigx.common.security.compoent.PigxWebResponseExceptionTranslator;
+import lombok.AllArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
+import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
+import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
+import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
+import org.springframework.security.oauth2.provider.token.TokenEnhancer;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
+
+import javax.sql.DataSource;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author lengleng
+ * @date 2018/6/22
+ * 认证服务器配置
+ */
+@Configuration
+@AllArgsConstructor
+@EnableAuthorizationServer
+public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
+	private final DataSource dataSource;
+	private final AuthenticationManager authenticationManager;
+	private final RedisConnectionFactory redisConnectionFactory;
+
+	@Override
+	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
+		JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
+		clientDetailsService.setSelectClientDetailsSql(SecurityConstants.DEFAULT_SELECT_STATEMENT);
+		clientDetailsService.setFindClientDetailsSql(SecurityConstants.DEFAULT_FIND_STATEMENT);
+		clients.withClientDetails(clientDetailsService);
+	}
+
+	@Override
+	public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
+		oauthServer
+			.allowFormAuthenticationForClients()
+			.checkTokenAccess("permitAll()");
+	}
+
+	@Override
+	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
+		endpoints
+			.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
+			.tokenStore(tokenStore())
+			.tokenEnhancer(tokenEnhancer())
+			.authenticationManager(authenticationManager)
+			.reuseRefreshTokens(false)
+			.exceptionTranslator(new PigxWebResponseExceptionTranslator());
+	}
+
+
+
+	@Bean
+	public TokenStore tokenStore() {
+		RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
+		tokenStore.setPrefix(SecurityConstants.PIGX_PREFIX + SecurityConstants.OAUTH_PREFIX);
+		return tokenStore;
+	}
+
+	@Bean
+	public TokenEnhancer tokenEnhancer() {
+		return (accessToken, authentication) -> {
+			final Map<String, Object> additionalInfo = new HashMap<>(1);
+			additionalInfo.put("license", SecurityConstants.PIGX_LICENSE);
+			((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
+			return accessToken;
+		};
+	}
+}

+ 68 - 0
pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/WebSecurityConfigurer.java

@@ -0,0 +1,68 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.auth.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.annotation.Order;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.factory.PasswordEncoderFactories;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+/**
+ * @author lengleng
+ * @date 2018/6/22
+ * 认证相关配置
+ */
+@Primary
+@Order(90)
+@Configuration
+public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
+
+	@Override
+	protected void configure(HttpSecurity http) throws Exception {
+		http
+			.authorizeRequests()
+			.antMatchers("/actuator/**", "/oauth/removeToken").permitAll()
+			.anyRequest().authenticated()
+			.and().csrf().disable();
+	}
+
+	@Bean
+	@Override
+	public AuthenticationManager authenticationManagerBean() throws Exception {
+		return super.authenticationManagerBean();
+	}
+
+	/**
+	 * https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-storage-updated
+	 * Encoded password does not look like BCrypt
+	 *
+	 * @return PasswordEncoder
+	 */
+	@Bean
+	public PasswordEncoder passwordEncoder() {
+		return PasswordEncoderFactories.createDelegatingPasswordEncoder();
+	}
+
+}

+ 59 - 0
pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/RevokeTokenEndpoint.java

@@ -0,0 +1,59 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.auth.endpoint;
+
+import cn.hutool.core.util.StrUtil;
+import com.pig4cloud.pigx.common.core.util.R;
+import lombok.AllArgsConstructor;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author lengleng
+ * @date 2018/6/24
+ * 删除token端点
+ */
+@RestController
+@AllArgsConstructor
+public class RevokeTokenEndpoint {
+	private final TokenStore tokenStore;
+
+	/**
+	 * 删除token
+	 *
+	 * @param authHeader Authorization
+	 */
+	@RequestMapping("/oauth/removeToken")
+	public R<Boolean> logout(@RequestHeader(value = "Authorization", required = false) String authHeader) {
+		if (StringUtils.hasText(authHeader)) {
+			String tokenValue = authHeader.replace("Bearer", "").trim();
+			OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
+			if (accessToken == null || StrUtil.isBlank(accessToken.getValue())) {
+				return new R<>(false, "退出失败,token 为空");
+			}
+			tokenStore.removeAccessToken(accessToken);
+		}
+		return new R<>(Boolean.TRUE);
+	}
+}

+ 81 - 0
pigx-auth/src/main/java/com/pig4cloud/pigx/auth/service/PigxUserDetailsServiceImpl.java

@@ -0,0 +1,81 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.auth.service;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.StrUtil;
+import com.pig4cloud.pigx.admin.api.dto.UserInfo;
+import com.pig4cloud.pigx.admin.api.entity.SysUser;
+import com.pig4cloud.pigx.admin.api.feign.RemoteUserService;
+import com.pig4cloud.pigx.common.core.constant.CommonConstant;
+import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
+import com.pig4cloud.pigx.common.core.util.R;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * 用户详细信息
+ *
+ * @author lengleng
+ */
+@Slf4j
+@Service
+@AllArgsConstructor
+public class PigxUserDetailsServiceImpl implements UserDetailsService {
+	private final RemoteUserService remoteUserService;
+
+	@Override
+	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+		R<UserInfo> result = remoteUserService.info(username, SecurityConstants.FROM_IN);
+
+		if (result == null || result.getData() == null) {
+			throw new UsernameNotFoundException("用户不存在");
+		}
+
+		UserInfo info = result.getData();
+		Set<String> dbAuthsSet = new HashSet<>();
+		if (ArrayUtil.isNotEmpty(info.getRoles())) {
+			// 获取角色
+			Arrays.stream(info.getRoles()).forEach(role -> dbAuthsSet.add(SecurityConstants.ROLE + role));
+			// 获取资源
+			dbAuthsSet.addAll(Arrays.asList(info.getPermissions()));
+
+		}
+		Collection<? extends GrantedAuthority> authorities
+			= AuthorityUtils.createAuthorityList(dbAuthsSet.toArray(new String[0]));
+		SysUser user = info.getSysUser();
+		boolean enabled = StrUtil.equals(user.getDelFlag(), CommonConstant.STATUS_NORMAL);
+		// 构造security用户
+		return new User(username, SecurityConstants.BCRYPT + user.getPassword(), enabled,
+			true, true, true, authorities);
+	}
+}

+ 26 - 0
pigx-auth/src/main/resources/bootstrap.yml

@@ -0,0 +1,26 @@
+server:
+  port: 3000
+
+spring:
+  application:
+    name: pigx-auth
+  # 配置中心
+  cloud:
+    config:
+      fail-fast: true
+      name: ${spring.application.name}
+      profile: dev
+      discovery:
+        enabled: true
+        service-id: pigx-config
+
+# 注册中心配置
+eureka:
+  instance:
+    prefer-ip-address: true
+  client:
+    service-url:
+      defaultZone: http://pig:pig@localhost:1025/eureka/
+logging:
+  level:
+    root: debug

+ 99 - 0
pigx-common/pigx-common-code/src/main/java/com/pig4cloud/pigx/common/code/config/KaptchaConfiguration.java

@@ -0,0 +1,99 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.config;
+
+import com.google.code.kaptcha.impl.DefaultKaptcha;
+import com.google.code.kaptcha.util.Config;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Properties;
+
+/**
+ * @author lengleng
+ * @date 2017-12-21 21:12:18
+ */
+@Configuration
+public class KaptchaConfiguration {
+
+    private static final String KAPTCHA_BORDER = "kaptcha.border";
+    private static final String KAPTCHA_TEXTPRODUCER_FONT_COLOR = "kaptcha.textproducer.font.color";
+    private static final String KAPTCHA_TEXTPRODUCER_CHAR_SPACE = "kaptcha.textproducer.char.space";
+    private static final String KAPTCHA_IMAGE_WIDTH = "kaptcha.image.width";
+    private static final String KAPTCHA_IMAGE_HEIGHT = "kaptcha.image.height";
+    private static final String KAPTCHA_TEXTPRODUCER_CHAR_LENGTH = "kaptcha.textproducer.char.length";
+    private static final Object KAPTCHA_IMAGE_FONT_SIZE = "kaptcha.textproducer.font.size";
+
+	/**
+	 * 默认生成图形验证码宽度
+	 */
+	String DEFAULT_IMAGE_WIDTH = "100";
+
+	/**
+	 * 默认生成图像验证码高度
+	 */
+	String DEFAULT_IMAGE_HEIGHT = "40";
+
+	/**
+	 * 默认生成图形验证码长度
+	 */
+	String DEFAULT_IMAGE_LENGTH = "4";
+
+	/**
+	 * 默认生成图形验证码过期时间
+	 */
+	int DEFAULT_IMAGE_EXPIRE = 60;
+	/**
+	 * 边框颜色,合法值: r,g,b (and optional alpha) 或者 white,black,blue.
+	 */
+	String DEFAULT_COLOR_FONT = "black";
+
+	/**
+	 * 图片边框
+	 */
+	String DEFAULT_IMAGE_BORDER = "no";
+	/**
+	 * 默认图片间隔
+	 */
+	String DEFAULT_CHAR_SPACE = "5";
+
+	/**
+	 * 默认保存code的前缀
+	 */
+	String DEFAULT_CODE_KEY = "DEFAULT_CODE_KEY";
+	/**
+	 * 验证码文字大小
+	 */
+	String DEFAULT_IMAGE_FONT_SIZE = "30";
+
+    @Bean
+    public DefaultKaptcha producer() {
+        Properties properties = new Properties();
+        properties.put(KAPTCHA_BORDER, DEFAULT_IMAGE_BORDER);
+        properties.put(KAPTCHA_TEXTPRODUCER_FONT_COLOR, DEFAULT_COLOR_FONT);
+        properties.put(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, DEFAULT_CHAR_SPACE);
+        properties.put(KAPTCHA_IMAGE_WIDTH, DEFAULT_IMAGE_WIDTH);
+        properties.put(KAPTCHA_IMAGE_HEIGHT, DEFAULT_IMAGE_HEIGHT);
+        properties.put(KAPTCHA_IMAGE_FONT_SIZE, DEFAULT_IMAGE_FONT_SIZE);
+        properties.put(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, DEFAULT_IMAGE_LENGTH);
+        Config config = new Config(properties);
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+        defaultKaptcha.setConfig(config);
+        return defaultKaptcha;
+    }
+}

+ 25 - 0
pigx-common/pigx-common-code/src/main/java/com/pig4cloud/pigx/common/code/exception/ValidateCodeException.java

@@ -0,0 +1,25 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.exception;
+
+/**
+ * @author lengleng
+ */
+public class ValidateCodeException extends Exception {
+
+}

+ 93 - 0
pigx-common/pigx-common-code/src/main/java/com/pig4cloud/pigx/common/code/filter/ImageCodeGatewayFilter.java

@@ -0,0 +1,93 @@
+package com.pig4cloud.pigx.gateway.filter;
+
+import cn.hutool.core.util.StrUtil;
+import com.pig4cloud.pigx.gateway.exception.ValidateCodeException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author lengleng
+ * @date 2018/7/4
+ * 验证码处理
+ */
+@Slf4j
+@Component
+public class ImageCodeGatewayFilter extends AbstractGatewayFilterFactory {
+	private static final String OAUTH_TOKEN_URL = "/oauth/token";
+	public static final String DEFAULT_CODE_KEY = "DEFAULT_CODE_KEY";
+
+	@Autowired
+	private RedisTemplate redisTemplate;
+
+	@Override
+	public GatewayFilter apply(Object config) {
+		return (exchange, chain) -> {
+			ServerHttpRequest request = exchange.getRequest();
+
+			// 不是登录请求,直接向下执行
+			if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath(), OAUTH_TOKEN_URL)) {
+				return chain.filter(exchange);
+			}
+			try {
+				checkCode(request);
+			} catch (ValidateCodeException e) {
+				ServerHttpResponse response = exchange.getResponse();
+				response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED);
+				return response.setComplete();
+			}
+
+			return chain.filter(exchange);
+		};
+	}
+
+
+	/**
+	 * 检查code
+	 *
+	 * @param request
+	 * @throws ValidateCodeException 校验异常
+	 */
+	private void checkCode(ServerHttpRequest request) throws ValidateCodeException {
+		String code = request.getQueryParams().getFirst("code");
+
+		if (StrUtil.isBlank(code)) {
+			throw new ValidateCodeException();
+		}
+
+		String randomStr = request.getQueryParams().getFirst("randomStr");
+		if (StrUtil.isBlank(randomStr)) {
+			throw new ValidateCodeException();
+		}
+
+		String key = DEFAULT_CODE_KEY + randomStr;
+		if (!redisTemplate.hasKey(key)) {
+			throw new ValidateCodeException();
+		}
+
+		Object codeObj = redisTemplate.opsForValue().get(key);
+
+		if (codeObj == null) {
+			throw new ValidateCodeException();
+		}
+
+		String saveCode = codeObj.toString();
+		if (StrUtil.isBlank(saveCode)) {
+			redisTemplate.delete(key);
+			throw new ValidateCodeException();
+		}
+
+		if (!StrUtil.equals(saveCode, code)) {
+			redisTemplate.delete(key);
+			throw new ValidateCodeException();
+		}
+
+		redisTemplate.delete(key);
+	}
+}

+ 77 - 0
pigx-common/pigx-common-code/src/main/java/com/pig4cloud/pigx/common/code/handle/ImageCodeHandler.java

@@ -0,0 +1,77 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.handle;
+
+import com.google.code.kaptcha.Producer;
+import com.pig4cloud.pigx.gateway.filter.ImageCodeGatewayFilter;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.util.FastByteArrayOutputStream;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author lengleng
+ * @date 2018/7/5
+ * 验证码生成逻辑处理类
+ */
+@Slf4j
+@Component
+@AllArgsConstructor
+public class ImageCodeHandler implements HandlerFunction<ServerResponse> {
+	private final Producer producer;
+	private final RedisTemplate redisTemplate;
+
+	@Override
+	public Mono<ServerResponse> handle(ServerRequest serverRequest) {
+		//生成验证码
+		String text = producer.createText();
+		BufferedImage image = producer.createImage(text);
+
+		//保存验证码信息
+		String  randomStr = serverRequest.queryParam("randomStr").get();
+		redisTemplate.opsForValue().set(ImageCodeGatewayFilter.DEFAULT_CODE_KEY + randomStr, text, 60, TimeUnit.SECONDS);
+
+		// 转换流信息写出
+		FastByteArrayOutputStream os = new FastByteArrayOutputStream();
+		try {
+			ImageIO.write(image, "jpeg", os);
+		} catch (IOException e) {
+			log.error("ImageIO write err", e);
+			return Mono.error(e);
+		}
+
+		return ServerResponse
+			.status(HttpStatus.OK)
+			.contentType(MediaType.IMAGE_JPEG)
+			.body(BodyInserters.fromResource(new ByteArrayResource(os.toByteArray())));
+	}
+}

+ 63 - 0
pigx-common/pigx-common-core/pom.xml

@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng (wangiegie@gmail.com)
+  ~
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx-common</artifactId>
+		<version>${pigx.version}</version>
+	</parent>
+
+	<artifactId>pigx-common-core</artifactId>
+	<version>${pigx.version}</version>
+	<packaging>jar</packaging>
+	<name>pigx-common-core</name>
+	<description>pigx 公共工具类核心包</description>
+
+
+	<dependencies>
+		<!--hutool-->
+		<dependency>
+			<groupId>cn.hutool</groupId>
+			<artifactId>hutool-all</artifactId>
+			<version>${hutool.version}</version>
+		</dependency>
+		<!--fastjson-->
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>fastjson</artifactId>
+			<version>${fastjson.version}</version>
+		</dependency>
+		<!--redis-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-redis</artifactId>
+		</dependency>
+		<!--server-api-->
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>javax.servlet-api</artifactId>
+			<version>${servlet-api.version}</version>
+			<scope>provided</scope>
+		</dependency>
+	</dependencies>
+</project>

+ 77 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/config/RedisConfig.java

@@ -0,0 +1,77 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.config;
+
+import lombok.AllArgsConstructor;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.*;
+import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * @author lengleng
+ * @date 2018/6/23
+ * Redis 配置类
+ */
+@EnableCaching
+@Configuration
+@AllArgsConstructor
+public class RedisConfig {
+	private final RedisConnectionFactory factory;
+
+	@Bean
+	public RedisTemplate<String, Object> redisTemplate() {
+		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
+		redisTemplate.setKeySerializer(new StringRedisSerializer());
+		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
+		redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
+		redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
+		redisTemplate.setConnectionFactory(factory);
+		return redisTemplate;
+	}
+
+	@Bean
+	public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
+		return redisTemplate.opsForHash();
+	}
+
+	@Bean
+	public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
+		return redisTemplate.opsForValue();
+	}
+
+	@Bean
+	public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
+		return redisTemplate.opsForList();
+	}
+
+	@Bean
+	public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
+		return redisTemplate.opsForSet();
+	}
+
+	@Bean
+	public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
+		return redisTemplate.opsForZSet();
+	}
+}

+ 89 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/CommonConstant.java

@@ -0,0 +1,89 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.constant;
+
+/**
+ * @author lengleng
+ * @date 2017/10/29
+ */
+public interface CommonConstant {
+	/**
+	 * token请求头名称
+	 */
+	String REQ_HEADER = "Authorization";
+
+	/**
+	 * token分割符
+	 */
+	String TOKEN_SPLIT = "Bearer ";
+
+	/**
+	 * jwt签名
+	 */
+	String SIGN_KEY = "PIG";
+	/**
+	 * 删除
+	 */
+	String STATUS_DEL = "1";
+	/**
+	 * 正常
+	 */
+	String STATUS_NORMAL = "0";
+
+	/**
+	 * 锁定
+	 */
+	String STATUS_LOCK = "9";
+
+	/**
+	 * 菜单
+	 */
+	String MENU = "0";
+
+	/**
+	 * 按钮
+	 */
+	String BUTTON = "1";
+
+	/**
+	 * 删除标记
+	 */
+	String DEL_FLAG = "del_flag";
+
+	/**
+	 * 编码
+	 */
+	String UTF8 = "UTF-8";
+
+	/**
+	 * JSON 资源
+	 */
+	String CONTENT_TYPE = "application/json; charset=utf-8";
+
+	/**
+	 * 阿里大鱼
+	 */
+	String ALIYUN_SMS = "aliyun_sms";
+
+	/**
+	 * 路由信息Redis保存的key
+	 */
+	String ROUTE_KEY = "_ROUTE_KEY";
+}

+ 57 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/MqQueueConstant.java

@@ -0,0 +1,57 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.constant;
+
+/**
+ * @author lengleng
+ * @date 2018/1/15
+ * MQ 消息队列
+ */
+public interface MqQueueConstant {
+	/**
+	 * log rabbit队列名称
+	 */
+	String LOG_QUEUE = "log";
+
+	/**
+	 * 发送短信验证码队列
+	 */
+	String MOBILE_CODE_QUEUE = "mobile_code_queue";
+
+	/**
+	 * 短信服务状态队列
+	 */
+	String MOBILE_SERVICE_STATUS_CHANGE = "mobile_service_status_change";
+
+	/**
+	 * 钉钉服务状态队列
+	 */
+	String DINGTALK_SERVICE_STATUS_CHANGE = "dingtalk_service_status_change";
+
+	/**
+	 * zipkin 队列
+	 */
+	String ZIPKIN_NAME_QUEUE = "zipkin";
+
+	/**
+	 * 路由配置状态队列
+	 */
+	String ROUTE_CONFIG_CHANGE = "route_config_change";
+}

+ 77 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java

@@ -0,0 +1,77 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.constant;
+
+/**
+ * @author lengleng
+ * @date 2017-12-18
+ */
+public interface SecurityConstants {
+	/**
+	 * 角色前缀
+	 */
+	String ROLE = "ROLE_";
+	/**
+	 * 前缀
+	 */
+	String PIGX_PREFIX = "pigx_";
+
+	/**
+	 * oauth 相关前缀
+	 */
+	String OAUTH_PREFIX = "oauth:";
+	/**
+	 * 项目的license
+	 */
+	String PIGX_LICENSE = "made by pigx";
+
+	/**
+	 * 内部
+	 */
+	String FROM_IN = "Y";
+
+	/**
+	 * {bcrypt} 加密的特征码
+	 */
+	String BCRYPT = "{bcrypt}";
+	/**
+	 * sys_oauth_client_details 表的字段,不包括client_id、client_secret
+	 */
+	String CLIENT_FIELDS = "client_id, CONCAT('{noop}',client_secret) as client_secret, resource_ids, scope, "
+		+ "authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, "
+		+ "refresh_token_validity, additional_information, autoapprove";
+
+	/**
+	 * JdbcClientDetailsService 查询语句
+	 */
+	String BASE_FIND_STATEMENT = "select " + CLIENT_FIELDS
+		+ " from sys_oauth_client_details";
+
+	/**
+	 * 默认的查询语句
+	 */
+	String DEFAULT_FIND_STATEMENT = BASE_FIND_STATEMENT + " order by client_id";
+
+	/**
+	 * 按条件client_id 查询
+	 */
+	String DEFAULT_SELECT_STATEMENT = BASE_FIND_STATEMENT + " where client_id = ?";
+
+}

+ 37 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/ServiceNameConstant.java

@@ -0,0 +1,37 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.constant;
+
+/**
+ * @author lengleng
+ * @date 2018年06月22日16:41:01
+ * 服务名称
+ */
+public interface ServiceNameConstant {
+	/**
+	 * 认证服务的SERVICEID(zuul 配置的对应)
+	 */
+	String AUTH_SERVICE = "pigx-auth";
+
+	/**
+	 * UMPS模块
+	 */
+	String UMPS_SERVICE = "pigx-upms";
+}

+ 45 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/EnumSmsChannel.java

@@ -0,0 +1,45 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.constant.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author lengleng
+ * @date 2018/1/16
+ * 短信通道枚举
+ */
+@Getter
+@AllArgsConstructor
+public enum EnumSmsChannel {
+	/**
+	 * 阿里大鱼短信通道
+	 */
+	ALIYUN("ALIYUN_SMS", "阿里大鱼");
+	/**
+	 * 通道名称
+	 */
+	private final String name;
+	/**
+	 * 通道描述
+	 */
+	private final String description;
+}

+ 50 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/EnumSmsChannelTemplate.java

@@ -0,0 +1,50 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.constant.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author LiXunHuan
+ * @date 2018/1/16
+ * 短信通道模板
+ */
+@Getter
+@AllArgsConstructor
+public enum EnumSmsChannelTemplate {
+	/**
+	 * 登录验证
+	 */
+	LOGIN_NAME_LOGIN("loginCodeChannel", "登录验证"),
+	/**
+	 * 服务异常提醒
+	 */
+	SERVICE_STATUS_CHANGE("serviceStatusChange", "Pig4Cloud");
+
+	/**
+	 * 模板名称
+	 */
+	private final String template;
+	/**
+	 * 模板签名
+	 */
+	private final String signName;
+}

+ 48 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/exception/CheckedException.java

@@ -0,0 +1,48 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.exception;
+
+import lombok.NoArgsConstructor;
+
+/**
+ * @author lengleng
+ * @date 😴2018年06月22日16:21:57
+ */
+@NoArgsConstructor
+public class CheckedException extends RuntimeException {
+	private static final long serialVersionUID = 1L;
+
+	public CheckedException(String message) {
+		super(message);
+	}
+
+	public CheckedException(Throwable cause) {
+		super(cause);
+	}
+
+	public CheckedException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+	public CheckedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+		super(message, cause, enableSuppression, writableStackTrace);
+	}
+
+}

+ 49 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/exception/PigDeniedException.java

@@ -0,0 +1,49 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.exception;
+
+import lombok.NoArgsConstructor;
+
+/**
+ * @author lengleng
+ * @date 2018年06月22日16:22:03
+ * 403 授权拒绝
+ */
+@NoArgsConstructor
+public class PigDeniedException extends RuntimeException {
+	private static final long serialVersionUID = 1L;
+
+	public PigDeniedException(String message) {
+		super(message);
+	}
+
+	public PigDeniedException(Throwable cause) {
+		super(cause);
+	}
+
+	public PigDeniedException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+	public PigDeniedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+		super(message, cause, enableSuppression, writableStackTrace);
+	}
+
+}

+ 48 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/exception/UnloginException.java

@@ -0,0 +1,48 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.exception;
+
+import lombok.NoArgsConstructor;
+
+/**
+ * @author lengleng
+ * @date 2018年06月22日16:22:10
+ */
+@NoArgsConstructor
+public class UnloginException extends RuntimeException {
+	private static final long serialVersionUID = 1L;
+
+	public UnloginException(String message) {
+		super(message);
+	}
+
+	public UnloginException(Throwable cause) {
+		super(cause);
+	}
+
+	public UnloginException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+	public UnloginException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+		super(message, cause, enableSuppression, writableStackTrace);
+	}
+
+}

+ 32 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/exception/ValidateCodeException.java

@@ -0,0 +1,32 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.exception;
+
+/**
+ * @author lengleng
+ * @date 2018年06月22日16:22:15
+ */
+public class ValidateCodeException extends Exception {
+	private static final long serialVersionUID = -7285211528095468156L;
+
+	public ValidateCodeException(String msg) {
+		super(msg);
+	}
+}

+ 112 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/ClassUtils.java

@@ -0,0 +1,112 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.util;
+
+import org.springframework.core.BridgeMethodResolver;
+import org.springframework.core.DefaultParameterNameDiscoverer;
+import org.springframework.core.MethodParameter;
+import org.springframework.core.ParameterNameDiscoverer;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+import org.springframework.core.annotation.SynthesizingMethodParameter;
+import org.springframework.web.method.HandlerMethod;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * 类工具类
+ *
+ * @author L.cm
+ */
+public class ClassUtils extends org.springframework.util.ClassUtils {
+	private static final ParameterNameDiscoverer PARAMETERNAMEDISCOVERER = new DefaultParameterNameDiscoverer();
+
+	/**
+	 * 获取方法参数信息
+	 *
+	 * @param constructor    构造器
+	 * @param parameterIndex 参数序号
+	 * @return {MethodParameter}
+	 */
+	public static MethodParameter getMethodParameter(Constructor<?> constructor, int parameterIndex) {
+		MethodParameter methodParameter = new SynthesizingMethodParameter(constructor, parameterIndex);
+		methodParameter.initParameterNameDiscovery(PARAMETERNAMEDISCOVERER);
+		return methodParameter;
+	}
+
+	/**
+	 * 获取方法参数信息
+	 *
+	 * @param method         方法
+	 * @param parameterIndex 参数序号
+	 * @return {MethodParameter}
+	 */
+	public static MethodParameter getMethodParameter(Method method, int parameterIndex) {
+		MethodParameter methodParameter = new SynthesizingMethodParameter(method, parameterIndex);
+		methodParameter.initParameterNameDiscovery(PARAMETERNAMEDISCOVERER);
+		return methodParameter;
+	}
+
+	/**
+	 * 获取Annotation
+	 *
+	 * @param method         Method
+	 * @param annotationType 注解类
+	 * @param <A>            泛型标记
+	 * @return {Annotation}
+	 */
+	public static <A extends Annotation> A getAnnotation(Method method, Class<A> annotationType) {
+		Class<?> targetClass = method.getDeclaringClass();
+		// The method may be on an interface, but we need attributes from the target class.
+		// If the target class is null, the method will be unchanged.
+		Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
+		// If we are dealing with method with generic parameters, find the original method.
+		specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
+		// 先找方法,再找方法上的类
+		A annotation = AnnotatedElementUtils.findMergedAnnotation(specificMethod, annotationType);
+		;
+		if (null != annotation) {
+			return annotation;
+		}
+		// 获取类上面的Annotation,可能包含组合注解,故采用spring的工具类
+		return AnnotatedElementUtils.findMergedAnnotation(specificMethod.getDeclaringClass(), annotationType);
+	}
+
+	/**
+	 * 获取Annotation
+	 *
+	 * @param handlerMethod  HandlerMethod
+	 * @param annotationType 注解类
+	 * @param <A>            泛型标记
+	 * @return {Annotation}
+	 */
+	public static <A extends Annotation> A getAnnotation(HandlerMethod handlerMethod, Class<A> annotationType) {
+		// 先找方法,再找方法上的类
+		A annotation = handlerMethod.getMethodAnnotation(annotationType);
+		if (null != annotation) {
+			return annotation;
+		}
+		// 获取类上面的Annotation,可能包含组合注解,故采用spring的工具类
+		Class<?> beanType = handlerMethod.getBeanType();
+		return AnnotatedElementUtils.findMergedAnnotation(beanType, annotationType);
+	}
+
+}

+ 71 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/R.java

@@ -0,0 +1,71 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.util;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+
+/**
+ * 响应信息主体
+ *
+ * @param <T>
+ * @author lengleng
+ */
+@ToString
+public class R<T> implements Serializable {
+	private static final int SUCCESS = 0;
+	private static final int FAIL = 1;
+	private static final long serialVersionUID = 1L;
+	@Getter
+	@Setter
+	private String msg = "success";
+
+	@Getter
+	@Setter
+	private int code = SUCCESS;
+
+	@Getter
+	@Setter
+	private T data;
+
+	public R() {
+		super();
+	}
+
+	public R(T data) {
+		super();
+		this.data = data;
+	}
+
+	public R(T data, String msg) {
+		super();
+		this.data = data;
+		this.msg = msg;
+	}
+
+	public R(Throwable e) {
+		super();
+		this.msg = e.getMessage();
+		this.code = FAIL;
+	}
+}

+ 102 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/SpringContextHolder.java

@@ -0,0 +1,102 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author lengleng
+ * @date 2018/6/27
+ * Spring 工具类
+ */
+@Slf4j
+@Service
+@Lazy(false)
+public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
+
+	private static ApplicationContext applicationContext = null;
+
+	/**
+	 * 取得存储在静态变量中的ApplicationContext.
+	 */
+	public static ApplicationContext getApplicationContext() {
+		return applicationContext;
+	}
+
+	/**
+	 * 实现ApplicationContextAware接口, 注入Context到静态变量中.
+	 */
+	@Override
+	public void setApplicationContext(ApplicationContext applicationContext) {
+		SpringContextHolder.applicationContext = applicationContext;
+	}
+
+	/**
+	 * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> T getBean(String name) {
+		return (T) applicationContext.getBean(name);
+	}
+
+	/**
+	 * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
+	 */
+	public static <T> T getBean(Class<T> requiredType) {
+		return applicationContext.getBean(requiredType);
+	}
+
+	/**
+	 * 清除SpringContextHolder中的ApplicationContext为Null.
+	 */
+	public static void clearHolder() {
+		if (log.isDebugEnabled()) {
+			log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
+		}
+		applicationContext = null;
+	}
+
+	/**
+	 * 发布事件
+	 *
+	 * @param event
+	 */
+	public static void publishEvent(ApplicationEvent event) {
+		if (applicationContext == null) {
+			return;
+		}
+		applicationContext.publishEvent(event);
+	}
+
+	/**
+	 * 实现DisposableBean接口, 在Context关闭时清理静态变量.
+	 */
+	@Override
+	public void destroy() throws Exception {
+		SpringContextHolder.clearHolder();
+	}
+
+}

+ 195 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/WebUtils.java

@@ -0,0 +1,195 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.core.util;
+
+import cn.hutool.json.JSONUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.http.MediaType;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.method.HandlerMethod;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+
+/**
+ * Miscellaneous utilities for web applications.
+ *
+ * @author L.cm
+ */
+@Slf4j
+public class WebUtils extends org.springframework.web.util.WebUtils {
+
+	public static final String UNKNOWN = "unknown";
+
+	/**
+	 * 判断是否ajax请求
+	 * spring ajax 返回含有 ResponseBody 或者 RestController注解
+	 *
+	 * @param handlerMethod HandlerMethod
+	 * @return 是否ajax请求
+	 */
+	public static boolean isBody(HandlerMethod handlerMethod) {
+		ResponseBody responseBody = ClassUtils.getAnnotation(handlerMethod, ResponseBody.class);
+		return responseBody != null;
+	}
+
+	/**
+	 * 读取cookie
+	 *
+	 * @param name cookie name
+	 * @return cookie value
+	 */
+	public static String getCookieVal(String name) {
+		HttpServletRequest request = WebUtils.getRequest();
+		Assert.notNull(request, "request from RequestContextHolder is null");
+		return getCookieVal(request, name);
+	}
+
+	/**
+	 * 读取cookie
+	 *
+	 * @param request HttpServletRequest
+	 * @param name    cookie name
+	 * @return cookie value
+	 */
+	public static String getCookieVal(HttpServletRequest request, String name) {
+		Cookie cookie = getCookie(request, name);
+		return cookie != null ? cookie.getValue() : null;
+	}
+
+	/**
+	 * 清除 某个指定的cookie
+	 *
+	 * @param response HttpServletResponse
+	 * @param key      cookie key
+	 */
+	public static void removeCookie(HttpServletResponse response, String key) {
+		setCookie(response, key, null, 0);
+	}
+
+	/**
+	 * 设置cookie
+	 *
+	 * @param response        HttpServletResponse
+	 * @param name            cookie name
+	 * @param value           cookie value
+	 * @param maxAgeInSeconds maxage
+	 */
+	public static void setCookie(HttpServletResponse response, String name, String value, int maxAgeInSeconds) {
+		Cookie cookie = new Cookie(name, value);
+		cookie.setPath("/");
+		cookie.setMaxAge(maxAgeInSeconds);
+		cookie.setHttpOnly(true);
+		response.addCookie(cookie);
+	}
+
+	/**
+	 * 获取 HttpServletRequest
+	 *
+	 * @return {HttpServletRequest}
+	 */
+	public static HttpServletRequest getRequest() {
+		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+	}
+
+	/**
+	 * 获取 HttpServletResponse
+	 *
+	 * @return {HttpServletResponse}
+	 */
+	public static HttpServletResponse getResponse() {
+		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
+	}
+
+	/**
+	 * 返回json
+	 *
+	 * @param response HttpServletResponse
+	 * @param result   结果对象
+	 */
+	public static void renderJson(HttpServletResponse response, Object result) {
+		renderJson(response, result, MediaType.APPLICATION_JSON_UTF8_VALUE);
+	}
+
+	/**
+	 * 返回json
+	 *
+	 * @param response    HttpServletResponse
+	 * @param result      结果对象
+	 * @param contentType contentType
+	 */
+	public static void renderJson(HttpServletResponse response, Object result, String contentType) {
+		response.setCharacterEncoding("UTF-8");
+		response.setContentType(contentType);
+		try (PrintWriter out = response.getWriter()) {
+			out.append(JSONUtil.toJsonStr(result));
+		} catch (IOException e) {
+			log.error(e.getMessage(), e);
+		}
+	}
+
+	/**
+	 * 获取ip
+	 *
+	 * @return {String}
+	 */
+	public static String getIP() {
+		return getIP(WebUtils.getRequest());
+	}
+
+	/**
+	 * 获取ip
+	 *
+	 * @param request HttpServletRequest
+	 * @return {String}
+	 */
+	public static String getIP(HttpServletRequest request) {
+		Assert.notNull(request, "HttpServletRequest is null");
+		String ip = request.getHeader("X-Requested-For");
+		if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
+			ip = request.getHeader("X-Forwarded-For");
+		}
+		if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
+			ip = request.getHeader("Proxy-Client-IP");
+		}
+		if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
+			ip = request.getHeader("WL-Proxy-Client-IP");
+		}
+		if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
+			ip = request.getHeader("HTTP_CLIENT_IP");
+		}
+		if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
+			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+		}
+		if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
+			ip = request.getRemoteAddr();
+		}
+		return StringUtils.isBlank(ip) ? null : ip.split(",")[0];
+	}
+}
+

+ 1 - 0
pigx-common/pigx-common-core/src/main/resources/META-INF/spring-devtools.properties

@@ -0,0 +1 @@
+restart.include.pigx-common-core=/pigx-common-core[\\w-]+\.jar

+ 3 - 0
pigx-common/pigx-common-core/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,3 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  com.pig4cloud.pigx.common.core.config.RedisConfig,\
+  com.pig4cloud.pigx.common.core.util.SpringContextHolder

+ 1 - 0
pigx-common/pigx-common-core/src/main/resources/META-INF/spring.provides

@@ -0,0 +1 @@
+provides: hutool-all, spring-cloud-starter-openfeign, feign-okhttp, fastjson, spring-boot-starter-data-redis

+ 51 - 0
pigx-common/pigx-common-log/pom.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng (wangiegie@gmail.com)
+  ~
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx-common</artifactId>
+		<version>${pigx.version}</version>
+	</parent>
+
+	<artifactId>pigx-common-log</artifactId>
+	<version>${pigx.version}</version>
+	<packaging>jar</packaging>
+	<name>pigx-common-log</name>
+	<description>pigx 日志服务</description>
+
+
+	<dependencies>
+		<!--工具类核心包-->
+		<dependency>
+			<groupId>com.pig4cloud</groupId>
+			<artifactId>pigx-common-core</artifactId>
+			<version>${pigx.version}</version>
+		</dependency>
+		<!--UPMS接口模块-->
+		<dependency>
+			<groupId>com.pig4cloud</groupId>
+			<artifactId>pigx-upms-api</artifactId>
+			<version>${pigx.version}</version>
+		</dependency>
+	</dependencies>
+</project>

+ 52 - 0
pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/LogAutoConfiguration.java

@@ -0,0 +1,52 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.log;
+
+import com.pig4cloud.pigx.admin.api.feign.RemoteLogService;
+import com.pig4cloud.pigx.common.log.aspect.SysLogAspect;
+import com.pig4cloud.pigx.common.log.event.SysLogListener;
+import lombok.AllArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author lengleng
+ * @date 2018/6/28
+ * 日志自动配置
+ */
+@Configuration
+@AllArgsConstructor
+@ConditionalOnWebApplication
+@EnableFeignClients({"com.pig4cloud.pigx.admin.api.feign"})
+public class LogAutoConfiguration {
+	private final RemoteLogService remoteLogService;
+
+	@Bean
+	public SysLogListener sysLogListener() {
+		return new SysLogListener(remoteLogService);
+	}
+
+	@Bean
+	public SysLogAspect sysLogAspect() {
+		return new SysLogAspect();
+	}
+}

+ 40 - 0
pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/annotation/SysLog.java

@@ -0,0 +1,40 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.log.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * @author lengleng
+ * @date 2018/6/28
+ * 操作日志注解
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SysLog {
+
+	/**
+	 * 描述
+	 *
+	 * @return {String}
+	 */
+	String value();
+}

+ 57 - 0
pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java

@@ -0,0 +1,57 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.log.aspect;
+
+import com.pig4cloud.pigx.common.log.annotation.SysLog;
+import com.pig4cloud.pigx.common.log.event.SysLogEvent;
+import com.pig4cloud.pigx.common.log.util.SysLogUtils;
+import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+
+/**
+ * 操作日志使用spring event异步入库
+ *
+ * @author L.cm
+ */
+@Aspect
+@Slf4j
+public class SysLogAspect {
+
+	@Around("@annotation(sysLog)")
+	public Object aroundWxApi(ProceedingJoinPoint point, SysLog sysLog) throws Throwable {
+		String strClassName = point.getTarget().getClass().getName();
+		String strMethodName = point.getSignature().getName();
+		log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName);
+
+		com.pig4cloud.pigx.admin.api.entity.SysLog logVo = SysLogUtils.getSysLog();
+		logVo.setTitle(sysLog.value());
+		// 发送异步日志事件
+		Long startTime = System.currentTimeMillis();
+		Object obj = point.proceed();
+		Long endTime = System.currentTimeMillis();
+		logVo.setTime(endTime - startTime);
+		SpringContextHolder.publishEvent(new SysLogEvent(logVo));
+		return obj;
+	}
+
+}

+ 34 - 0
pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogEvent.java

@@ -0,0 +1,34 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.log.event;
+
+import com.pig4cloud.pigx.admin.api.entity.SysLog;
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * @author lengleng
+ * 系统日志事件
+ */
+public class SysLogEvent extends ApplicationEvent {
+
+	public SysLogEvent(SysLog source) {
+		super(source);
+	}
+}

+ 47 - 0
pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogListener.java

@@ -0,0 +1,47 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.log.event;
+
+import com.pig4cloud.pigx.admin.api.entity.SysLog;
+import com.pig4cloud.pigx.admin.api.feign.RemoteLogService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.event.EventListener;
+import org.springframework.core.annotation.Order;
+import org.springframework.scheduling.annotation.Async;
+
+
+/**
+ * @author lengleng
+ * 异步监听日志事件
+ */
+@Slf4j
+@AllArgsConstructor
+public class SysLogListener {
+	private final RemoteLogService remoteLogService;
+
+	@Async
+	@Order
+	@EventListener(SysLogEvent.class)
+	public void saveSysLog(SysLogEvent event) {
+		SysLog sysLog = (SysLog) event.getSource();
+		remoteLogService.saveLog(sysLog);
+	}
+}

+ 66 - 0
pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/util/SysLogUtils.java

@@ -0,0 +1,66 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.log.util;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.URLUtil;
+import cn.hutool.http.HttpUtil;
+import com.pig4cloud.pigx.admin.api.entity.SysLog;
+import com.pig4cloud.pigx.common.core.constant.CommonConstant;
+import com.pig4cloud.pigx.common.security.util.SecurityUtils;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 系统日志工具类
+ *
+ * @author L.cm
+ */
+public class SysLogUtils {
+
+	private static final String PASSWORD = "password";
+
+	public static SysLog getSysLog() {
+		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+		StringBuilder params = new StringBuilder();
+		request.getParameterMap().forEach((key, values) -> {
+			params.append(key).append("=");
+			if (PASSWORD.equalsIgnoreCase(key)) {
+				params.append("******");
+			} else {
+				params.append(ArrayUtil.toString(values));
+			}
+			params.append("&");
+		});
+
+		SysLog sysLog = new SysLog();
+		sysLog.setCreateBy(SecurityUtils.getUser());
+		sysLog.setType(CommonConstant.STATUS_NORMAL);
+		sysLog.setRemoteAddr(HttpUtil.getClientIP(request));
+		sysLog.setRequestUri(URLUtil.getPath(request.getRequestURI()));
+		sysLog.setMethod(request.getMethod());
+		sysLog.setUserAgent(request.getHeader("user-agent"));
+		sysLog.setParams(HttpUtil.toParams(request.getParameterMap()));
+		sysLog.setServiceId(SecurityUtils.getClientId());
+		return sysLog;
+	}
+}

+ 1 - 0
pigx-common/pigx-common-log/src/main/resources/META-INF/spring-devtools.properties

@@ -0,0 +1 @@
+restart.include.pigx-common-security=/pigx-common-log[\\w-]+\.jar

+ 2 - 0
pigx-common/pigx-common-log/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+    com.pig4cloud.pigx.common.log.LogAutoConfiguration

+ 59 - 0
pigx-common/pigx-common-security/pom.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng (wangiegie@gmail.com)
+  ~
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx-common</artifactId>
+		<version>${pigx.version}</version>
+	</parent>
+
+	<artifactId>pigx-common-security</artifactId>
+	<version>${pigx.version}</version>
+	<packaging>jar</packaging>
+	<name>pigx-common-security</name>
+	<description>pigx 安全工具类</description>
+
+
+	<dependencies>
+		<!--工具类核心包-->
+		<dependency>
+			<groupId>com.pig4cloud</groupId>
+			<artifactId>pigx-common-core</artifactId>
+			<version>${pigx.version}</version>
+		</dependency>
+		<!--安全模块-->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-security</artifactId>
+		</dependency>
+		<!--feign 依赖-->
+		<dependency>
+			<groupId>io.github.openfeign</groupId>
+			<artifactId>feign-okhttp</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-openfeign</artifactId>
+		</dependency>
+	</dependencies>
+</project>

+ 61 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/compoent/PermissionService.java

@@ -0,0 +1,61 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.security.compoent;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.util.PatternMatchUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.Collection;
+
+/**
+ * @author lengleng
+ * @date 2018/6/22
+ * 接口权限判断工具
+ */
+@Slf4j
+@Component("pms")
+public class PermissionService {
+	/**
+	 * 判断接口是否有xxx:xxx权限
+	 *
+	 * @param permission 权限
+	 * @return {boolean}
+	 */
+	public boolean hasPermission(String permission) {
+		if (StrUtil.isBlank(permission)) {
+			return false;
+		}
+		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+		if (authentication == null) {
+			return false;
+		}
+		Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
+		return authorities.stream()
+			.map(GrantedAuthority::getAuthority)
+			.filter(StringUtils::hasText)
+			.anyMatch(x -> PatternMatchUtils.simpleMatch(permission, x));
+	}
+}

+ 74 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/compoent/PigAccessDeniedHandler.java

@@ -0,0 +1,74 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.security.compoent;
+
+/**
+ * @author lengleng
+ * @date 2018/6/22
+ */
+
+import cn.hutool.http.HttpStatus;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.pig4cloud.pigx.common.core.constant.CommonConstant;
+import com.pig4cloud.pigx.common.core.exception.PigDeniedException;
+import com.pig4cloud.pigx.common.core.util.R;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author lengleng
+ * 授权拒绝处理器,覆盖默认的OAuth2AccessDeniedHandler
+ * 包装失败信息到PigDeniedException
+ */
+@Slf4j
+@Component
+@AllArgsConstructor
+public class PigAccessDeniedHandler extends OAuth2AccessDeniedHandler {
+	private final ObjectMapper objectMapper;
+
+	/**
+	 * 授权拒绝处理,使用R包装
+	 *
+	 * @param request       request
+	 * @param response      response
+	 * @param authException authException
+	 * @throws IOException      IOException
+	 * @throws ServletException ServletException
+	 */
+	@Override
+	public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException) throws IOException, ServletException {
+		log.info("授权失败,禁止访问 {}", request.getRequestURI());
+		response.setCharacterEncoding(CommonConstant.UTF8);
+		response.setContentType(CommonConstant.CONTENT_TYPE);
+		R<String> result = new R<>(new PigDeniedException("授权失败,禁止访问"));
+		response.setStatus(HttpStatus.HTTP_FORBIDDEN);
+		PrintWriter printWriter = response.getWriter();
+		printWriter.append(objectMapper.writeValueAsString(result));
+	}
+}

+ 105 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/compoent/PigxWebResponseExceptionTranslator.java

@@ -0,0 +1,105 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.security.compoent;
+
+import com.pig4cloud.pigx.common.security.exception.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.oauth2.common.DefaultThrowableAnalyzer;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException;
+import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
+import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
+import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
+import org.springframework.security.web.util.ThrowableAnalyzer;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+
+import java.io.IOException;
+
+/**
+ * @author lengleng
+ * @date 2018/7/8
+ * 异常处理,重写oauth 默认实现
+ */
+@Slf4j
+public class PigxWebResponseExceptionTranslator implements WebResponseExceptionTranslator {
+
+	private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
+
+	@Override
+	public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
+
+		// Try to extract a SpringSecurityException from the stacktrace
+		Throwable[] causeChain = throwableAnalyzer.determineCauseChain(e);
+
+		Exception ase = (AuthenticationException) throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class,
+			causeChain);
+		if (ase != null) {
+			return handleOAuth2Exception(new UnauthorizedException(e.getMessage(), e));
+		}
+
+		ase = (AccessDeniedException) throwableAnalyzer
+			.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
+		if (ase != null) {
+			return handleOAuth2Exception(new ForbiddenException(ase.getMessage(), ase));
+		}
+
+		ase = (InvalidGrantException) throwableAnalyzer
+			.getFirstThrowableOfType(InvalidGrantException.class, causeChain);
+		if (ase != null) {
+			return handleOAuth2Exception(new InvalidException(ase.getMessage(), ase));
+		}
+
+		ase = (HttpRequestMethodNotSupportedException) throwableAnalyzer
+			.getFirstThrowableOfType(HttpRequestMethodNotSupportedException.class, causeChain);
+		if (ase != null) {
+			return handleOAuth2Exception(new MethodNotAllowed(ase.getMessage(), ase));
+		}
+
+		 ase = (OAuth2Exception) throwableAnalyzer.getFirstThrowableOfType(
+			OAuth2Exception.class, causeChain);
+
+		if (ase != null) {
+			return handleOAuth2Exception((OAuth2Exception) ase);
+		}
+
+		return handleOAuth2Exception(new ServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(), e));
+
+	}
+
+	private ResponseEntity<OAuth2Exception> handleOAuth2Exception(OAuth2Exception e) throws IOException {
+
+		int status = e.getHttpErrorCode();
+		HttpHeaders headers = new HttpHeaders();
+		headers.set("Cache-Control", "no-store");
+		headers.set("Pragma", "no-cache");
+		if (status == HttpStatus.UNAUTHORIZED.value() || (e instanceof InsufficientScopeException)) {
+			headers.set("WWW-Authenticate", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, e.getSummary()));
+		}
+
+		ResponseEntity<OAuth2Exception> response = new ResponseEntity<>(new PigxAuth2Exception(e.getMessage()), headers,
+			HttpStatus.valueOf(status));
+
+		return response;
+
+	}
+}

+ 62 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/compoent/ResourceAuthExceptionEntryPoint.java

@@ -0,0 +1,62 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.security.compoent;
+
+import cn.hutool.http.HttpStatus;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.pig4cloud.pigx.common.core.constant.CommonConstant;
+import com.pig4cloud.pigx.common.core.util.R;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author lengleng
+ * @date 2018/7/8
+ * 客户端异常处理
+ * 1. 可以根据 AuthenticationException 不同细化异常处理
+ */
+@Slf4j
+@Component
+@AllArgsConstructor
+public class ResourceAuthExceptionEntryPoint implements AuthenticationEntryPoint {
+	private final ObjectMapper objectMapper;
+
+	@Override
+	public void commence(HttpServletRequest request, HttpServletResponse response,
+						 AuthenticationException authException) throws IOException {
+		response.setCharacterEncoding(CommonConstant.UTF8);
+		response.setContentType(CommonConstant.CONTENT_TYPE);
+		R<String> result = new R<>();
+		result.setCode(HttpStatus.HTTP_UNAUTHORIZED);
+		if (authException != null) {
+			result.setMsg("error");
+			result.setData(authException.getMessage());
+		}
+		response.setStatus(HttpStatus.HTTP_UNAUTHORIZED);
+		PrintWriter printWriter = response.getWriter();
+		printWriter.append(objectMapper.writeValueAsString(result));
+	}
+}

+ 43 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/ForbiddenException.java

@@ -0,0 +1,43 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.security.exception;
+
+import org.springframework.http.HttpStatus;
+
+/**
+ * @author lengleng
+ * @date 2018/7/8
+ */
+public class ForbiddenException extends PigxAuth2Exception {
+
+	public ForbiddenException(String msg, Throwable t) {
+		super(msg);
+	}
+
+	@Override
+	public String getOAuth2ErrorCode() {
+		return "access_denied";
+	}
+
+	@Override
+	public int getHttpErrorCode() {
+		return HttpStatus.FORBIDDEN.value();
+	}
+
+}
+

+ 40 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/InvalidException.java

@@ -0,0 +1,40 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.security.exception;
+
+/**
+ * @author lengleng
+ * @date 2018/7/8
+ */
+public class InvalidException extends PigxAuth2Exception {
+
+	public InvalidException(String msg, Throwable t) {
+		super(msg);
+	}
+
+	@Override
+	public String getOAuth2ErrorCode() {
+		return "invalid_exception";
+	}
+
+	@Override
+	public int getHttpErrorCode() {
+		return 426;
+	}
+
+}

+ 42 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/MethodNotAllowed.java

@@ -0,0 +1,42 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.security.exception;
+
+import org.springframework.http.HttpStatus;
+
+/**
+ * @author lengleng
+ * @date 2018/7/8
+ */
+public class MethodNotAllowed extends PigxAuth2Exception {
+
+	public MethodNotAllowed(String msg, Throwable t) {
+		super(msg);
+	}
+
+	@Override
+	public String getOAuth2ErrorCode() {
+		return "method_not_allowed";
+	}
+
+	@Override
+	public int getHttpErrorCode() {
+		return HttpStatus.METHOD_NOT_ALLOWED.value();
+	}
+
+}

+ 34 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/PigxAuth2Exception.java

@@ -0,0 +1,34 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.security.exception;
+
+import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
+
+import java.util.Map;
+
+/**
+ * @author lengleng
+ * @date 2018/7/8
+ * 自定义OAuth2Exception
+ */
+public class PigxAuth2Exception extends OAuth2Exception {
+
+	public PigxAuth2Exception(String msg) {
+		super(msg);
+	}
+}

+ 42 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/ServerErrorException.java

@@ -0,0 +1,42 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.security.exception;
+
+import org.springframework.http.HttpStatus;
+
+/**
+ * @author lengleng
+ * @date 2018/7/8
+ */
+public class ServerErrorException extends PigxAuth2Exception {
+
+	public ServerErrorException(String msg, Throwable t) {
+		super(msg);
+	}
+
+	@Override
+	public String getOAuth2ErrorCode() {
+		return "server_error";
+	}
+
+	@Override
+	public int getHttpErrorCode() {
+		return HttpStatus.INTERNAL_SERVER_ERROR.value();
+	}
+
+}

+ 42 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/exception/UnauthorizedException.java

@@ -0,0 +1,42 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.security.exception;
+
+import org.springframework.http.HttpStatus;
+
+/**
+ * @author lengleng
+ * @date 2018/7/8
+ */
+public class UnauthorizedException extends PigxAuth2Exception {
+
+	public UnauthorizedException(String msg, Throwable t) {
+		super(msg);
+	}
+
+	@Override
+	public String getOAuth2ErrorCode() {
+		return "unauthorized";
+	}
+
+	@Override
+	public int getHttpErrorCode() {
+		return HttpStatus.UNAUTHORIZED.value();
+	}
+
+}

+ 44 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/interceptor/PigxFeignClientIntercept.java

@@ -0,0 +1,44 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.security.interceptor;
+
+import feign.RequestInterceptor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.oauth2.client.OAuth2ClientContext;
+import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
+
+/**
+ * @author lengleng
+ * @date 2018/6/22
+ * feign 拦截器传递 header 中oauth token,
+ * 使用hystrix 的信号量模式
+ */
+@Configuration
+@ConditionalOnProperty("security.oauth2.client.client-id")
+public class PigxFeignClientIntercept {
+	@Bean
+	public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext,
+															OAuth2ProtectedResourceDetails resource) {
+		return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, resource);
+	}
+}

+ 94 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/SecurityUtils.java

@@ -0,0 +1,94 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.common.security.util;
+
+
+import cn.hutool.core.util.StrUtil;
+import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 安全工具类
+ *
+ * @author L.cm
+ */
+public class SecurityUtils {
+
+	/**
+	 * 获取Authentication
+	 */
+	public static Authentication getAuthentication() {
+		return SecurityContextHolder.getContext().getAuthentication();
+	}
+
+	/**
+	 * 获取用户
+	 */
+	public static String getUser(Authentication authentication) {
+		Object principal = authentication.getPrincipal();
+		if (principal == null) {
+			return null;
+		}
+		return (String) principal;
+	}
+
+	public static String getClientId() {
+		Authentication authentication = getAuthentication();
+		if (authentication instanceof OAuth2Authentication) {
+			OAuth2Authentication auth2Authentication = (OAuth2Authentication) authentication;
+			return auth2Authentication.getOAuth2Request().getClientId();
+		}
+		return null;
+	}
+
+	/**
+	 * 获取用户
+	 */
+	public static String getUser() {
+		Authentication authentication = getAuthentication();
+		if (authentication == null) {
+			return null;
+		}
+		return getUser(authentication);
+	}
+
+	/**
+	 * 获取用户角色信息
+	 *
+	 * @return 角色集合
+	 */
+	public static List<String> getRoles() {
+		Authentication authentication = getAuthentication();
+		Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
+
+		List<String> roles = new ArrayList<>();
+		authorities.stream()
+			.filter(granted -> StrUtil.startWith(granted.getAuthority(), SecurityConstants.ROLE))
+			.forEach(granted -> roles.add(StrUtil.removePrefix(granted.getAuthority(), SecurityConstants.ROLE)));
+		return roles;
+	}
+}

+ 1 - 0
pigx-common/pigx-common-security/src/main/resources/META-INF/spring-devtools.properties

@@ -0,0 +1 @@
+restart.include.pigx-common-security=/pigx-common-security[\\w-]+\.jar

+ 5 - 0
pigx-common/pigx-common-security/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,5 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  com.pig4cloud.pigx.common.security.compoent.PermissionService,\
+  com.pig4cloud.pigx.common.security.compoent.PigAccessDeniedHandler,\
+  com.pig4cloud.pigx.common.security.compoent.ResourceAuthExceptionEntryPoint,\
+  com.pig4cloud.pigx.common.security.interceptor.PigxFeignClientIntercept

+ 1 - 0
pigx-common/pigx-common-security/src/main/resources/META-INF/spring.provides

@@ -0,0 +1 @@
+provides: pigx-common-core, spring-cloud-starter-security

+ 64 - 0
pigx-common/pigx-common-security/src/main/resources/org/springframework/security/messages_zh_CN.properties

@@ -0,0 +1,64 @@
+#
+#
+#      Copyright (c) 2018-2025, lengleng All rights reserved.
+#
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice,
+#  this list of conditions and the following disclaimer.
+#  Redistributions in binary form must reproduce the above copyright
+#  notice, this list of conditions and the following disclaimer in the
+#  documentation and/or other materials provided with the distribution.
+#  Neither the name of the pig4cloud.com developer nor the names of its
+#  contributors may be used to endorse or promote products derived from
+#  this software without specific prior written permission.
+#  Author: lengleng (wangiegie@gmail.com)
+#
+#
+AbstractAccessDecisionManager.accessDenied=\u4E0D\u5141\u8BB8\u8BBF\u95EE
+AbstractLdapAuthenticationProvider.emptyPassword=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
+AbstractSecurityInterceptor.authenticationNotFound=\u672A\u5728SecurityContext\u4E2D\u67E5\u627E\u5230\u8BA4\u8BC1\u5BF9\u8C61
+AbstractUserDetailsAuthenticationProvider.badCredentials=\u7528\u6237\u540D\u4E0D\u5B58\u5728\u6216\u8005\u5BC6\u7801\u9519\u8BEF
+AbstractUserDetailsAuthenticationProvider.credentialsExpired=\u7528\u6237\u51ED\u8BC1\u5DF2\u8FC7\u671F
+AbstractUserDetailsAuthenticationProvider.disabled=\u7528\u6237\u672A\u6FC0\u6D3B
+AbstractUserDetailsAuthenticationProvider.expired=\u7528\u6237\u5E10\u53F7\u5DF2\u8FC7\u671F
+AbstractUserDetailsAuthenticationProvider.locked=\u7528\u6237\u5E10\u53F7\u5DF2\u88AB\u9501\u5B9A
+AbstractUserDetailsAuthenticationProvider.onlySupports=\u4EC5\u4EC5\u652F\u6301UsernamePasswordAuthenticationToken
+AccountStatusUserDetailsChecker.credentialsExpired=\u7528\u6237\u51ED\u8BC1\u5DF2\u8FC7\u671F
+AccountStatusUserDetailsChecker.disabled=\u7528\u6237\u672A\u6FC0\u6D3B
+AccountStatusUserDetailsChecker.expired=\u7528\u6237\u5E10\u53F7\u5DF2\u8FC7\u671F
+AccountStatusUserDetailsChecker.locked=\u7528\u6237\u5E10\u53F7\u5DF2\u88AB\u9501\u5B9A
+AclEntryAfterInvocationProvider.noPermission=\u7ED9\u5B9A\u7684Authentication\u5BF9\u8C61({0})\u6839\u672C\u65E0\u6743\u64CD\u63A7\u9886\u57DF\u5BF9\u8C61({1})
+AnonymousAuthenticationProvider.incorrectKey=\u5C55\u793A\u7684AnonymousAuthenticationToken\u4E0D\u542B\u6709\u9884\u671F\u7684key
+BindAuthenticator.badCredentials=\u5BC6\u7801\u9519\u8BEF
+BindAuthenticator.emptyPassword=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
+CasAuthenticationProvider.incorrectKey=\u5C55\u793A\u7684CasAuthenticationToken\u4E0D\u542B\u6709\u9884\u671F\u7684key
+CasAuthenticationProvider.noServiceTicket=\u672A\u80FD\u591F\u6B63\u786E\u63D0\u4F9B\u5F85\u9A8C\u8BC1\u7684CAS\u670D\u52A1\u7968\u6839
+ConcurrentSessionControlAuthenticationStrategy.exceededAllowed=\u5DF2\u7ECF\u8D85\u8FC7\u4E86\u5F53\u524D\u4E3B\u4F53({0})\u88AB\u5141\u8BB8\u7684\u6700\u5927\u4F1A\u8BDD\u6570\u91CF
+DigestAuthenticationFilter.incorrectRealm=\u54CD\u5E94\u7ED3\u679C\u4E2D\u7684Realm\u540D\u5B57({0})\u540C\u7CFB\u7EDF\u6307\u5B9A\u7684Realm\u540D\u5B57({1})\u4E0D\u543B\u5408
+DigestAuthenticationFilter.incorrectResponse=\u9519\u8BEF\u7684\u54CD\u5E94\u7ED3\u679C
+DigestAuthenticationFilter.missingAuth=\u9057\u6F0F\u4E86\u9488\u5BF9'auth' QOP\u7684\u3001\u5FC5\u987B\u7ED9\u5B9A\u7684\u6458\u8981\u53D6\u503C; \u63A5\u6536\u5230\u7684\u5934\u4FE1\u606F\u4E3A{0}
+DigestAuthenticationFilter.missingMandatory=\u9057\u6F0F\u4E86\u5FC5\u987B\u7ED9\u5B9A\u7684\u6458\u8981\u53D6\u503C; \u63A5\u6536\u5230\u7684\u5934\u4FE1\u606F\u4E3A{0}
+DigestAuthenticationFilter.nonceCompromised=Nonce\u4EE4\u724C\u5DF2\u7ECF\u5B58\u5728\u95EE\u9898\u4E86\uFF0C{0}
+DigestAuthenticationFilter.nonceEncoding=Nonce\u672A\u7ECF\u8FC7Base64\u7F16\u7801; \u76F8\u5E94\u7684nonce\u53D6\u503C\u4E3A {0}
+DigestAuthenticationFilter.nonceExpired=Nonce\u5DF2\u7ECF\u8FC7\u671F/\u8D85\u65F6
+DigestAuthenticationFilter.nonceNotNumeric=Nonce\u4EE4\u724C\u7684\u7B2C1\u90E8\u5206\u5E94\u8BE5\u662F\u6570\u5B57\uFF0C\u4F46\u7ED3\u679C\u5374\u662F{0}
+DigestAuthenticationFilter.nonceNotTwoTokens=Nonce\u5E94\u8BE5\u7531\u4E24\u90E8\u5206\u53D6\u503C\u6784\u6210\uFF0C\u4F46\u7ED3\u679C\u5374\u662F{0}
+DigestAuthenticationFilter.usernameNotFound=\u7528\u6237\u540D{0}\u672A\u627E\u5230
+JdbcDaoImpl.noAuthority=\u6CA1\u6709\u4E3A\u7528\u6237{0}\u6307\u5B9A\u89D2\u8272
+JdbcDaoImpl.notFound=\u672A\u627E\u5230\u7528\u6237{0}
+LdapAuthenticationProvider.badCredentials=\u574F\u7684\u51ED\u8BC1
+LdapAuthenticationProvider.credentialsExpired=\u7528\u6237\u51ED\u8BC1\u5DF2\u8FC7\u671F
+LdapAuthenticationProvider.disabled=\u7528\u6237\u672A\u6FC0\u6D3B
+LdapAuthenticationProvider.expired=\u7528\u6237\u5E10\u53F7\u5DF2\u8FC7\u671F
+LdapAuthenticationProvider.locked=\u7528\u6237\u5E10\u53F7\u5DF2\u88AB\u9501\u5B9A
+LdapAuthenticationProvider.emptyUsername=\u7528\u6237\u540D\u4E0D\u5141\u8BB8\u4E3A\u7A7A
+LdapAuthenticationProvider.onlySupports=\u4EC5\u4EC5\u652F\u6301UsernamePasswordAuthenticationToken
+PasswordComparisonAuthenticator.badCredentials=\u574F\u7684\u51ED\u8BC1
+ProviderManager.providerNotFound=\u672A\u67E5\u627E\u5230\u9488\u5BF9{0}\u7684AuthenticationProvider
+RememberMeAuthenticationProvider.incorrectKey=\u5C55\u793ARememberMeAuthenticationToken\u4E0D\u542B\u6709\u9884\u671F\u7684key
+RunAsImplAuthenticationProvider.incorrectKey=\u5C55\u793A\u7684RunAsUserToken\u4E0D\u542B\u6709\u9884\u671F\u7684key
+SubjectDnX509PrincipalExtractor.noMatching=\u672A\u5728subjectDN\: {0}\u4E2D\u627E\u5230\u5339\u914D\u7684\u6A21\u5F0F
+SwitchUserFilter.noCurrentUser=\u4E0D\u5B58\u5728\u5F53\u524D\u7528\u6237
+SwitchUserFilter.noOriginalAuthentication=\u4E0D\u80FD\u591F\u67E5\u627E\u5230\u539F\u5148\u7684\u5DF2\u8BA4\u8BC1\u5BF9\u8C61

+ 58 - 0
pigx-common/pigx-common-swagger/pom.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng (wangiegie@gmail.com)
+  ~
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx-common</artifactId>
+		<version>${pigx.version}</version>
+	</parent>
+
+	<artifactId>pigx-common-swagger</artifactId>
+	<version>${pigx.version}</version>
+	<packaging>jar</packaging>
+	<name>pigx-common-log</name>
+	<description>pigx 接口文档</description>
+
+
+	<dependencies>
+		<!--安全模块支持swagger security-->
+		<dependency>
+			<groupId>com.pig4cloud</groupId>
+			<artifactId>pigx-common-security</artifactId>
+			<version>${pigx.version}</version>
+		</dependency>
+		<!--server-api-->
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>javax.servlet-api</artifactId>
+			<version>${servlet-api.version}</version>
+			<scope>provided</scope>
+		</dependency>
+		<!--swagger 依赖-->
+		<dependency>
+			<groupId>io.springfox</groupId>
+			<artifactId>springfox-swagger2</artifactId>
+			<version>${swagger.version}</version>
+		</dependency>
+	</dependencies>
+</project>

+ 36 - 0
pigx-common/pigx-common-swagger/src/main/java/com/pig4cloud/pigx/common/swagger/annotation/EnablePigxSwagger2.java

@@ -0,0 +1,36 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.swagger.annotation;
+
+import com.pig4cloud.pigx.common.swagger.config.SwaggerAutoConfiguration;
+import org.springframework.context.annotation.Import;
+
+import java.lang.annotation.*;
+
+/**
+ * @author lengleng
+ * @date 2018/7/21
+ * 开启pigx swagger
+ */
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+@Import({SwaggerAutoConfiguration.class})
+public @interface EnablePigxSwagger2 {
+}

+ 93 - 0
pigx-common/pigx-common-swagger/src/main/java/com/pig4cloud/pigx/common/swagger/config/SwaggerAutoConfiguration.java

@@ -0,0 +1,93 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+package com.pig4cloud.pigx.common.swagger.config;
+
+
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.*;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Sywd
+ * swagger配置
+ */
+@Configuration
+@EnableSwagger2
+@EnableAutoConfiguration
+public class SwaggerAutoConfiguration {
+
+	@Bean
+	public Docket api() {
+		return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
+			.apis(RequestHandlerSelectors.any()).paths(PathSelectors.any())
+			.build().securitySchemes(Collections.singletonList(securitySchema()))
+			.securityContexts(Collections.singletonList(securityContext())).pathMapping("/");
+	}
+
+	private SecurityContext securityContext() {
+		return SecurityContext.builder().securityReferences(defaultAuth())
+			.forPaths(PathSelectors.ant("/**"))
+			.build();
+	}
+
+	private List<SecurityReference> defaultAuth() {
+
+		final AuthorizationScope[] authorizationScopes = new AuthorizationScope[3];
+		authorizationScopes[0] = new AuthorizationScope("read", "read all");
+		authorizationScopes[1] = new AuthorizationScope("trust", "trust all");
+		authorizationScopes[2] = new AuthorizationScope("write", "write all");
+
+		return Collections.singletonList(new SecurityReference("pigX OAuth", authorizationScopes));
+	}
+
+
+	private OAuth securitySchema() {
+		ArrayList authorizationScopeList = new ArrayList();
+		authorizationScopeList.add(new AuthorizationScope("server", "server all"));
+		authorizationScopeList.add(new AuthorizationScope("read", "read all"));
+		authorizationScopeList.add(new AuthorizationScope("write", "access all"));
+
+		ArrayList grantTypes = new ArrayList();
+		GrantType creGrant = new ResourceOwnerPasswordCredentialsGrant("http://localhost:9999/auth/oauth/token");
+
+		grantTypes.add(creGrant);
+		return new OAuth("pigX OAuth", authorizationScopeList, grantTypes);
+	}
+
+	private ApiInfo apiInfo() {
+		return new ApiInfoBuilder()
+			.title("PigX Swagger API ")
+			.description("https://gitee.com/log4j/pig/wikis")
+			.termsOfServiceUrl("https://gitee.wang/pig/pigx")
+			.contact(new Contact("冷冷", "https://gitee.wang/pig/pigx", "wangiegie@gmail.com"))
+			.version("2.0")
+			.build();
+	}
+
+}

+ 42 - 0
pigx-common/pom.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng (wangiegie@gmail.com)
+  ~
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx</artifactId>
+		<version>${pigx.version}</version>
+	</parent>
+
+	<artifactId>pigx-common</artifactId>
+	<version>${pigx.version}</version>
+	<packaging>pom</packaging>
+	<name>pigx-common</name>
+	<description>pigx 公共聚合模块</description>
+
+	<modules>
+		<module>pigx-common-core</module>
+		<module>pigx-common-log</module>
+		<module>pigx-common-security</module>
+		<module>pigx-common-swagger</module>
+	</modules>
+</project>

+ 13 - 0
pigx-config/Dockerfile

@@ -0,0 +1,13 @@
+FROM anapsix/alpine-java:8_server-jre_unlimited
+
+MAINTAINER wangiegie@gmail.com
+
+RUN mkdir -p /pigx/bin/com.pig4cloud/pigx-config
+
+WORKDIR /pigx/bin/com.pig4cloud/pigx-config
+
+EXPOSE 1025
+
+ADD ./pigx-config/target/pigx-config.jar ./
+
+CMD java -Djava.security.egd=file:/dev/./urandom -jar pigx-config.jar

+ 75 - 0
pigx-config/pom.xml

@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng (wangiegie@gmail.com)
+  ~
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx</artifactId>
+		<version>${pigx.version}</version>
+	</parent>
+
+	<artifactId>pigx-config</artifactId>
+	<version>${pigx.version}</version>
+	<packaging>jar</packaging>
+
+	<name>pigx-config</name>
+	<description>pigx 配置中心,基于spring cloud config</description>
+
+	<dependencies>
+		<!--配置中心-->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-config-server</artifactId>
+		</dependency>
+		<!--web 模块-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+			<exclusions>
+				<!--排除tomcat依赖-->
+				<exclusion>
+					<artifactId>spring-boot-starter-tomcat</artifactId>
+					<groupId>org.springframework.boot</groupId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<!--undertow容器-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-undertow</artifactId>
+		</dependency>
+	</dependencies>
+
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<configuration>
+					<finalName>${project.name}</finalName>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

+ 38 - 0
pigx-config/src/main/java/com/pig4cloud/pigx/config/PigxConfigApplication.java

@@ -0,0 +1,38 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.config;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.cloud.client.SpringCloudApplication;
+import org.springframework.cloud.config.server.EnableConfigServer;
+
+/**
+ * @author lengleng
+ * @date 2018年06月22日
+ * 配置中心
+ */
+@EnableConfigServer
+@SpringCloudApplication
+public class PigxConfigApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(PigxConfigApplication.class, args);
+	}
+}

+ 29 - 0
pigx-config/src/main/resources/bootstrap.yml

@@ -0,0 +1,29 @@
+server:
+  port: 4001
+
+spring:
+  application:
+    name: pigx-config
+  profiles:
+    active: native
+  # 配置中心
+  cloud:
+    config:
+      server:
+        native:
+          search-locations: classpath:/config/
+
+# 注册中心配置
+eureka:
+  instance:
+    prefer-ip-address: true
+  client:
+    service-url:
+      defaultZone: http://pig:pig@localhost:1025/eureka/
+
+# 暴露监控端点
+management:
+  endpoints:
+    web:
+      exposure:
+        include: '*'

+ 48 - 0
pigx-config/src/main/resources/config/application-dev.yml

@@ -0,0 +1,48 @@
+# redis 相关
+spring:
+  redis:
+    password:
+    host: localhost
+# 暴露监控端点
+management:
+  endpoints:
+    web:
+      exposure:
+        include: '*'
+
+# feign 配置
+feign:
+  hystrix:
+    enabled: true
+  okhttp:
+    enabled: true
+  httpclient:
+    enabled: false
+  client:
+    config:
+      feignName:
+        connectTimeout: 10000
+        readTimeout: 10000
+  compression:
+    request:
+      enabled: true
+    response:
+      enabled: true
+# hystrix If you need to use ThreadLocal bound variables in your RequestInterceptor`s
+# you will need to either set the thread isolation strategy for Hystrix to `SEMAPHORE or disable Hystrix in Feign.
+hystrix:
+  command:
+    default:
+      execution:
+        isolation:
+          strategy: SEMAPHORE
+          thread:
+            timeoutInMilliseconds: 60000
+  shareSecurityContext: true
+
+#请求处理的超时时间
+ribbon:
+  ReadTimeout: 10000
+  ConnectTimeout: 10000
+
+

+ 8 - 0
pigx-config/src/main/resources/config/pigx-auth-dev.yml

@@ -0,0 +1,8 @@
+# 数据源
+spring:
+  datasource:
+    type: com.zaxxer.hikari.HikariDataSource
+    driver-class-name: com.mysql.jdbc.Driver
+    username: root
+    password: root
+    url: jdbc:mysql://114.116.45.246:13306/pigx?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false

+ 49 - 0
pigx-config/src/main/resources/config/pigx-gateway-dev.yml

@@ -0,0 +1,49 @@
+spring:
+  cloud:
+    gateway:
+      locator:
+        enabled: true
+      routes:
+      - id: pigx-auth
+        uri: lb://pigx-auth
+        predicates:
+        - Path=/auth/**
+        filters:
+          # 验证码处理
+        - ImageCodeGatewayFilter
+          # 前端密码解密
+        - PasswordDecoderFilter
+        - StripPrefix=1
+      - id: pigx-upms
+        uri: lb://pigx-upms
+        predicates:
+        - Path=/admin/**
+        filters:
+          # Swagger请求头处理
+        - SwaggerHeaderFilter
+          # 请求头清理避免不合法请求头
+        - name: RemoveRequestHeader
+          args:
+            name: from
+          # 限流配置
+        - name: RequestRateLimiter
+          args:
+            key-resolver: '#{@remoteAddrKeyResolver}'
+            redis-rate-limiter.replenishRate: 10
+            redis-rate-limiter.burstCapacity: 20
+        - StripPrefix=1
+          # 降级配置
+        - name: Hystrix
+          args:
+            name: default
+            fallbackUri: 'forward:/fallback'
+
+security:
+  encode:
+    # 前端密码密钥,必须16位
+    key: 'pigxpigxpigxpigx'
+
+# 不校验验证码终端
+ignore:
+  clients:
+    - test

+ 40 - 0
pigx-config/src/main/resources/config/pigx-upms-dev.yml

@@ -0,0 +1,40 @@
+## spring security 配置
+security:
+  oauth2:
+    client:
+      client-id: pig
+      client-secret: pig
+      scope: server
+    resource:
+      token-info-uri: http://localhost:9999/auth/oauth/check_token
+
+# 数据源
+spring:
+  datasource:
+    type: com.zaxxer.hikari.HikariDataSource
+    driver-class-name: com.mysql.jdbc.Driver
+    username: root
+    password: root
+    url: jdbc:mysql://114.116.45.246:13306/pigx?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false
+
+#mybaits-plus配置,修改主键类型,mapper.xml、type 别名等
+mybatis-plus:
+  mapper-locations: classpath:/mapper/*Mapper.xml
+  typeAliasesPackage: com.pig4cloud.pigx.admin.api.entity
+  global-config:
+    #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
+    id-type: 0
+    #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
+    field-strategy: 1
+    #驼峰下划线转换
+    db-column-underline: true
+    #刷新mapper 调试神器
+    refresh-mapper: true
+    # 逻辑删除字段
+    logic-delete-value: 1
+    logic-not-delete-value: 0
+    #自定义SQL注入器
+    sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector
+  configuration:
+    map-underscore-to-camel-case: true
+    cache-enabled: true

+ 13 - 0
pigx-eureka/Dockerfile

@@ -0,0 +1,13 @@
+FROM anapsix/alpine-java:8_server-jre_unlimited
+
+MAINTAINER wangiegie@gmail.com
+
+RUN mkdir -p /pigx/bin/com.pig4cloud/pigx-eureka
+
+WORKDIR /pigx/bin/com.pig4cloud/pigx-eureka
+
+EXPOSE 1025
+
+ADD ./pigx-eureka/target/pigx-eureka.jar ./
+
+CMD java -Djava.security.egd=file:/dev/./urandom -jar pigx-eureka.jar

+ 80 - 0
pigx-eureka/pom.xml

@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng (wangiegie@gmail.com)
+  ~
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx</artifactId>
+		<version>${pigx.version}</version>
+	</parent>
+
+	<groupId>com.pig4cloud.pigx</groupId>
+	<artifactId>pigx-eureka</artifactId>
+	<version>${pigx.version}</version>
+	<packaging>jar</packaging>
+
+	<name>pigx-eureka</name>
+	<description>pigx 服务中心,基于eureka</description>
+
+	<dependencies>
+		<!--服务中心-->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
+		</dependency>
+		<!--security-->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-security</artifactId>
+		</dependency>
+		<!--web 模块-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+			<exclusions>
+				<!--排除tomcat依赖-->
+				<exclusion>
+					<artifactId>spring-boot-starter-tomcat</artifactId>
+					<groupId>org.springframework.boot</groupId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<!--undertow容器-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-undertow</artifactId>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<configuration>
+					<finalName>${project.name}</finalName>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

+ 39 - 0
pigx-eureka/src/main/java/com/pig4cloud/pigx/eureka/PigxEurekaApplication.java

@@ -0,0 +1,39 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.eureka;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+/**
+ * @author lengleng
+ * @date 2018年06月21日
+ * 服务中心
+ */
+@EnableEurekaServer
+@SpringBootApplication
+public class PigxEurekaApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(PigxEurekaApplication.class, args);
+	}
+}

+ 39 - 0
pigx-eureka/src/main/java/com/pig4cloud/pigx/eureka/security/WebSecurityConfig.java

@@ -0,0 +1,39 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.eureka.security;
+
+/**
+ * @author lengleng
+ * @date 2018/7/12
+ */
+
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+	@Override
+	protected void configure(HttpSecurity http) throws Exception {
+		http.csrf().disable()
+			.authorizeRequests()
+			.antMatchers("actuator/**").permitAll()
+			.anyRequest()
+			.authenticated().and().httpBasic();
+	}
+}

+ 32 - 0
pigx-eureka/src/main/resources/bootstrap.yml

@@ -0,0 +1,32 @@
+server:
+  port: 1025
+
+spring:
+  security:
+    user:
+      name: pig
+      password: pig
+  application:
+    name: pigx-eureka
+
+# docker-compose部署时候 hostname 换成pigx-eureka
+# 类似的 redis 使用pigx-redis ,gateway 换成 pigx-gateway
+eureka:
+  instance:
+    hostname: localhost
+    prefer-ip-address: true
+  client:
+    register-with-eureka: false
+    fetch-registry: false
+    service-url:
+      defaultZone: http://pig:pig@${eureka.instance.hostname}:${server.port}/eureka/
+  server:
+    eviction-interval-timer-in-ms: 4000
+    enable-self-preservation: false
+    renewal-percent-threshold: 0.9
+
+management:
+  endpoints:
+    web:
+      exposure:
+        include: '*'

+ 13 - 0
pigx-gateway/Dockerfile

@@ -0,0 +1,13 @@
+FROM anapsix/alpine-java:8_server-jre_unlimited
+
+MAINTAINER wangiegie@gmail.com
+
+RUN mkdir -p /pigx/bin/com.pig4cloud/pigx-gateway
+
+WORKDIR /pigx/bin/com.pig4cloud/pigx-gateway
+
+EXPOSE 1025
+
+ADD ./pigx-gateway/target/pigx-gateway.jar ./
+
+CMD java -Djava.security.egd=file:/dev/./urandom -jar pigx-gateway.jar

+ 88 - 0
pigx-gateway/pom.xml

@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~
+  ~      Copyright (c) 2018-2025, lengleng All rights reserved.
+  ~
+  ~  Redistribution and use in source and binary forms, with or without
+  ~  modification, are permitted provided that the following conditions are met:
+  ~
+  ~ Redistributions of source code must retain the above copyright notice,
+  ~  this list of conditions and the following disclaimer.
+  ~  Redistributions in binary form must reproduce the above copyright
+  ~  notice, this list of conditions and the following disclaimer in the
+  ~  documentation and/or other materials provided with the distribution.
+  ~  Neither the name of the pig4cloud.com developer nor the names of its
+  ~  contributors may be used to endorse or promote products derived from
+  ~  this software without specific prior written permission.
+  ~  Author: lengleng (wangiegie@gmail.com)
+  ~
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx</artifactId>
+		<version>${pigx.version}</version>
+	</parent>
+
+	<artifactId>pigx-gateway</artifactId>
+	<version>${pigx.version}</version>
+	<packaging>jar</packaging>
+	<name>pigx-gateway</name>
+	<description>pigx 服务网关,基于 spring cloud gateway</description>
+
+	<dependencies>
+		<!--gateway 网关依赖,内置webflux 依赖-->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-gateway</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
+		</dependency>
+		<!--配置中心客户端-->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-config</artifactId>
+		</dependency>
+		<!--验证码-->
+		<dependency>
+			<groupId>com.github.axet</groupId>
+			<artifactId>kaptcha</artifactId>
+			<version>${kaptcha.version}</version>
+		</dependency>
+		<!--hutool-->
+		<dependency>
+			<groupId>cn.hutool</groupId>
+			<artifactId>hutool-all</artifactId>
+			<version>${hutool.version}</version>
+		</dependency>
+		<!--接口文档-->
+		<dependency>
+			<groupId>io.springfox</groupId>
+			<artifactId>springfox-swagger-ui</artifactId>
+			<version>${swagger.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>io.springfox</groupId>
+			<artifactId>springfox-swagger2</artifactId>
+			<version>${swagger.version}</version>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<configuration>
+					<finalName>${project.name}</finalName>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

+ 37 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/PigxGatewayApplication.java

@@ -0,0 +1,37 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.gateway;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.cloud.client.SpringCloudApplication;
+
+/**
+ * @author lengleng
+ * @date 2018年06月21日
+ * 网关应用
+ */
+@SpringCloudApplication
+public class PigxGatewayApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(PigxGatewayApplication.class, args);
+	}
+}

+ 41 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/FilterIgnorePropertiesConfig.java

@@ -0,0 +1,41 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.config;
+
+import lombok.Data;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author lengleng
+ * @date 2018/7/22
+ * 网关不简要终端配置
+ */
+@Data
+@Configuration
+@RefreshScope
+@ConditionalOnExpression("!'${ignore}'.isEmpty()")
+@ConfigurationProperties(prefix = "ignore")
+public class FilterIgnorePropertiesConfig {
+	private List<String> clients = new ArrayList<>();
+}

+ 89 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/KaptchaConfiguration.java

@@ -0,0 +1,89 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.config;
+
+import com.google.code.kaptcha.impl.DefaultKaptcha;
+import com.google.code.kaptcha.util.Config;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Properties;
+
+/**
+ * @author lengleng
+ * @date 2017-12-21 21:12:18
+ */
+@Configuration
+public class KaptchaConfiguration {
+
+	private static final String KAPTCHA_BORDER = "kaptcha.border";
+	private static final String KAPTCHA_TEXTPRODUCER_FONT_COLOR = "kaptcha.textproducer.font.color";
+	private static final String KAPTCHA_TEXTPRODUCER_CHAR_SPACE = "kaptcha.textproducer.char.space";
+	private static final String KAPTCHA_IMAGE_WIDTH = "kaptcha.image.width";
+	private static final String KAPTCHA_IMAGE_HEIGHT = "kaptcha.image.height";
+	private static final String KAPTCHA_TEXTPRODUCER_CHAR_LENGTH = "kaptcha.textproducer.char.length";
+	private static final Object KAPTCHA_IMAGE_FONT_SIZE = "kaptcha.textproducer.font.size";
+
+	/**
+	 * 默认生成图形验证码宽度
+	 */
+	private static final String DEFAULT_IMAGE_WIDTH = "100";
+
+	/**
+	 * 默认生成图像验证码高度
+	 */
+	private static final String DEFAULT_IMAGE_HEIGHT = "40";
+
+	/**
+	 * 默认生成图形验证码长度
+	 */
+	private static final String DEFAULT_IMAGE_LENGTH = "4";
+	/**
+	 * 边框颜色,合法值: r,g,b (and optional alpha) 或者 white,black,blue.
+	 */
+	private static final String DEFAULT_COLOR_FONT = "black";
+
+	/**
+	 * 图片边框
+	 */
+	private static final String DEFAULT_IMAGE_BORDER = "no";
+	/**
+	 * 默认图片间隔
+	 */
+	private static final String DEFAULT_CHAR_SPACE = "5";
+	/**
+	 * 验证码文字大小
+	 */
+	private static final String DEFAULT_IMAGE_FONT_SIZE = "30";
+
+	@Bean
+	public DefaultKaptcha producer() {
+		Properties properties = new Properties();
+		properties.put(KAPTCHA_BORDER, DEFAULT_IMAGE_BORDER);
+		properties.put(KAPTCHA_TEXTPRODUCER_FONT_COLOR, DEFAULT_COLOR_FONT);
+		properties.put(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, DEFAULT_CHAR_SPACE);
+		properties.put(KAPTCHA_IMAGE_WIDTH, DEFAULT_IMAGE_WIDTH);
+		properties.put(KAPTCHA_IMAGE_HEIGHT, DEFAULT_IMAGE_HEIGHT);
+		properties.put(KAPTCHA_IMAGE_FONT_SIZE, DEFAULT_IMAGE_FONT_SIZE);
+		properties.put(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, DEFAULT_IMAGE_LENGTH);
+		Config config = new Config(properties);
+		DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+		defaultKaptcha.setConfig(config);
+		return defaultKaptcha;
+	}
+}

+ 38 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/RateLimiterConfiguration.java

@@ -0,0 +1,38 @@
+/*
+ *
+ *      Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the pig4cloud.com developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.gateway.config;
+
+import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import reactor.core.publisher.Mono;
+
+/**
+ * @author lengleng
+ * @date 2018/7/1
+ * 路由限流配置
+ */
+@Configuration
+public class RateLimiterConfiguration {
+	@Bean(value = "remoteAddrKeyResolver")
+	public KeyResolver remoteAddrKeyResolver() {
+		return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
+	}
+}

+ 61 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/RouterFunctionConfiguration.java

@@ -0,0 +1,61 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.config;
+
+import com.pig4cloud.pigx.gateway.handle.*;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+
+/**
+ * @author lengleng
+ * @date 2018/7/5
+ * 路由配置信息
+ */
+@Slf4j
+@Configuration
+@AllArgsConstructor
+public class RouterFunctionConfiguration {
+	private final HystrixFallbackHandler hystrixFallbackHandler;
+	private final SwaggerResourceHandler swaggerResourceHandler;
+	private final SwaggerSecurityHandler swaggerSecurityHandler;
+	private final SwaggerUiHandler swaggerUiHandler;
+	private final ImageCodeHandler imageCodeHandler;
+
+	@Bean
+	public RouterFunction routerFunction() {
+		return RouterFunctions.route(
+			RequestPredicates.GET("/fallback")
+				.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), hystrixFallbackHandler)
+			.andRoute(RequestPredicates.GET("/code")
+				.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), imageCodeHandler)
+			.andRoute(RequestPredicates.GET("/swagger-resources")
+				.and(RequestPredicates.accept(MediaType.ALL)), swaggerResourceHandler)
+			.andRoute(RequestPredicates.GET("/swagger-resources/configuration/ui")
+				.and(RequestPredicates.accept(MediaType.ALL)), swaggerUiHandler)
+			.andRoute(RequestPredicates.GET("/swagger-resources/configuration/security")
+				.and(RequestPredicates.accept(MediaType.ALL)), swaggerSecurityHandler);
+
+	}
+
+}

+ 67 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/SwaggerProvider.java

@@ -0,0 +1,67 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.config;
+
+import lombok.AllArgsConstructor;
+import org.springframework.cloud.gateway.config.GatewayProperties;
+import org.springframework.cloud.gateway.route.RouteLocator;
+import org.springframework.cloud.gateway.support.NameUtils;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
+import springfox.documentation.swagger.web.SwaggerResource;
+import springfox.documentation.swagger.web.SwaggerResourcesProvider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Sywd
+ * 聚合接口文档注册,和zuul实现类似
+ */
+@Component
+@Primary
+@AllArgsConstructor
+public class SwaggerProvider implements SwaggerResourcesProvider {
+	public static final String API_URI = "/v2/api-docs";
+	private final RouteLocator routeLocator;
+	private final GatewayProperties gatewayProperties;
+
+
+	@Override
+	public List<SwaggerResource> get() {
+		List<SwaggerResource> resources = new ArrayList<>();
+		List<String> routes = new ArrayList<>();
+		routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
+		gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId()))
+			.forEach(routeDefinition -> routeDefinition.getPredicates().stream()
+				.filter(predicateDefinition -> "Path".equalsIgnoreCase(predicateDefinition.getName()))
+				.filter(predicateDefinition -> !"pigx-auth".equalsIgnoreCase(routeDefinition.getId()))
+				.forEach(predicateDefinition -> resources.add(swaggerResource(routeDefinition.getId(),
+					predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
+						.replace("/**", API_URI)))));
+		return resources;
+	}
+
+	private SwaggerResource swaggerResource(String name, String location) {
+		SwaggerResource swaggerResource = new SwaggerResource();
+		swaggerResource.setName(name);
+		swaggerResource.setLocation(location);
+		swaggerResource.setSwaggerVersion("2.0");
+		return swaggerResource;
+	}
+}

+ 47 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/exception/CheckedException.java

@@ -0,0 +1,47 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.exception;
+
+/**
+ * @author lengleng
+ * @date 2018年07月22日
+ * 异常包装类
+ */
+public class CheckedException extends Exception {
+
+	private static final long serialVersionUID = 1L;
+
+	public CheckedException() {
+	}
+
+	public CheckedException(String message) {
+		super(message);
+	}
+
+	public CheckedException(Throwable cause) {
+		super(cause);
+	}
+
+	public CheckedException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+	public CheckedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+		super(message, cause, enableSuppression, writableStackTrace);
+	}
+}

+ 25 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/exception/ValidateCodeException.java

@@ -0,0 +1,25 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.exception;
+
+/**
+ * @author lengleng
+ */
+public class ValidateCodeException extends Exception {
+
+}

+ 186 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/ImageCodeGatewayFilter.java

@@ -0,0 +1,186 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.filter;
+
+import cn.hutool.core.codec.Base64;
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.core.util.StrUtil;
+import com.pig4cloud.pigx.gateway.config.FilterIgnorePropertiesConfig;
+import com.pig4cloud.pigx.gateway.exception.CheckedException;
+import com.pig4cloud.pigx.gateway.exception.ValidateCodeException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+/**
+ * @author lengleng
+ * @date 2018/7/4
+ * 验证码处理
+ */
+@Slf4j
+@Component
+public class ImageCodeGatewayFilter extends AbstractGatewayFilterFactory {
+	public static final String DEFAULT_CODE_KEY = "DEFAULT_CODE_KEY";
+	public static final String OAUTH_TOKEN_URL = "/oauth/token";
+	@Autowired
+	private RedisTemplate redisTemplate;
+	@Autowired
+	private FilterIgnorePropertiesConfig filterIgnorePropertiesConfig;
+
+	@Override
+	public GatewayFilter apply(Object config) {
+		return (exchange, chain) -> {
+			ServerHttpRequest request = exchange.getRequest();
+
+			// 不是登录请求,直接向下执行
+			if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath(), OAUTH_TOKEN_URL)) {
+				return chain.filter(exchange);
+			}
+
+			// 终端设置不校验, 直接向下执行(1. 从请求参数中获取 2.从header取)
+			String clientId = request.getQueryParams().getFirst("client_id");
+			if (StrUtil.isNotBlank(clientId)) {
+				if (filterIgnorePropertiesConfig.getClients().contains(clientId)) {
+					return chain.filter(exchange);
+				}
+			}
+			try {
+				String[] clientInfos = extractAndDecodeHeader(request);
+				if (filterIgnorePropertiesConfig.getClients().contains(clientInfos[0])) {
+					return chain.filter(exchange);
+				}
+			} catch (Exception e) {
+				ServerHttpResponse response = exchange.getResponse();
+				response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED);
+				return response.setComplete();
+			}
+
+			//校验验证码合法性
+			try {
+				checkCode(request);
+			} catch (ValidateCodeException e) {
+				ServerHttpResponse response = exchange.getResponse();
+				response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED);
+				return response.setComplete();
+			}
+
+			return chain.filter(exchange);
+		};
+	}
+
+
+	/**
+	 * 检查code
+	 *
+	 * @param request
+	 * @throws ValidateCodeException 校验异常
+	 */
+	private void checkCode(ServerHttpRequest request) throws ValidateCodeException {
+		String code = request.getQueryParams().getFirst("code");
+
+		if (StrUtil.isBlank(code)) {
+			throw new ValidateCodeException();
+		}
+
+		String randomStr = request.getQueryParams().getFirst("randomStr");
+		if (StrUtil.isBlank(randomStr)) {
+			throw new ValidateCodeException();
+		}
+
+		String key = DEFAULT_CODE_KEY + randomStr;
+		if (!redisTemplate.hasKey(key)) {
+			throw new ValidateCodeException();
+		}
+
+		Object codeObj = redisTemplate.opsForValue().get(key);
+
+		if (codeObj == null) {
+			throw new ValidateCodeException();
+		}
+
+		String saveCode = codeObj.toString();
+		if (StrUtil.isBlank(saveCode)) {
+			redisTemplate.delete(key);
+			throw new ValidateCodeException();
+		}
+
+		if (!StrUtil.equals(saveCode, code)) {
+			redisTemplate.delete(key);
+			throw new ValidateCodeException();
+		}
+
+		redisTemplate.delete(key);
+	}
+
+	private static final String BASIC_ = "Basic ";
+
+	/**
+	 * 从header 请求中的clientId/clientsecect
+	 *
+	 * @param header header中的参数
+	 * @throws CheckedException if the Basic header is not present or is not valid
+	 *                          Base64
+	 */
+	public static String[] extractAndDecodeHeader(String header)
+		throws IOException, CheckedException {
+
+		byte[] base64Token = header.substring(6).getBytes("UTF-8");
+		byte[] decoded;
+		try {
+			decoded = Base64.decode(base64Token);
+		} catch (IllegalArgumentException e) {
+			throw new CheckedException(
+				"Failed to decode basic authentication token");
+		}
+
+		String token = new String(decoded, CharsetUtil.UTF_8);
+
+		int delim = token.indexOf(":");
+
+		if (delim == -1) {
+			throw new CheckedException("Invalid basic authentication token");
+		}
+		return new String[]{token.substring(0, delim), token.substring(delim + 1)};
+	}
+
+	/**
+	 * *从header 请求中的clientId/clientsecect
+	 *
+	 * @param request
+	 * @return
+	 * @throws IOException
+	 */
+	public static String[] extractAndDecodeHeader(ServerHttpRequest request)
+		throws IOException, CheckedException {
+		String header = request.getHeaders().getFirst("Authorization");
+
+		if (header == null || !header.startsWith(BASIC_)) {
+			throw new CheckedException("请求头中client信息为空");
+		}
+
+		return extractAndDecodeHeader(header);
+	}
+}

+ 97 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/PasswordDecoderFilter.java

@@ -0,0 +1,97 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.filter;
+
+import cn.hutool.core.codec.Base64;
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.stereotype.Component;
+import org.springframework.web.util.UriComponentsBuilder;
+import reactor.core.publisher.Mono;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.net.URI;
+import java.util.Map;
+
+/**
+ * @author lengleng
+ * @date 2018/7/15
+ * 密码解密工具类
+ */
+@Slf4j
+@Component
+public class PasswordDecoderFilter extends AbstractGatewayFilterFactory {
+	private static final String PASSWORD = "password";
+	private static final String KEY_ALGORITHM = "AES";
+	private static final String DEFAULT_CIPHER_ALGORITHM = "AES/CBC/NOPadding";
+	@Value("${security.encode.key:1234567812345678}")
+	private String encodeKey;
+
+	@Override
+	public GatewayFilter apply(Object config) {
+		return (exchange, chain) -> {
+			ServerHttpRequest request = exchange.getRequest();
+
+			// 不是登录请求,直接向下执行
+			if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath(), ImageCodeGatewayFilter.OAUTH_TOKEN_URL)) {
+				return chain.filter(exchange);
+			}
+
+			URI uri = exchange.getRequest().getURI();
+			String queryParam = uri.getRawQuery();
+			Map<String, String> paramMap = HttpUtil.decodeParamMap(queryParam, CharsetUtil.UTF_8);
+
+			String password = paramMap.get(PASSWORD);
+			if (StrUtil.isNotBlank(password)) {
+				try {
+					password = decryptAES(password, encodeKey);
+				} catch (Exception e) {
+					log.error("密码解密失败:{}", password);
+					return Mono.error(e);
+				}
+				paramMap.put(PASSWORD, password.trim());
+			}
+
+			URI newUri = UriComponentsBuilder.fromUri(uri)
+				.replaceQuery(HttpUtil.toParams(paramMap))
+				.build(true)
+				.toUri();
+
+			ServerHttpRequest newRequest = exchange.getRequest().mutate().uri(newUri).build();
+			return chain.filter(exchange.mutate().request(newRequest).build());
+		};
+	}
+
+
+	private static String decryptAES(String data, String pass) throws Exception {
+		Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
+		SecretKeySpec keyspec = new SecretKeySpec(pass.getBytes(), KEY_ALGORITHM);
+		IvParameterSpec ivspec = new IvParameterSpec(pass.getBytes());
+		cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
+		byte[] result = cipher.doFinal(Base64.decode(data.getBytes(CharsetUtil.UTF_8)));
+		return new String(result, CharsetUtil.UTF_8);
+	}
+}

+ 53 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/SwaggerHeaderFilter.java

@@ -0,0 +1,53 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.filter;
+
+import com.pig4cloud.pigx.gateway.config.SwaggerProvider;
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.server.ServerWebExchange;
+
+/**
+ * @author Sywd
+ * 添加X-Forwarded-Prefix header
+ */
+@Component
+public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
+	private static final String HEADER_NAME = "X-Forwarded-Prefix";
+
+	@Override
+	public GatewayFilter apply(Object config) {
+		return (exchange, chain) -> {
+			ServerHttpRequest request = exchange.getRequest();
+			String path = request.getURI().getPath();
+			if (!StringUtils.endsWithIgnoreCase(path, SwaggerProvider.API_URI)) {
+				return chain.filter(exchange);
+			}
+
+			String basePath = path.substring(0, path.lastIndexOf(SwaggerProvider.API_URI));
+
+
+			ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
+			ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
+			return chain.filter(newExchange);
+		};
+	}
+}

+ 44 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handle/HystrixFallbackHandler.java

@@ -0,0 +1,44 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.handle;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+/**
+ * @author lengleng
+ * @date 2018/7/5
+ * Hystrix 降级处理
+ */
+@Slf4j
+@Component
+public class HystrixFallbackHandler implements HandlerFunction<ServerResponse> {
+	@Override
+	public Mono<ServerResponse> handle(ServerRequest serverRequest) {
+		log.error("网关执行请求:{}失败,hystrix服务降级处理", serverRequest.uri());
+		return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
+			.contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromObject("服务异常"));
+	}
+}

+ 77 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handle/ImageCodeHandler.java

@@ -0,0 +1,77 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.handle;
+
+import com.google.code.kaptcha.Producer;
+import com.pig4cloud.pigx.gateway.filter.ImageCodeGatewayFilter;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.util.FastByteArrayOutputStream;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author lengleng
+ * @date 2018/7/5
+ * 验证码生成逻辑处理类
+ */
+@Slf4j
+@Component
+@AllArgsConstructor
+public class ImageCodeHandler implements HandlerFunction<ServerResponse> {
+	private final Producer producer;
+	private final RedisTemplate redisTemplate;
+
+	@Override
+	public Mono<ServerResponse> handle(ServerRequest serverRequest) {
+		//生成验证码
+		String text = producer.createText();
+		BufferedImage image = producer.createImage(text);
+
+		//保存验证码信息
+		String randomStr = serverRequest.queryParam("randomStr").get();
+		redisTemplate.opsForValue().set(ImageCodeGatewayFilter.DEFAULT_CODE_KEY + randomStr, text, 60, TimeUnit.SECONDS);
+
+		// 转换流信息写出
+		FastByteArrayOutputStream os = new FastByteArrayOutputStream();
+		try {
+			ImageIO.write(image, "jpeg", os);
+		} catch (IOException e) {
+			log.error("ImageIO write err", e);
+			return Mono.error(e);
+		}
+
+		return ServerResponse
+			.status(HttpStatus.OK)
+			.contentType(MediaType.IMAGE_JPEG)
+			.body(BodyInserters.fromResource(new ByteArrayResource(os.toByteArray())));
+	}
+}

+ 55 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handle/SwaggerResourceHandler.java

@@ -0,0 +1,55 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.handle;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+import springfox.documentation.swagger.web.SwaggerResourcesProvider;
+
+/**
+ * @author lengleng
+ * @date 2018-07-19
+ * SwaggerResourceHandler
+ */
+@Slf4j
+@Component
+@AllArgsConstructor
+public class SwaggerResourceHandler implements HandlerFunction<ServerResponse> {
+	private final SwaggerResourcesProvider swaggerResources;
+
+	/**
+	 * Handle the given request.
+	 *
+	 * @param request the request to handle
+	 * @return the response
+	 */
+	@Override
+	public Mono<ServerResponse> handle(ServerRequest request) {
+		return ServerResponse.status(HttpStatus.OK)
+			.contentType(MediaType.APPLICATION_JSON_UTF8)
+			.body(BodyInserters.fromObject(swaggerResources.get()));
+	}
+}

+ 60 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handle/SwaggerSecurityHandler.java

@@ -0,0 +1,60 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.handle;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+import springfox.documentation.swagger.web.SecurityConfiguration;
+import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
+
+import java.util.Optional;
+
+/**
+ * @author lengleng
+ * @date 2018-07-19
+ * SwaggerSecurityHandler
+ */
+@Slf4j
+@Component
+public class SwaggerSecurityHandler implements HandlerFunction<ServerResponse> {
+	@Autowired(required = false)
+	private SecurityConfiguration securityConfiguration;
+
+	/**
+	 * Handle the given request.
+	 *
+	 * @param request the request to handle
+	 * @return the response
+	 */
+	@Override
+	public Mono<ServerResponse> handle(ServerRequest request) {
+		return ServerResponse.status(HttpStatus.OK)
+			.contentType(MediaType.APPLICATION_JSON_UTF8)
+			.body(BodyInserters.fromObject(
+				Optional.ofNullable(securityConfiguration)
+					.orElse(SecurityConfigurationBuilder.builder().build())));
+	}
+}

+ 0 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handle/SwaggerUiHandler.java


Some files were not shown because too many files changed in this diff