...
 
Commits (19)
    https://gitcode.net/qq_16063307/pig/-/commit/3ca9d94ccec823656a4b5829462a8d7856acef32 :rotating_light: Removing linter warnings. 错误合并 2023-05-27T10:07:02+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/e3e712801a179636881d2da97796df855f4340ed 修改spring.checkstyle.plugin版本不一致问题 2023-06-12T06:05:31+00:00 GuoZhang zhang1426754079@163.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:zhang1426754079@163.com" title="zhang1426754079@163.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg1" style="text-decoration: none">N</a><a href="mailto:zhang1426754079@163.com" title="zhang1426754079@163.com">GuoZhang</a> &lt;<a href="mailto:zhang1426754079@163.com" title="zhang1426754079@163.com">zhang1426754079@163.com</a>&gt;</span> https://gitcode.net/qq_16063307/pig/-/commit/94b510887b19c90e05e373f42afdb54fb7704ecf Merge branch 'dev' 2023-06-17T18:53:34+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/cafd57ee957c09c5dc8827b5ec09febf969afbf1 !374 修改spring.checkstyle.plugin版本不一致问题 2023-06-18T00:52:39+00:00 lengleng wangiegie@gmail.com Merge pull request !374 from GuoZhang/N/A https://gitcode.net/qq_16063307/pig/-/commit/d0cddfd89c447b0fe20a11b401c9dc3aa790e2bf :memo: Writing docs. 增加issue文档 2023-06-18T08:54:02+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/e427126bcc4199f7ac95090b1287c82ef7ba0f4b :recycle: PigSecurityInnerAspect使用前置通知替代环绕通知 2023-07-26T11:03:37+08:00 knight lixiao@neuro-touch.com https://gitcode.net/qq_16063307/pig/-/commit/6b0aae7d2619933aa938bc8d62de49927ee62c6c Merge branch 'master' into dev 2023-08-17T16:01:55+08:00 lbw wangiegie@163.com # Conflicts: # pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/component/PigSecurityInnerAspect.java https://gitcode.net/qq_16063307/pig/-/commit/cc43baa795a8bf4e37cd3b9530f584bffe2ce35f :bookmark: Releasing / Version tags. 3.7.0-JDK8 2023-08-17T21:45:14+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/80adb67cff3a5040318560f2e8736a7cea5ef8ac :bookmark: Releasing / Version tags. 3.7.0-JDK8 2023-08-17T21:46:22+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/0e8fa668b34f9e39546d34eefcf2b8e2ede97c66 :card_file_box: 执行数据库相关的变化,quartz 配置默认链接端口 2023-08-17T21:50:48+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/e0a9c78a1dad94c42e6a6801b9518bed07925127 :card_file_box: 执行数据库相关的变化,quartz 配置默认链接端口 2023-08-17T22:11:36+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/2f673068ef8af0db5c648ce83ba41418c42a8672 :art: Improving structure / format of the code. up format 0.0.39 2023-08-17T22:16:13+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/a6894fa2e3b18ac5985d818bd15053540698733c :card_file_box: 执行数据库相关的变化,删除无用菜单SQL 2023-08-19T20:29:12+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/3b87cf34f6fc6badbfd6cc888a3a5298d02a98bf :bookmark: Releasing / Version tags. 3.7.0-JDK8 2023-08-22T12:33:02+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/4275fcc61d89da6fce33331c732bcb141265acc4 :recycle: Refactoring code. 代码生成的模板修改 2023-08-23T13:40:29+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/ac2b4fd2de777cb895657c01a26e4a9ed607c92b :bug: Fixing a bug. swagger 参数平铺问题 2023-08-23T14:05:51+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/f85a0acac55d01158a8be8358d481f5604e541ba :arrow_up: Upgrading dependencies. 避免验证码负数 2023-08-24T10:53:37+08:00 lbw wangiegie@163.com https://gitcode.net/qq_16063307/pig/-/commit/fa84f67755d83cdd9418e3ac95e65c19bf08026c up spring-boot version close #I7VR8X 2023-08-24T13:48:23+00:00 Mac666 support@mail.pigx.vip Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:support@mail.pigx.vip" title="support@mail.pigx.vip"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg2" style="text-decoration: none">N</a><a href="mailto:support@mail.pigx.vip" title="support@mail.pigx.vip">Mac666</a> &lt;<a href="mailto:support@mail.pigx.vip" title="support@mail.pigx.vip">support@mail.pigx.vip</a>&gt;</span> https://gitcode.net/qq_16063307/pig/-/commit/803ae532ad1201de610b1197656e941f55ad8769 !409 【轻量级 PR】:up spring-boot version close #I7VR8X 2023-08-24T13:49:30+00:00 lengleng wangiegie@gmail.com Merge pull request !409 from Mac666/N/A
......@@ -21,7 +21,7 @@
[ 配套视频 tv.pig4cloud.com](https://www.bilibili.com/video/BV12t411B7e9)
[PIGX 在线体验 pigx.pig4cloud.com](http://pigx.pig4cloud.com)
[PIGX 在线体验 pigx.pigx.top](http://pigx.pigx.top)
[产品白皮书 paper.pig4cloud.com](https://paper.pig4cloud.com)
......@@ -34,18 +34,18 @@
### 分支说明
- master: java8 + springboot 2.7 + springcloud 2021
- jdk17: java17 + springboot 3.0 + springcloud 2022
- jdk17: java17 + springboot 3.1 + springcloud 2022
### 核心依赖
| 依赖 | 版本 |
|-----------------------------|------------|
| Spring Boot | 2.7.13 |
| Spring Cloud | 2021.0.7 |
| Spring Boot | 2.7.15 |
| Spring Cloud | 2021.0.8 |
| Spring Cloud Alibaba | 2021.0.5.0 |
| Spring Authorization Server | 0.4.3 |
| Mybatis Plus | 3.5.3.1 |
| hutool | 5.8.20 |
| hutool | 5.8.1 |
### 模块说明
......@@ -60,6 +60,7 @@ pig
├── pig-common-datasource -- 动态数据源包
├── pig-common-job -- xxl-job 封装
├── pig-common-log -- 日志服务
├── pig-common-oss -- 文件上传工具类
├── pig-common-mybatis -- mybatis 扩展封装
├── pig-common-seata -- 分布式事务
├── pig-common-security -- 安全工具类
......@@ -74,8 +75,7 @@ pig
└── pig-visual
└── pig-monitor -- 服务监控 [5001]
├── pig-codegen -- 图形化代码生成 [5002]
├── pig-sentinel-dashboard -- 流量高可用 [5003]
└── pig-xxl-job-admin -- 分布式定时任务管理台 [5004]
└── pig-quartz -- 定时任务管理台 [5007]
```
### 本地开发 运行
......
此差异已折叠。
此差异已折叠。
......@@ -37,13 +37,13 @@ CREATE TABLE `config_info` (
-- Records of config_info
-- ----------------------------
BEGIN;
INSERT INTO `config_info` VALUES (1, 'application-dev.yml', 'DEFAULT_GROUP', '# 配置文件加密根密码\njasypt:\n encryptor:\n password: pig\n algorithm: PBEWithMD5AndDES\n iv-generator-classname: org.jasypt.iv.NoIvGenerator\n \n# Spring 相关\nspring:\n cache:\n type: redis\n redis:\n host: pig-redis\n cloud:\n sentinel:\n eager: true\n transport:\n dashboard: pig-sentinel:5003\n\n# 暴露监控端点\nmanagement:\n endpoints:\n web:\n exposure:\n include: \"*\" \n endpoint:\n health:\n show-details: ALWAYS\n\n\n# feign 配置\nfeign:\n sentinel:\n enabled: true\n okhttp:\n enabled: true\n httpclient:\n enabled: false\n client:\n config:\n default:\n connectTimeout: 10000\n readTimeout: 10000\n compression:\n request:\n enabled: true\n response:\n enabled: true\n\n# mybaits-plus配置\nmybatis-plus:\n mapper-locations: classpath:/mapper/*Mapper.xml\n global-config:\n banner: false\n db-config:\n id-type: auto\n table-underline: true\n logic-delete-value: 1\n logic-not-delete-value: 0\n configuration:\n map-underscore-to-camel-case: true\n\n# swagger 配置\nswagger:\n enabled: true\n title: Pig Swagger API\n gateway: http://${GATEWAY_HOST:pig-gateway}:${GATEWAY-PORT:9999}\n token-url: ${swagger.gateway}/auth/oauth2/token\n scope: server\n services:\n pig-upms-biz: admin\n pig-codegen: gen', '81f8bae4b8125fd198704f797268c6b5', '2022-05-08 12:10:37', '2023-02-28 14:45:23', 'nacos', '127.0.0.1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` VALUES (1, 'application-dev.yml', 'DEFAULT_GROUP', '# 配置文件加密根密码\njasypt:\n encryptor:\n password: pig\n algorithm: PBEWithMD5AndDES\n iv-generator-classname: org.jasypt.iv.NoIvGenerator\n \n# Spring 相关\nspring:\n cache:\n type: redis\n redis:\n host: pig-redis\n cloud:\n sentinel:\n eager: true\n transport:\n dashboard: pig-sentinel:5003\n\n# 暴露监控端点\nmanagement:\n endpoints:\n web:\n exposure:\n include: \"*\" \n endpoint:\n health:\n show-details: ALWAYS\n\n\n# feign 配置\nfeign:\n sentinel:\n enabled: true\n okhttp:\n enabled: true\n httpclient:\n enabled: false\n client:\n config:\n default:\n connectTimeout: 10000\n readTimeout: 10000\n compression:\n request:\n enabled: true\n response:\n enabled: true\n\n# mybaits-plus配置\nmybatis-plus:\n mapper-locations: classpath:/mapper/*Mapper.xml\n type-handlers-package: com.pig4cloud.pig.common.mybatis.handler\n global-config:\n banner: false\n db-config:\n id-type: auto\n table-underline: true\n logic-delete-value: 1\n logic-not-delete-value: 0\n configuration:\n map-underscore-to-camel-case: true\n shrink-whitespaces-in-sql: true\n# swagger 配置\nswagger:\n enabled: true\n title: Pig Swagger API\n gateway: http://${GATEWAY_HOST:pig-gateway}:${GATEWAY-PORT:9999}\n token-url: ${swagger.gateway}/auth/oauth2/token\n scope: server\n services:\n pig-upms-biz: admin\n pig-codegen: gen', 'a07e272a112eaa8d4f7ea2a257bf5076', '2022-05-08 12:10:37', '2023-08-17 21:20:45', 'nacos', '127.0.0.1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` VALUES (2, 'pig-auth-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n freemarker:\n allow-request-override: false\n allow-session-override: false\n cache: true\n charset: UTF-8\n check-template-location: true\n content-type: text/html\n enabled: true\n expose-request-attributes: false\n expose-session-attributes: false\n expose-spring-macro-helpers: true\n prefer-file-system-access: true\n suffix: .ftl\n template-loader-path: classpath:/templates/', '74f53b71c7799aa754da75662378b93c', '2022-05-08 12:10:37', '2022-06-04 14:15:35', 'nacos', '127.0.0.1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` VALUES (3, 'pig-codegen-dev.yml', 'DEFAULT_GROUP', '# 数据源配置\nspring:\n datasource:\n type: com.zaxxer.hikari.HikariDataSource\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: root\n password: root\n url: jdbc:mysql://pig-mysql:3306/pig_codegen?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true\n resources:\n static-locations: classpath:/static/,classpath:/views/\n', 'cf786dbe3b07074fc187bf2eab3266b1', '2022-05-08 12:10:37', '2023-01-28 14:05:36', '', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` VALUES (4, 'pig-gateway-dev.yml', 'DEFAULT_GROUP', 'spring:\n cloud:\n gateway:\n locator:\n enabled: true\n routes:\n # 认证中心\n - id: pig-auth\n uri: lb://pig-auth\n predicates:\n - Path=/auth/**\n filters:\n # 验证码处理\n - ValidateCodeGatewayFilter\n # 前端密码解密\n - PasswordDecoderFilter\n #UPMS 模块\n - id: pig-upms-biz\n uri: lb://pig-upms-biz\n predicates:\n - Path=/admin/**\n filters:\n # 限流配置\n - name: RequestRateLimiter\n args:\n key-resolver: \'#{@remoteAddrKeyResolver}\'\n redis-rate-limiter.replenishRate: 100\n redis-rate-limiter.burstCapacity: 200\n # 代码生成模块\n - id: pig-codegen\n uri: lb://pig-codegen\n predicates:\n - Path=/gen/**\n # 固定路由转发配置 无修改\n - id: openapi\n uri: lb://pig-gateway\n predicates:\n - Path=/v3/api-docs/**\n filters:\n - RewritePath=/v3/api-docs/(?<path>.*), /$\\{path}/$\\{path}/v3/api-docs\n\ngateway:\n encode-key: \'thanks,pig4cloud\'\n ignore-clients:\n - test\n - client', '000988cf0102382d3f23df35027b47fd', '2022-05-08 12:10:37', '2022-06-07 14:00:11', 'nacos', '127.0.0.1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` VALUES (4, 'pig-gateway-dev.yml', 'DEFAULT_GROUP', 'spring:\n cloud:\n gateway:\n locator:\n enabled: true\n routes:\n # 认证中心\n - id: pig-auth\n uri: lb://pig-auth\n predicates:\n - Path=/auth/**\n filters:\n # 验证码处理\n - ValidateCodeGatewayFilter\n # 前端密码解密\n - PasswordDecoderFilter\n #UPMS 模块\n - id: pig-upms-biz\n uri: lb://pig-upms-biz\n predicates:\n - Path=/admin/**\n filters:\n # 限流配置\n - name: RequestRateLimiter\n args:\n key-resolver: \'#{@remoteAddrKeyResolver}\'\n redis-rate-limiter.replenishRate: 100\n redis-rate-limiter.burstCapacity: 200\n # 代码生成模块\n - id: pig-codegen\n uri: lb://pig-codegen\n predicates:\n - Path=/gen/**\n # 代码生成模块\n - id: pig-quartz\n uri: lb://pig-quartz\n predicates:\n - Path=/job/**\n # 固定路由转发配置 无修改\n - id: openapi\n uri: lb://pig-gateway\n predicates:\n - Path=/v3/api-docs/**\n filters:\n - RewritePath=/v3/api-docs/(?<path>.*), /$\\{path}/$\\{path}/v3/api-docs\n\ngateway:\n encode-key: \'thanks,pig4cloud\'\n ignore-clients:\n - test\n - client', 'cde041935aeeb2a5f59bf3b56d78f56d', '2022-05-08 12:10:37', '2023-07-05 13:50:59', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` VALUES (5, 'pig-monitor-dev.yml', 'DEFAULT_GROUP', 'spring:\n autoconfigure:\n exclude: com.pig4cloud.pig.common.core.config.JacksonConfiguration\n # 安全配置\n security:\n user:\n name: ENC(8Hk2ILNJM8UTOuW/Xi75qg==) # pig\n password: ENC(o6cuPFfUevmTbkmBnE67Ow====) # pig\n', '650bdfa15f60f3faa84dfe6e6878b8cf', '2022-05-08 12:10:37', '2022-05-08 12:10:37', NULL, '127.0.0.1', '', '', NULL, NULL, NULL, 'yaml', NULL, '');
INSERT INTO `config_info` VALUES (6, 'pig-upms-biz-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.zaxxer.hikari.HikariDataSource\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: root\n password: root\n url: jdbc:mysql://pig-mysql:3306/pig?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true\n\n# 文件上传相关 支持阿里云、华为云、腾讯、minio\noss:\n endpoint: http://minio.pig4cloud.com\n accessKey: lengleng\n secretKey: lengleng\n bucket-name: tmp', '899d2431d91da0d521378cc7fa61268d', '2022-05-08 12:10:37', '2023-01-28 14:01:46', '', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` VALUES (7, 'pig-xxl-job-admin-dev.yml', 'DEFAULT_GROUP', '# xxl\nxxl:\n job:\n accessToken: default_token\n i18n: zh_CN\n logretentiondays: 30\n triggerpool:\n fast.max: 200\n slow.max: 200\n\n# mybatis\nmybatis:\n mapper-locations: classpath:/mybatis-mapper/*Mapper.xml\n\nspring:\n datasource:\n url: jdbc:mysql://${MYSQL_HOST:pig-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pig_job}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: ${MYSQL_USER:root}\n password: ${MYSQL_PWD:root}\n mvc:\n static-path-pattern: /static/**\n freemarker:\n suffix: .ftl\n request-context-attribute: request\n settings:\n number_format: 0.##########\n mail:\n host: smtp.mxhichina.com\n port: 465\n from: xxxx@gitee.wang\n username: xxxx@gitee.wang\n password: xxxx\n properties:\n mail:\n smtp:\n auth: true\n ssl.enable: true\n starttls.enable: false\n required: false\n# spring boot admin 配置\n\nmanagement:\n health:\n mail:\n enabled: false\n endpoints:\n web:\n exposure:\n include: \'*\'\n endpoint:\n health:\n show-details: ALWAYS\n\n', 'b67cbbd37c8b42cdc6521780b3ed742a', '2022-11-27 17:23:42', '2022-11-27 17:28:01', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` VALUES (6, 'pig-upms-biz-dev.yml', 'DEFAULT_GROUP', '# 数据源\nspring:\n datasource:\n type: com.zaxxer.hikari.HikariDataSource\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: root\n password: root\n url: jdbc:mysql://pig-mysql:3306/pig?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true\n\n# 文件上传相关 支持阿里云、华为云、腾讯、minio\nfile:\n bucketName: s3demo \n local:\n enable: true\n base-path: /Users/lengleng/Downloads/img', '48f8db128aeb5debb331bae49ff37908', '2022-05-08 12:10:37', '2023-07-07 14:44:09', 'nacos', '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '', '');
INSERT INTO `config_info` VALUES (7, 'pig-quartz-dev.yml', 'DEFAULT_GROUP', 'spring:\n datasource:\n type: com.zaxxer.hikari.HikariDataSource\n driver-class-name: com.mysql.cj.jdbc.Driver\n username: root\n password: root\n url: jdbc:mysql://pig-mysql:3306/pig_job?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true\n quartz:\n #相关属性配置\n properties:\n org:\n quartz:\n scheduler:\n instanceName: clusteredScheduler\n instanceId: AUTO\n jobStore:\n class: org.springframework.scheduling.quartz.LocalDataSourceJobStore\n driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate\n tablePrefix: QRTZ_\n isClustered: true\n clusterCheckinInterval: 10000\n useProperties: false\n threadPool:\n class: org.quartz.simpl.SimpleThreadPool\n threadCount: 50\n threadPriority: 5\n threadsInheritContextClassLoaderOfInitializingThread: true\n #数据库方式\n job-store-type: jdbc\n #初始化表结构 (第一次启动自动创建表,后续改成never 即可)\n jdbc:\n initialize-schema: always\n\n', '7a2859cbd056ef554b6163f5c70dfcf5', '2023-07-02 12:24:33', '2023-08-17 20:44:54', 'nacos', '127.0.0.1', '', '', '', '', '', 'yaml', '', '');
COMMIT;
-- ----------------------------
......
......@@ -2,119 +2,57 @@ DROP DATABASE IF EXISTS `pig_job`;
CREATE DATABASE `pig_job` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
use `pig_job`;
SET NAMES utf8mb4;
CREATE TABLE `xxl_job_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_desc` varchar(255) NOT NULL,
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`author` varchar(64) DEFAULT NULL COMMENT '作者',
`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
`schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型',
`schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',
`misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
`executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
`glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
`child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔',
`trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态:0-停止,1-运行',
`trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',
`trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_id` int(11) NOT NULL COMMENT '任务,主键ID',
`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
`trigger_code` int(11) NOT NULL COMMENT '调度-结果',
`trigger_msg` text COMMENT '调度-日志',
`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
`handle_code` int(11) NOT NULL COMMENT '执行-状态',
`handle_msg` text COMMENT '执行-日志',
`alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败',
PRIMARY KEY (`id`),
KEY `I_trigger_time` (`trigger_time`),
KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log_report` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',
`running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',
`suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',
`fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_logglue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) NOT NULL COMMENT '任务,主键ID',
`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_registry` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`registry_group` varchar(50) NOT NULL,
`registry_key` varchar(255) NOT NULL,
`registry_value` varchar(255) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
`title` varchar(12) NOT NULL COMMENT '执行器名称',
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',
`address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '账号',
`password` varchar(50) NOT NULL COMMENT '密码',
`role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员',
`permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割',
PRIMARY KEY (`id`),
UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_lock` (
`lock_name` varchar(50) NOT NULL COMMENT '锁名称',
PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' );
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '');
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');
USE pig_job;
-- ----------------------------
-- Table structure for sys_job
-- ----------------------------
DROP TABLE IF EXISTS `sys_job`;
CREATE TABLE `sys_job` (
`job_id` bigint NOT NULL COMMENT '任务id',
`job_name` varchar(64) CHARACTER SET utf8mb4 NOT NULL COMMENT '任务名称',
`job_group` varchar(64) CHARACTER SET utf8mb4 NOT NULL COMMENT '任务组名',
`job_order` char(1) CHARACTER SET utf8mb4 DEFAULT '1' COMMENT '组内执行顺利,值越大执行优先级越高,最大值9,最小值1',
`job_type` char(1) CHARACTER SET utf8mb4 NOT NULL DEFAULT '1' COMMENT '1、java类;2、spring bean名称;3、rest调用;4、jar调用;9其他',
`execute_path` varchar(500) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'job_type=3时,rest调用地址,仅支持rest get协议,需要增加String返回值,0成功,1失败;job_type=4时,jar路径;其它值为空',
`class_name` varchar(500) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'job_type=1时,类完整路径;job_type=2时,spring bean名称;其它值为空',
`method_name` varchar(500) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '任务方法',
`method_params_value` varchar(2000) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '参数值',
`cron_expression` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'cron执行表达式',
`misfire_policy` varchar(20) CHARACTER SET utf8mb4 DEFAULT '3' COMMENT '错失执行策略(1错失周期立即执行 2错失周期执行一次 3下周期执行)',
`job_tenant_type` char(1) CHARACTER SET utf8mb4 DEFAULT '1' COMMENT '1、多租户任务;2、非多租户任务',
`job_status` char(1) CHARACTER SET utf8mb4 DEFAULT '0' COMMENT '状态(1、未发布;2、运行中;3、暂停;4、删除;)',
`job_execute_status` char(1) CHARACTER SET utf8mb4 DEFAULT '0' COMMENT '状态(0正常 1异常)',
`create_by` varchar(64) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb4 DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`start_time` timestamp NULL DEFAULT NULL COMMENT '初次执行时间',
`previous_time` timestamp NULL DEFAULT NULL COMMENT '上次执行时间',
`next_time` timestamp NULL DEFAULT NULL COMMENT '下次执行时间',
`remark` varchar(500) CHARACTER SET utf8mb4 DEFAULT '' COMMENT '备注信息',
PRIMARY KEY (`job_id`,`job_name`,`job_group`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='定时任务调度表';
-- ----------------------------
DROP TABLE IF EXISTS `sys_job_log`;
CREATE TABLE `sys_job_log` (
`job_log_id` bigint NOT NULL COMMENT '任务日志ID',
`job_id` bigint NOT NULL COMMENT '任务id',
`job_name` varchar(64) CHARACTER SET utf8 DEFAULT NULL COMMENT '任务名称',
`job_group` varchar(64) CHARACTER SET utf8 DEFAULT NULL COMMENT '任务组名',
`job_order` char(1) CHARACTER SET utf8 DEFAULT NULL COMMENT '组内执行顺利,值越大执行优先级越高,最大值9,最小值1',
`job_type` char(1) CHARACTER SET utf8 NOT NULL DEFAULT '1' COMMENT '1、java类;2、spring bean名称;3、rest调用;4、jar调用;9其他',
`execute_path` varchar(500) CHARACTER SET utf8 DEFAULT NULL COMMENT 'job_type=3时,rest调用地址,仅支持post协议;job_type=4时,jar路径;其它值为空',
`class_name` varchar(500) CHARACTER SET utf8 DEFAULT NULL COMMENT 'job_type=1时,类完整路径;job_type=2时,spring bean名称;其它值为空',
`method_name` varchar(500) CHARACTER SET utf8 DEFAULT NULL COMMENT '任务方法',
`method_params_value` varchar(2000) CHARACTER SET utf8 DEFAULT NULL COMMENT '参数值',
`cron_expression` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT 'cron执行表达式',
`job_message` varchar(500) CHARACTER SET utf8 DEFAULT NULL COMMENT '日志信息',
`job_log_status` char(1) CHARACTER SET utf8 DEFAULT '0' COMMENT '执行状态(0正常 1失败)',
`execute_time` varchar(30) CHARACTER SET utf8 DEFAULT NULL COMMENT '执行时间',
`exception_info` varchar(2000) CHARACTER SET utf8 DEFAULT '' COMMENT '异常信息',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`job_log_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='定时任务执行日志表';
commit;
......@@ -9,12 +9,20 @@ services:
restart: always
container_name: pig-mysql
image: pig-mysql
ports:
- 3306:3306
networks:
- spring_cloud_default
pig-redis:
image: redis:7.0.0
ports:
- 6379:6379
restart: always
container_name: pig-redis
hostname: pig-redis
networks:
- spring_cloud_default
pig-register:
build:
......@@ -25,6 +33,8 @@ services:
container_name: pig-register
hostname: pig-register
image: pig-register
networks:
- spring_cloud_default
pig-gateway:
build:
......@@ -35,6 +45,8 @@ services:
container_name: pig-gateway
hostname: pig-gateway
image: pig-gateway
networks:
- spring_cloud_default
pig-auth:
build:
......@@ -43,6 +55,8 @@ services:
container_name: pig-auth
hostname: pig-auth
image: pig-auth
networks:
- spring_cloud_default
pig-upms:
build:
......@@ -51,6 +65,8 @@ services:
container_name: pig-upms
hostname: pig-upms
image: pig-upms
networks:
- spring_cloud_default
pig-monitor:
build:
......@@ -61,15 +77,8 @@ services:
container_name: pig-monitor
hostname: pig-monitor
image: pig-monitor
pig-sentinel:
build:
context: ./pig-visual/pig-sentinel-dashboard
restart: always
image: pig-sentinel
container_name: pig-sentinel
ports:
- 5003:5003
networks:
- spring_cloud_default
pig-codegen:
build:
......@@ -78,13 +87,19 @@ services:
container_name: pig-codegen
hostname: pig-codegen
image: pig-codegen
networks:
- spring_cloud_default
pig-job:
pig-quartz:
build:
context: ./pig-visual/pig-xxl-job-admin
context: ./pig-visual/pig-quartz
restart: always
container_name: pig-job
hostname: pig-job
image: pig-job
ports:
- 5004:5004
image: pig-quartz
container_name: pig-quartz
networks:
- spring_cloud_default
networks:
spring_cloud_default:
name: spring_cloud_default
driver: bridge
......@@ -21,7 +21,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-auth</artifactId>
......
......@@ -27,6 +27,7 @@ import com.pig4cloud.pig.admin.api.vo.TokenVo;
import com.pig4cloud.pig.auth.support.handler.PigAuthenticationFailureEventHandler;
import com.pig4cloud.pig.common.core.constant.CacheConstants;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.core.util.RetOps;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
......@@ -34,6 +35,8 @@ import com.pig4cloud.pig.common.security.annotation.Inner;
import com.pig4cloud.pig.common.security.util.OAuth2EndpointUtils;
import com.pig4cloud.pig.common.security.util.OAuth2ErrorCodesExpand;
import com.pig4cloud.pig.common.security.util.OAuthClientException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
......@@ -59,8 +62,6 @@ import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.Principal;
import java.util.List;
import java.util.Map;
......@@ -107,7 +108,8 @@ public class PigTokenEndpoint {
@RequestParam(OAuth2ParameterNames.CLIENT_ID) String clientId,
@RequestParam(OAuth2ParameterNames.SCOPE) String scope,
@RequestParam(OAuth2ParameterNames.STATE) String state) {
SysOauthClientDetails clientDetails = RetOps.of(clientDetailsService.getClientDetailsById(clientId))
SysOauthClientDetails clientDetails = RetOps
.of(clientDetailsService.getClientDetailsById(clientId, SecurityConstants.FROM_IN))
.getData()
.orElseThrow(() -> new OAuthClientException("clientId 不合法"));
......
package com.pig4cloud.pig.auth.support.base;
import com.pig4cloud.pig.common.security.util.OAuth2EndpointUtils;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
......@@ -9,7 +10,6 @@ import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
......
......@@ -3,7 +3,6 @@ package com.pig4cloud.pig.auth.support.base;
import cn.hutool.extra.spring.SpringUtil;
import com.pig4cloud.pig.common.security.util.OAuth2ErrorCodesExpand;
import com.pig4cloud.pig.common.security.util.ScopeException;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.support.MessageSourceAccessor;
......@@ -36,7 +35,6 @@ import java.util.function.Supplier;
*
* 处理自定义授权
*/
@Slf4j
public abstract class OAuth2ResourceOwnerBaseAuthenticationProvider<T extends OAuth2ResourceOwnerBaseAuthenticationToken>
implements AuthenticationProvider {
......@@ -111,29 +109,29 @@ public abstract class OAuth2ResourceOwnerBaseAuthenticationProvider<T extends OA
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
T resourceOwnerBaseAuthentication = (T) authentication;
T resouceOwnerBaseAuthentication = (T) authentication;
OAuth2ClientAuthenticationToken clientPrincipal = getAuthenticatedClientElseThrowInvalidClient(
resourceOwnerBaseAuthentication);
resouceOwnerBaseAuthentication);
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
checkClient(registeredClient);
Set<String> authorizedScopes;
// Default to configured scopes
if (!CollectionUtils.isEmpty(resourceOwnerBaseAuthentication.getScopes())) {
for (String requestedScope : resourceOwnerBaseAuthentication.getScopes()) {
if (!CollectionUtils.isEmpty(resouceOwnerBaseAuthentication.getScopes())) {
for (String requestedScope : resouceOwnerBaseAuthentication.getScopes()) {
if (!registeredClient.getScopes().contains(requestedScope)) {
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_SCOPE);
}
}
authorizedScopes = new LinkedHashSet<>(resourceOwnerBaseAuthentication.getScopes());
authorizedScopes = new LinkedHashSet<>(resouceOwnerBaseAuthentication.getScopes());
}
else {
throw new ScopeException(OAuth2ErrorCodesExpand.SCOPE_IS_EMPTY);
authorizedScopes = new LinkedHashSet<>();
}
Map<String, Object> reqParameters = resourceOwnerBaseAuthentication.getAdditionalParameters();
Map<String, Object> reqParameters = resouceOwnerBaseAuthentication.getAdditionalParameters();
try {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = buildToken(reqParameters);
......@@ -149,14 +147,14 @@ public abstract class OAuth2ResourceOwnerBaseAuthenticationProvider<T extends OA
.principal(usernamePasswordAuthentication)
.authorizationServerContext(AuthorizationServerContextHolder.getContext())
.authorizedScopes(authorizedScopes)
.authorizationGrantType(resourceOwnerBaseAuthentication.getAuthorizationGrantType())
.authorizationGrant(resourceOwnerBaseAuthentication);
.authorizationGrantType(AuthorizationGrantType.PASSWORD)
.authorizationGrant(resouceOwnerBaseAuthentication);
// @formatter:on
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization
.withRegisteredClient(registeredClient)
.principalName(usernamePasswordAuthentication.getName())
.authorizationGrantType(resourceOwnerBaseAuthentication.getAuthorizationGrantType())
.authorizationGrantType(AuthorizationGrantType.PASSWORD)
// 0.4.0 新增的方法
.authorizedScopes(authorizedScopes);
......@@ -219,6 +217,7 @@ public abstract class OAuth2ResourceOwnerBaseAuthenticationProvider<T extends OA
}
catch (Exception ex) {
LOGGER.error("problem in authenticate", ex);
throw oAuth2AuthenticationException(authentication, (AuthenticationException) ex);
}
......@@ -266,10 +265,7 @@ public abstract class OAuth2ResourceOwnerBaseAuthenticationProvider<T extends OA
return new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_SCOPE,
this.messages.getMessage("AbstractAccessDecisionManager.accessDenied", "invalid_scope"), ""));
}
log.error(authenticationException.getLocalizedMessage());
return new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR),
authenticationException.getLocalizedMessage(), authenticationException);
return new OAuth2AuthenticationException(OAuth2ErrorCodesExpand.UN_KNOW_LOGIN_ERROR);
}
private OAuth2ClientAuthenticationToken getAuthenticatedClientElseThrowInvalidClient(
......
......@@ -31,6 +31,8 @@ public class CustomeOAuth2TokenCustomizer implements OAuth2TokenCustomizer<OAuth
PigUser pigUser = (PigUser) context.getPrincipal().getPrincipal();
claims.claim(SecurityConstants.DETAILS_USER, pigUser);
claims.claim(SecurityConstants.DETAILS_USER_ID, pigUser.getId());
claims.claim(SecurityConstants.USERNAME, pigUser.getUsername());
}
}
......@@ -22,13 +22,11 @@ public final class FormIdentityLoginConfigurer
formLogin.failureHandler(new FormAuthenticationFailureHandler());
})
.logout() // SSO登出成功处理
.logoutSuccessHandler(new SsoLogoutSuccessHandler())
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.and()
.csrf()
.disable();
.logout(logout -> logout.logoutSuccessHandler(new SsoLogoutSuccessHandler())
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)) // SSO登出成功处理
.csrf(AbstractHttpConfigurer::disable);
}
}
package com.pig4cloud.pig.auth.support.core;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.util.WebUtils;
import com.pig4cloud.pig.common.security.service.PigUserDetailsService;
import javax.servlet.http.HttpServletRequest;
import lombok.SneakyThrows;
import org.springframework.core.Ordered;
import org.springframework.security.authentication.BadCredentialsException;
......@@ -24,7 +24,6 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.web.authentication.www.BasicAuthenticationConverter;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
......@@ -70,7 +69,7 @@ public class PigDaoAuthenticationProvider extends AbstractUserDetailsAuthenticat
// app 模式不用校验密码
String grantType = WebUtils.getRequest().get().getParameter(OAuth2ParameterNames.GRANT_TYPE);
if (StrUtil.equals(SecurityConstants.APP, grantType)) {
if (StrUtil.equals(SecurityConstants.MOBILE, grantType)) {
return;
}
......@@ -89,15 +88,15 @@ public class PigDaoAuthenticationProvider extends AbstractUserDetailsAuthenticat
@SneakyThrows
@Override
protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) {
prepareTimingAttackProtection();
HttpServletRequest request = WebUtils.getRequest()
.orElseThrow(
(Supplier<Throwable>) () -> new InternalAuthenticationServiceException("web request is empty"));
Map<String, String> paramMap = ServletUtil.getParamMap(request);
String grantType = paramMap.get(OAuth2ParameterNames.GRANT_TYPE);
String clientId = paramMap.get(OAuth2ParameterNames.CLIENT_ID);
String grantType = WebUtils.getRequest().get().getParameter(OAuth2ParameterNames.GRANT_TYPE);
String clientId = WebUtils.getRequest().get().getParameter(OAuth2ParameterNames.CLIENT_ID);
if (StrUtil.isBlank(clientId)) {
clientId = basicConvert.convert(request).getName();
......
......@@ -19,14 +19,13 @@ package com.pig4cloud.pig.auth.support.handler;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpUtil;
import com.pig4cloud.pig.common.core.util.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author lengleng
* @date 2022-06-02
......
......@@ -23,10 +23,11 @@ import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.util.MsgUtils;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import com.pig4cloud.pig.common.core.util.WebUtils;
import com.pig4cloud.pig.common.log.event.SysLogEvent;
import com.pig4cloud.pig.common.log.util.LogTypeEnum;
import com.pig4cloud.pig.common.log.util.SysLogUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
......@@ -38,8 +39,6 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
......@@ -67,7 +66,7 @@ public class PigAuthenticationFailureEventHandler implements AuthenticationFailu
log.info("用户:{} 登录失败,异常:{}", username, exception.getLocalizedMessage());
SysLog logVo = SysLogUtils.getSysLog();
logVo.setTitle("登录失败");
logVo.setType(LogTypeEnum.ERROR.getType());
logVo.setLogType(LogTypeEnum.ERROR.getType());
logVo.setException(exception.getLocalizedMessage());
// 发送异步日志事件
String startTimeStr = request.getHeader(CommonConstants.REQUEST_START_TIME);
......@@ -76,10 +75,7 @@ public class PigAuthenticationFailureEventHandler implements AuthenticationFailu
Long endTime = System.currentTimeMillis();
logVo.setTime(endTime - startTime);
}
logVo.setServiceId(WebUtils.getClientId());
logVo.setCreateBy(username);
logVo.setUpdateBy(username);
SpringContextHolder.publishEvent(new SysLogEvent(logVo));
// 写出错误信息
sendErrorResponse(request, response, exception);
......@@ -103,7 +99,7 @@ public class PigAuthenticationFailureEventHandler implements AuthenticationFailu
// 手机号登录
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
if (SecurityConstants.APP.equals(grantType)) {
if (SecurityConstants.MOBILE.equals(grantType)) {
errorMessage = MsgUtils.getSecurityMessage("AbstractUserDetailsAuthenticationProvider.smsBadCredentials");
}
......
......@@ -24,24 +24,23 @@ import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import com.pig4cloud.pig.common.log.event.SysLogEvent;
import com.pig4cloud.pig.common.log.util.SysLogUtils;
import com.pig4cloud.pig.common.security.component.PigCustomOAuth2AccessTokenResponseHttpMessageConverter;
import com.pig4cloud.pig.common.security.service.PigUser;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.temporal.ChronoUnit;
import java.util.Map;
......@@ -53,7 +52,7 @@ import java.util.Map;
@Slf4j
public class PigAuthenticationSuccessEventHandler implements AuthenticationSuccessHandler {
private final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter = new OAuth2AccessTokenResponseHttpMessageConverter();
private final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter = new PigCustomOAuth2AccessTokenResponseHttpMessageConverter();
/**
* Called when a user has been successfully authenticated.
......@@ -72,10 +71,7 @@ public class PigAuthenticationSuccessEventHandler implements AuthenticationSucce
// 发送异步日志事件
PigUser userInfo = (PigUser) map.get(SecurityConstants.DETAILS_USER);
log.info("用户:{} 登录成功", userInfo.getName());
// 避免 race condition
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(accessTokenAuthentication);
SecurityContextHolder.setContext(context);
SecurityContextHolder.getContext().setAuthentication(accessTokenAuthentication);
SysLog logVo = SysLogUtils.getSysLog();
logVo.setTitle("登录成功");
String startTimeStr = request.getHeader(CommonConstants.REQUEST_START_TIME);
......@@ -84,10 +80,7 @@ public class PigAuthenticationSuccessEventHandler implements AuthenticationSucce
Long endTime = System.currentTimeMillis();
logVo.setTime(endTime - startTime);
}
logVo.setServiceId(accessTokenAuthentication.getRegisteredClient().getClientId());
logVo.setCreateBy(userInfo.getName());
logVo.setUpdateBy(userInfo.getName());
SpringContextHolder.publishEvent(new SysLogEvent(logVo));
}
......@@ -121,6 +114,7 @@ public class PigAuthenticationSuccessEventHandler implements AuthenticationSucce
// 无状态 注意删除 context 上下文的信息
SecurityContextHolder.clearContext();
this.accessTokenHttpResponseConverter.write(accessTokenResponse, null, httpResponse);
}
......
......@@ -70,7 +70,6 @@ public class PigLogoutSuccessEventHandler implements ApplicationListener<LogoutS
logVo.setServiceId(authentication.getCredentials().toString());
}
logVo.setCreateBy(authentication.getName());
logVo.setUpdateBy(authentication.getName());
SpringContextHolder.publishEvent(new SysLogEvent(logVo));
}
......
package com.pig4cloud.pig.auth.support.handler;
import cn.hutool.core.util.StrUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
......
......@@ -2,6 +2,7 @@ package com.pig4cloud.pig.auth.support.password;
import com.pig4cloud.pig.auth.support.base.OAuth2ResourceOwnerBaseAuthenticationConverter;
import com.pig4cloud.pig.common.security.util.OAuth2EndpointUtils;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
......@@ -9,7 +10,6 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Set;
......
......@@ -3,13 +3,13 @@ package com.pig4cloud.pig.auth.support.sms;
import com.pig4cloud.pig.auth.support.base.OAuth2ResourceOwnerBaseAuthenticationConverter;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.security.util.OAuth2EndpointUtils;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Set;
......@@ -29,13 +29,13 @@ public class OAuth2ResourceOwnerSmsAuthenticationConverter
*/
@Override
public boolean support(String grantType) {
return SecurityConstants.APP.equals(grantType);
return SecurityConstants.MOBILE.equals(grantType);
}
@Override
public OAuth2ResourceOwnerSmsAuthenticationToken buildToken(Authentication clientPrincipal, Set requestedScopes,
Map additionalParameters) {
return new OAuth2ResourceOwnerSmsAuthenticationToken(new AuthorizationGrantType(SecurityConstants.APP),
return new OAuth2ResourceOwnerSmsAuthenticationToken(new AuthorizationGrantType(SecurityConstants.MOBILE),
clientPrincipal, requestedScopes, additionalParameters);
}
......
......@@ -52,7 +52,7 @@ public class OAuth2ResourceOwnerSmsAuthenticationProvider
public void checkClient(RegisteredClient registeredClient) {
assert registeredClient != null;
if (!registeredClient.getAuthorizationGrantTypes()
.contains(new AuthorizationGrantType(SecurityConstants.APP))) {
.contains(new AuthorizationGrantType(SecurityConstants.MOBILE))) {
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
}
}
......
......@@ -6,7 +6,7 @@
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-bom</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
<packaging>pom</packaging>
<name>pig-common-bom</name>
......@@ -15,25 +15,27 @@
<properties>
<pig.common.version>${project.version}</pig.common.version>
<spring-boot.version>2.7.10</spring-boot.version>
<spring-boot.version>2.7.15</spring-boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<log4j2.version>2.17.1</log4j2.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<git.commit.plugin>4.9.9</git.commit.plugin>
<spring.checkstyle.plugin>0.0.34</spring.checkstyle.plugin>
<spring.checkstyle.plugin>0.0.39</spring.checkstyle.plugin>
<fastjson.version>1.2.83</fastjson.version>
<springdoc.version>1.6.9</springdoc.version>
<swagger.core.version>2.2.0</swagger.core.version>
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<mybatis-plus.version>3.5.3.2</mybatis-plus.version>
<dynamic-ds.version>4.1.3</dynamic-ds.version>
<mysql.version>8.0.33</mysql.version>
<seata.version>1.6.1</seata.version>
<excel.version>1.2.6</excel.version>
<asm.version>7.1</asm.version>
<aws.version>1.11.543</aws.version>
<oss.version>1.0.5</oss.version>
<sms.version>2.0.2</sms.version>
<jaxb.version>2.3.5</jaxb.version>
<hutool.version>5.8.20</hutool.version>
<hutool.version>5.8.21</hutool.version>
<mica.version>2.7.4</mica.version>
<sentinel.version>1.8.4</sentinel.version>
</properties>
......@@ -91,6 +93,11 @@
<artifactId>pig-common-xss</artifactId>
<version>${pig.common.version}</version>
</dependency>
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-oss</artifactId>
<version>${pig.common.version}</version>
</dependency>
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-upms-api</artifactId>
......@@ -134,6 +141,18 @@
<artifactId>excel-spring-boot-starter</artifactId>
<version>${excel.version}</version>
</dependency>
<!--动态数据源组件-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${dynamic-ds.version}</version>
</dependency>
<!-- S3 sdk -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>${aws.version}</version>
</dependency>
<!-- 阿里云短信下发 -->
<dependency>
<groupId>io.springboot.sms</groupId>
......
......@@ -21,7 +21,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-common-core</artifactId>
......
......@@ -29,11 +29,6 @@ public interface CacheConstants {
*/
String PROJECT_OAUTH_ACCESS = "token::access_token";
/**
* oauth 缓存令牌前缀
*/
String PROJECT_OAUTH_TOKEN = "pig_oauth:token:";
/**
* 验证码前缀
*/
......@@ -54,6 +49,11 @@ public interface CacheConstants {
*/
String DICT_DETAILS = "dict_details";
/**
* 角色信息缓存
*/
String ROLE_DETAILS = "role_details";
/**
* oauth 客户端信息
*/
......
......@@ -65,7 +65,7 @@ public interface SecurityConstants {
/**
* 手机号登录
*/
String APP = "app";
String MOBILE = "mobile";
/**
* {bcrypt} 加密的特征码
......@@ -92,6 +92,11 @@ public interface SecurityConstants {
*/
String DETAILS_USER = "user_info";
/**
* 用户ID
*/
String DETAILS_USER_ID = "user_id";
/**
* 协议字段
*/
......@@ -120,7 +125,7 @@ public interface SecurityConstants {
/**
* 短信登录 参数名称
*/
String SMS_PARAMETER_NAME = "phone";
String SMS_PARAMETER_NAME = "mobile";
/**
* 授权码模式confirm
......
......@@ -16,28 +16,31 @@
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>pig-common</artifactId>
<groupId>com.pig4cloud</groupId>
<version>3.6.7</version>
</parent>
<modelVersion>4.0.0</modelVersion>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>pig-common</artifactId>
<groupId>com.pig4cloud</groupId>
<version>3.7.0-JDK8</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-datasource</artifactId>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-datasource</artifactId>
<packaging>jar</packaging>
<packaging>jar</packaging>
<description>pig 动态切换数据源</description>
<description>pig 动态切换数据源</description>
<dependencies>
<!--mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${dynamic-ds.version}</version>
</dependency>
</dependencies>
<dependencies>
<!--动态数据源组件-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</dependency>
</dependencies>
</project>
......@@ -16,17 +16,29 @@
package com.pig4cloud.pig.common.datasource;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.hikaricp.HikariDataSourceCreator;
import com.baomidou.dynamic.datasource.processor.DsHeaderProcessor;
import com.baomidou.dynamic.datasource.processor.DsProcessor;
import com.baomidou.dynamic.datasource.processor.DsSessionProcessor;
import com.baomidou.dynamic.datasource.processor.DsSpelExpressionProcessor;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.pig4cloud.pig.common.datasource.config.ClearTtlDataSourceFilter;
import com.pig4cloud.pig.common.datasource.config.DataSourceProperties;
import com.pig4cloud.pig.common.datasource.config.JdbcDynamicDataSourceProvider;
import com.pig4cloud.pig.common.datasource.config.LastParamDsProcessor;
import org.jasypt.encryption.StringEncryptor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.expression.BeanFactoryResolver;
import java.util.ArrayList;
import java.util.List;
/**
* @author lengleng
......@@ -39,15 +51,57 @@ import org.springframework.context.annotation.Configuration;
@EnableConfigurationProperties(DataSourceProperties.class)
public class DynamicDataSourceAutoConfiguration {
/**
* 动态数据源提供者
* @param defaultDataSourceCreator 默认数据源创建器
* @param stringEncryptor 字符串加密器
* @param properties 数据源配置属性
* @return 动态数据源提供者
*/
@Bean
public DynamicDataSourceProvider dynamicDataSourceProvider(DefaultDataSourceCreator defaultDataSourceCreator,
StringEncryptor stringEncryptor, DataSourceProperties properties) {
return new JdbcDynamicDataSourceProvider(defaultDataSourceCreator, stringEncryptor, properties);
}
/**
* 获取数据源处理器
* @return 数据源处理器
*/
@Bean
public DsProcessor dsProcessor(BeanFactory beanFactory) {
DsProcessor lastParamDsProcessor = new LastParamDsProcessor();
DsProcessor headerProcessor = new DsHeaderProcessor();
DsProcessor sessionProcessor = new DsSessionProcessor();
DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor();
spelExpressionProcessor.setBeanResolver(new BeanFactoryResolver(beanFactory));
lastParamDsProcessor.setNextProcessor(headerProcessor);
headerProcessor.setNextProcessor(sessionProcessor);
sessionProcessor.setNextProcessor(spelExpressionProcessor);
return lastParamDsProcessor;
}
/**
* 默认数据源创建器
* @param hikariDataSourceCreator Hikari数据源创建器
* @return 默认数据源创建器
*/
@Bean
public DynamicDataSourceProvider dynamicDataSourceProvider(StringEncryptor stringEncryptor,
DataSourceProperties properties) {
return new JdbcDynamicDataSourceProvider(stringEncryptor, properties);
public DefaultDataSourceCreator defaultDataSourceCreator(HikariDataSourceCreator hikariDataSourceCreator) {
DefaultDataSourceCreator defaultDataSourceCreator = new DefaultDataSourceCreator();
List<DataSourceCreator> creators = new ArrayList<>();
creators.add(hikariDataSourceCreator);
defaultDataSourceCreator.setCreators(creators);
return defaultDataSourceCreator;
}
/**
* 清除Ttl数据源过滤器
* @return 清除Ttl数据源过滤器
*/
@Bean
public DsProcessor dsProcessor() {
return new LastParamDsProcessor();
public ClearTtlDataSourceFilter clearTtlDsFilter() {
return new ClearTtlDataSourceFilter();
}
}
package com.pig4cloud.pig.common.datasource.config;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import org.springframework.core.Ordered;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
/**
* @author lengleng
* @date 2020/12/11
* <p>
* 清空上文的DS 设置避免污染当前线程
*/
public class ClearTtlDataSourceFilter extends GenericFilterBean implements Ordered {
@Override
public int getOrder() {
return Integer.MIN_VALUE;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
DynamicDataSourceContextHolder.clear();
filterChain.doFilter(servletRequest, servletResponse);
DynamicDataSourceContextHolder.clear();
}
}
......@@ -16,8 +16,9 @@
package com.pig4cloud.pig.common.datasource.config;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.provider.AbstractJdbcDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.pig4cloud.pig.common.datasource.support.DataSourceConstants;
import org.jasypt.encryption.StringEncryptor;
......@@ -39,8 +40,10 @@ public class JdbcDynamicDataSourceProvider extends AbstractJdbcDataSourceProvide
private final StringEncryptor stringEncryptor;
public JdbcDynamicDataSourceProvider(StringEncryptor stringEncryptor, DataSourceProperties properties) {
super(properties.getDriverClassName(), properties.getUrl(), properties.getUsername(), properties.getPassword());
public JdbcDynamicDataSourceProvider(DefaultDataSourceCreator defaultDataSourceCreator,
StringEncryptor stringEncryptor, DataSourceProperties properties) {
super(defaultDataSourceCreator, properties.getDriverClassName(), properties.getUrl(), properties.getUsername(),
properties.getPassword());
this.stringEncryptor = stringEncryptor;
this.properties = properties;
}
......
package com.pig4cloud.pig.common.datasource.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2020/12/11
* <p>
* 数据源配置类型
*/
@Getter
@AllArgsConstructor
public enum DsConfTypeEnum {
/**
* 主机链接
*/
HOST(0, "主机链接"),
/**
* JDBC链接
*/
JDBC(1, "JDBC链接");
private final Integer type;
private final String description;
}
package com.pig4cloud.pig.common.datasource.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* @author lengleng
* @date 2020/12/11
* <p>
* jdbc-url
*/
@Getter
@AllArgsConstructor
public enum DsJdbcUrlEnum {
/**
* mysql 数据库
*/
MYSQL("mysql",
"jdbc:mysql://%s:%s/%s?characterEncoding=utf8"
+ "&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true"
+ "&useLegacyDatetimeCode=false&allowMultiQueries=true&allowPublicKeyRetrieval=true",
"select 1", "mysql8 链接"),
/**
* pg 数据库
*/
PG("pg", "jdbc:postgresql://%s:%s/%s", "select 1", "postgresql 链接"),
/**
* SQL SERVER
*/
MSSQL("mssql", "jdbc:sqlserver://%s:%s;database=%s;characterEncoding=UTF-8", "select 1", "sqlserver 链接"),
/**
* oracle
*/
ORACLE("oracle", "jdbc:oracle:thin:@%s:%s:%s", "select 1 from dual", "oracle 链接"),
/**
* db2
*/
DB2("db2", "jdbc:db2://%s:%s/%s", "select 1 from sysibm.sysdummy1", "DB2 TYPE4 连接"),
/**
* 达梦
*/
DM("dm", "jdbc:dm://%s:%s/%s", "select 1 from dual", "达梦连接"),
/**
* pg 数据库
*/
HIGHGO("highgo", "jdbc:highgo://%s:%s/%s", "select 1", "highgo 链接");
private final String dbName;
private final String url;
private final String validationQuery;
private final String description;
public static DsJdbcUrlEnum get(String dsType) {
return Arrays.stream(DsJdbcUrlEnum.values())
.filter(dsJdbcUrlEnum -> dsType.equals(dsJdbcUrlEnum.getDbName()))
.findFirst()
.get();
}
}
......@@ -21,7 +21,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -23,13 +23,13 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-common-job</artifactId>
<packaging>jar</packaging>
<description>pig 定时任务,基于xxl-job</description>
<description>pig 定时任务,基于xxl-job 支持自动发现</description>
<dependencies>
......
......@@ -21,7 +21,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-common-log</artifactId>
......
......@@ -18,9 +18,10 @@ package com.pig4cloud.pig.common.log;
import com.pig4cloud.pig.admin.api.feign.RemoteLogService;
import com.pig4cloud.pig.common.log.aspect.SysLogAspect;
import com.pig4cloud.pig.common.log.config.PigLogProperties;
import com.pig4cloud.pig.common.log.event.SysLogListener;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
......@@ -30,14 +31,14 @@ import org.springframework.scheduling.annotation.EnableAsync;
* @date 2019/2/1 日志自动配置
*/
@EnableAsync
@RequiredArgsConstructor
@ConditionalOnWebApplication
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(PigLogProperties.class)
@ConditionalOnProperty(value = "security.log.enabled", matchIfMissing = true)
public class LogAutoConfiguration {
@Bean
public SysLogListener sysLogListener(RemoteLogService remoteLogService) {
return new SysLogListener(remoteLogService);
public SysLogListener sysLogListener(PigLogProperties logProperties, RemoteLogService remoteLogService) {
return new SysLogListener(remoteLogService, logProperties);
}
@Bean
......
......@@ -17,11 +17,12 @@
package com.pig4cloud.pig.common.log.aspect;
import cn.hutool.core.util.StrUtil;
import com.pig4cloud.pig.admin.api.entity.SysLog;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import com.pig4cloud.pig.common.log.event.SysLogEvent;
import com.pig4cloud.pig.common.log.event.SysLogEventSource;
import com.pig4cloud.pig.common.log.util.LogTypeEnum;
import com.pig4cloud.pig.common.log.util.SysLogUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
......@@ -37,6 +38,7 @@ import org.springframework.expression.EvaluationContext;
*/
@Aspect
@Slf4j
@RequiredArgsConstructor
public class SysLogAspect {
@Around("@annotation(sysLog)")
......@@ -62,9 +64,12 @@ public class SysLogAspect {
}
}
SysLog logVo = SysLogUtils.getSysLog();
SysLogEventSource logVo = SysLogUtils.getSysLog();
logVo.setTitle(value);
// 获取请求body参数
if (StrUtil.isBlank(logVo.getParams())) {
logVo.setBody(point.getArgs());
}
// 发送异步日志事件
Long startTime = System.currentTimeMillis();
Object obj;
......@@ -73,7 +78,7 @@ public class SysLogAspect {
obj = point.proceed();
}
catch (Exception e) {
logVo.setType(LogTypeEnum.ERROR.getType());
logVo.setLogType(LogTypeEnum.ERROR.getType());
logVo.setException(e.getMessage());
throw e;
}
......
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.dashboard.config;
package com.pig4cloud.pig.common.log.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "auth")
public class AuthProperties {
import java.util.List;
/**
* 日志配置类
*
* @author L.cm
*/
@Getter
@Setter
@ConfigurationProperties(PigLogProperties.PREFIX)
public class PigLogProperties {
public static final String PREFIX = "security.log";
/**
* 开启日志记录
*/
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
/**
* 放行字段,password,mobile,idcard,phone
*/
@Value("${security.log.exclude-fields:password,mobile,idcard,phone}")
private List<String> excludeFields;
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
/**
* 请求报文最大存储长度
*/
private Integer maxLength = 2000;
}
package com.pig4cloud.pig.common.log.event;
import com.pig4cloud.pig.admin.api.entity.SysLog;
import lombok.Data;
/**
* spring event log
*
* @author lengleng
* @date 2023/8/11
*/
@Data
public class SysLogEventSource extends SysLog {
/**
* 参数重写成object
*/
private Object body;
}
......@@ -16,29 +16,74 @@
package com.pig4cloud.pig.common.log.event;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.pig4cloud.pig.admin.api.entity.SysLog;
import com.pig4cloud.pig.admin.api.feign.RemoteLogService;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.jackson.PigJavaTimeModule;
import com.pig4cloud.pig.common.log.config.PigLogProperties;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import java.util.Objects;
/**
* @author lengleng 异步监听日志事件
*/
@Slf4j
@RequiredArgsConstructor
public class SysLogListener {
public class SysLogListener implements InitializingBean {
// new 一个 避免日志脱敏策略影响全局ObjectMapper
private final static ObjectMapper objectMapper = new ObjectMapper();
private final RemoteLogService remoteLogService;
private final PigLogProperties logProperties;
@SneakyThrows
@Async
@Order
@EventListener(SysLogEvent.class)
public void saveSysLog(SysLogEvent event) {
SysLog sysLog = (SysLog) event.getSource();
remoteLogService.saveLog(sysLog);
SysLogEventSource source = (SysLogEventSource) event.getSource();
SysLog sysLog = new SysLog();
BeanUtils.copyProperties(source, sysLog);
// json 格式刷参数放在异步中处理,提升性能
if (Objects.nonNull(source.getBody())) {
String params = objectMapper.writeValueAsString(source.getBody());
sysLog.setParams(StrUtil.subPre(params, logProperties.getMaxLength()));
}
remoteLogService.saveLog(sysLog, SecurityConstants.FROM_IN);
}
@Override
public void afterPropertiesSet() {
objectMapper.addMixIn(Object.class, PropertyFilterMixIn.class);
String[] ignorableFieldNames = logProperties.getExcludeFields().toArray(new String[0]);
FilterProvider filters = new SimpleFilterProvider().addFilter("filter properties by name",
SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames));
objectMapper.setFilterProvider(filters);
objectMapper.registerModule(new PigJavaTimeModule());
}
@JsonFilter("filter properties by name")
class PropertyFilterMixIn {
}
}
......@@ -36,6 +36,9 @@ public class ApplicationLoggerInitializer implements EnvironmentPostProcessor, O
// spring boot admin 直接加载日志
System.setProperty("logging.file.name", String.format("%s/%s/debug.log", logBase, appName));
// 避免 sentinel 1.8.4+ 心跳日志过大
System.setProperty("csp.sentinel.log.level", "OFF");
}
@Override
......
......@@ -17,13 +17,17 @@
package com.pig4cloud.pig.common.log.util;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpUtil;
import com.pig4cloud.pig.admin.api.entity.SysLog;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import com.pig4cloud.pig.common.log.config.PigLogProperties;
import com.pig4cloud.pig.common.log.event.SysLogEventSource;
import lombok.experimental.UtilityClass;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.StandardReflectionParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
......@@ -37,6 +41,7 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
/**
......@@ -47,38 +52,24 @@ import java.util.Objects;
@UtilityClass
public class SysLogUtils {
public SysLog getSysLog() {
public SysLogEventSource getSysLog() {
HttpServletRequest request = ((ServletRequestAttributes) Objects
.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
SysLog sysLog = new SysLog();
sysLog.setType(LogTypeEnum.NORMAL.getType());
sysLog.setRemoteAddr(ServletUtil.getClientIP(request));
SysLogEventSource sysLog = new SysLogEventSource();
sysLog.setLogType(LogTypeEnum.NORMAL.getType());
sysLog.setRequestUri(URLUtil.getPath(request.getRequestURI()));
sysLog.setMethod(request.getMethod());
sysLog.setRemoteAddr(ServletUtil.getClientIP(request));
sysLog.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
sysLog.setParams(HttpUtil.toParams(request.getParameterMap()));
sysLog.setCreateBy(getUsername());
sysLog.setUpdateBy(getUsername());
sysLog.setServiceId(getClientId());
return sysLog;
}
/**
* 获取客户端
* @return clientId
*/
private String getClientId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
return null;
}
Object principal = authentication.getPrincipal();
if (principal instanceof OAuth2AuthenticatedPrincipal) {
OAuth2AuthenticatedPrincipal auth2Authentication = (OAuth2AuthenticatedPrincipal) principal;
return MapUtil.getStr(auth2Authentication.getAttributes(), SecurityConstants.CLIENT_ID);
}
return null;
// get 参数脱敏
PigLogProperties logProperties = SpringContextHolder.getBean(PigLogProperties.class);
Map<String, String[]> paramsMap = MapUtil.removeAny(request.getParameterMap(),
ArrayUtil.toArray(logProperties.getExcludeFields(), String.class));
sysLog.setParams(HttpUtil.toParams(paramsMap));
return sysLog;
}
/**
......@@ -114,7 +105,7 @@ public class SysLogUtils {
* @return 装载参数的容器
*/
public EvaluationContext getContext(Object[] arguments, Method signatureMethod) {
String[] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(signatureMethod);
String[] parameterNames = new StandardReflectionParameterNameDiscoverer().getParameterNames(signatureMethod);
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames == null) {
return context;
......@@ -125,4 +116,22 @@ public class SysLogUtils {
return context;
}
/**
* 获取客户端
* @return clientId
*/
private String getClientId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
return null;
}
Object principal = authentication.getPrincipal();
if (principal instanceof OAuth2AuthenticatedPrincipal) {
OAuth2AuthenticatedPrincipal auth2Authentication = (OAuth2AuthenticatedPrincipal) principal;
return MapUtil.getStr(auth2Authentication.getAttributes(), SecurityConstants.CLIENT_ID);
}
return null;
}
}
{
"groups": [
{
"name": "security.log",
"type": "com.pig4cloud.pig.common.log.config.PigLogProperties",
"sourceType": "com.pig4cloud.pig.common.log.config.PigLogProperties"
}
],
"properties": [
{
"name": "security.log.enabled",
"type": "java.lang.Boolean",
"description": "开启日志记录",
"sourceType": "com.pig4cloud.pig.common.log.config.PigLogProperties"
},
{
"name": "security.log.exclude-fields",
"type": "java.util.List<java.lang.String>",
"description": "放行字段,password,mobile,idcard,phone",
"sourceType": "com.pig4cloud.pig.common.log.config.PigLogProperties"
},
{
"name": "security.log.max-length",
"type": "java.lang.Integer",
"description": "请求报文最大存储长度",
"sourceType": "com.pig4cloud.pig.common.log.config.PigLogProperties"
}
],
"hints": []
}
# https://github.com/spring-projects/spring-boot/issues/31252
org.springframework.boot.env.EnvironmentPostProcessor=\
com.pig4cloud.pig.common.log.init.ApplicationLoggerInitializer
......@@ -21,7 +21,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-common-mybatis</artifactId>
......@@ -45,17 +45,12 @@
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</dependency>
<!---->
<!--swagger 注解-->
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<!--server-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
......@@ -67,5 +62,9 @@
<artifactId>spring-security-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-core</artifactId>
</dependency>
</dependencies>
</project>
......@@ -2,8 +2,10 @@ package com.pig4cloud.pig.common.mybatis.config;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.ClassUtils;
......@@ -25,10 +27,13 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
log.debug("mybatis plus start insert fill ....");
LocalDateTime now = LocalDateTime.now();
fillValIfNullByName("createTime", now, metaObject, false);
fillValIfNullByName("updateTime", now, metaObject, false);
fillValIfNullByName("createBy", getUserName(), metaObject, false);
fillValIfNullByName("updateBy", getUserName(), metaObject, false);
fillValIfNullByName("createTime", now, metaObject, true);
fillValIfNullByName("updateTime", now, metaObject, true);
fillValIfNullByName("createBy", getUserName(), metaObject, true);
fillValIfNullByName("updateBy", getUserName(), metaObject, true);
// 删除标记自动填充
fillValIfNullByName("delFlag", CommonConstants.STATUS_NORMAL, metaObject, true);
}
@Override
......@@ -46,6 +51,11 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
* @param isCover 是否覆盖原有值,避免更新操作手动入参
*/
private static void fillValIfNullByName(String fieldName, Object fieldVal, MetaObject metaObject, boolean isCover) {
// 0. 如果填充值为空
if (fieldVal == null) {
return;
}
// 1. 没有 set 方法
if (!metaObject.hasSetter(fieldName)) {
return;
......@@ -69,9 +79,15 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
*/
private String getUserName() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 匿名接口直接返回
if (authentication instanceof AnonymousAuthenticationToken) {
return null;
}
if (Optional.ofNullable(authentication).isPresent()) {
return authentication.getName();
}
return null;
}
......
package com.pig4cloud.pig.common.mybatis.handler;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Mybatis数组,符串互转
* <p>
* MappedJdbcTypes 数据库中的数据类型 MappedTypes java中的的数据类型
*
* @author xuzihui
* @date 2019-11-20
*/
@MappedTypes(value = { Long[].class })
@MappedJdbcTypes(value = JdbcType.VARCHAR)
public class JsonLongArrayTypeHandler extends BaseTypeHandler<Long[]> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Long[] parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, ArrayUtil.join(parameter, StrUtil.COMMA));
}
@Override
@SneakyThrows
public Long[] getNullableResult(ResultSet rs, String columnName) {
String reString = rs.getString(columnName);
return Convert.toLongArray(reString);
}
@Override
@SneakyThrows
public Long[] getNullableResult(ResultSet rs, int columnIndex) {
String reString = rs.getString(columnIndex);
return Convert.toLongArray(reString);
}
@Override
@SneakyThrows
public Long[] getNullableResult(CallableStatement cs, int columnIndex) {
String reString = cs.getString(columnIndex);
return Convert.toLongArray(reString);
}
}
package com.pig4cloud.pig.common.mybatis.handler;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Mybatis数组,符串互转
* <p>
* MappedJdbcTypes 数据库中的数据类型 MappedTypes java中的的数据类型
*
* @author xuzihui
* @date 2019-11-20
*/
@MappedTypes(value = { String[].class })
@MappedJdbcTypes(value = JdbcType.VARCHAR)
public class JsonStringArrayTypeHandler extends BaseTypeHandler<String[]> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String[] parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, ArrayUtil.join(parameter, StrUtil.COMMA));
}
@Override
@SneakyThrows
public String[] getNullableResult(ResultSet rs, String columnName) {
String reString = rs.getString(columnName);
return Convert.toStrArray(reString);
}
@Override
@SneakyThrows
public String[] getNullableResult(ResultSet rs, int columnIndex) {
String reString = rs.getString(columnIndex);
return Convert.toStrArray(reString);
}
@Override
@SneakyThrows
public String[] getNullableResult(CallableStatement cs, int columnIndex) {
String reString = cs.getString(columnIndex);
return Convert.toStrArray(reString);
}
}
......@@ -21,6 +21,7 @@ package com.pig4cloud.pig.common.mybatis.resolver;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
......@@ -28,7 +29,6 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
......
<?xml version="1.0" encoding="UTF-8"?>
<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>pig-common</artifactId>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-common-oss</artifactId>
<packaging>jar</packaging>
<description>pig 文件系统依赖</description>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
</dependencies>
</project>
/*
* 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.pig.common.file;
import com.pig4cloud.pig.common.file.core.FileProperties;
import com.pig4cloud.pig.common.file.local.LocalFileAutoConfiguration;
import com.pig4cloud.pig.common.file.oss.OssAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
/**
* aws 自动配置类
*
* @author lengleng
* @author 858695266
*/
@Import({ LocalFileAutoConfiguration.class, OssAutoConfiguration.class })
@EnableConfigurationProperties({ FileProperties.class })
public class FileAutoConfiguration {
}
/*
* 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.pig.common.file.core;
import com.pig4cloud.pig.common.file.local.LocalFileProperties;
import com.pig4cloud.pig.common.file.oss.OssProperties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 文件 配置信息
*
* @author lengleng
* <p>
* bucket 设置公共读权限
*/
@Data
@ConfigurationProperties(prefix = "file")
public class FileProperties {
/**
* 默认的存储桶名称
*/
private String bucketName = "local";
/**
* 本地文件配置信息
*/
private LocalFileProperties local;
/**
* oss 文件配置信息
*/
private OssProperties oss;
}
package com.pig4cloud.pig.common.file.core;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import org.springframework.beans.factory.InitializingBean;
import java.io.InputStream;
import java.util.List;
/**
* 文件操作模板
*
* @author lengleng
* @date 2022/4/19
*/
public interface FileTemplate extends InitializingBean {
/**
* 创建bucket
* @param bucketName bucket名称
*/
void createBucket(String bucketName);
/**
* 获取全部bucket
* <p>
*
* API Documentation</a>
*/
List<Bucket> getAllBuckets();
/**
* @param bucketName bucket名称
* @see <a href= Documentation</a>
*/
void removeBucket(String bucketName);
/**
* 上传文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @param contextType 文件类型
* @throws Exception
*/
void putObject(String bucketName, String objectName, InputStream stream, String contextType) throws Exception;
/**
* 上传文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @param contextType 文件类型
* @throws Exception
*/
void putObject(String bucketName, String objectName, InputStream stream) throws Exception;
/**
* 获取文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @return 二进制流 API Documentation</a>
*/
S3Object getObject(String bucketName, String objectName);
void removeObject(String bucketName, String objectName) throws Exception;
/**
* @throws Exception
*/
@Override
default void afterPropertiesSet() throws Exception {
}
/**
* 根据文件前置查询文件
* @param bucketName bucket名称
* @param prefix 前缀
* @param recursive 是否递归查询
* @return S3ObjectSummary 列表
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListObjects">AWS
* API Documentation</a>
*/
List<S3ObjectSummary> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive);
}
/*
* 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.pig.common.file.local;
import com.pig4cloud.pig.common.file.core.FileProperties;
import com.pig4cloud.pig.common.file.core.FileTemplate;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
/**
* aws 自动配置类
*
* @author lengleng
* @author 858695266
*/
@AllArgsConstructor
public class LocalFileAutoConfiguration {
private final FileProperties properties;
@Bean
@ConditionalOnMissingBean(LocalFileTemplate.class)
@ConditionalOnProperty(name = "file.local.enable", havingValue = "true", matchIfMissing = true)
public FileTemplate localFileTemplate() {
return new LocalFileTemplate(properties);
}
}
/*
* 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.pig.common.file.local;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 本地文件 配置信息
*
* @author lengleng
* <p>
* bucket 设置公共读权限
*/
@Data
@ConfigurationProperties(prefix = "local")
public class LocalFileProperties {
/**
* 是否开启
*/
private boolean enable;
/**
* 默认路径
*/
private String basePath;
}
package com.pig4cloud.pig.common.file.local;
import cn.hutool.core.io.FileUtil;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.pig4cloud.pig.common.file.core.FileProperties;
import com.pig4cloud.pig.common.file.core.FileTemplate;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import java.io.File;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 本地文件读取模式
*
* @author lengleng
* @date 2022/4/19
*/
@RequiredArgsConstructor
public class LocalFileTemplate implements FileTemplate {
private final FileProperties properties;
/**
* 创建bucket
* @param bucketName bucket名称
*/
@Override
public void createBucket(String bucketName) {
FileUtil.mkdir(properties.getLocal().getBasePath() + FileUtil.FILE_SEPARATOR + bucketName);
}
/**
* 获取全部bucket
* <p>
* <p>
* API Documentation</a>
*/
@Override
public List<Bucket> getAllBuckets() {
return Arrays.stream(FileUtil.ls(properties.getLocal().getBasePath()))
.filter(FileUtil::isDirectory)
.map(dir -> new Bucket(dir.getName()))
.collect(Collectors.toList());
}
/**
* @param bucketName bucket名称
* @see <a href= Documentation</a>
*/
@Override
public void removeBucket(String bucketName) {
FileUtil.del(properties.getLocal().getBasePath() + FileUtil.FILE_SEPARATOR + bucketName);
}
/**
* 上传文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @param contextType 文件类型
*/
@Override
public void putObject(String bucketName, String objectName, InputStream stream, String contextType) {
// 当 Bucket 不存在时创建
String dir = properties.getLocal().getBasePath() + FileUtil.FILE_SEPARATOR + bucketName;
if (!FileUtil.isDirectory(properties.getLocal().getBasePath() + FileUtil.FILE_SEPARATOR + bucketName)) {
createBucket(bucketName);
}
// 写入文件
File file = FileUtil.file(dir + FileUtil.FILE_SEPARATOR + objectName);
FileUtil.writeFromStream(stream, file);
}
/**
* 获取文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @return 二进制流 API Documentation</a>
*/
@Override
@SneakyThrows
public S3Object getObject(String bucketName, String objectName) {
String dir = properties.getLocal().getBasePath() + FileUtil.FILE_SEPARATOR + bucketName;
S3Object s3Object = new S3Object();
s3Object.setObjectContent(FileUtil.getInputStream(dir + FileUtil.FILE_SEPARATOR + objectName));
return s3Object;
}
/**
* @param bucketName
* @param objectName
* @throws Exception
*/
@Override
public void removeObject(String bucketName, String objectName) throws Exception {
String dir = properties.getLocal().getBasePath() + FileUtil.FILE_SEPARATOR + bucketName;
FileUtil.del(dir + FileUtil.FILE_SEPARATOR + objectName);
}
/**
* 上传文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @throws Exception
*/
@Override
public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
putObject(bucketName, objectName, stream, null);
}
/**
* 根据文件前置查询文件
* @param bucketName bucket名称
* @param prefix 前缀
* @param recursive 是否递归查询
* @return S3ObjectSummary 列表
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListObjects">AWS
* API Documentation</a>
*/
@Override
public List<S3ObjectSummary> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
String dir = properties.getLocal().getBasePath() + FileUtil.FILE_SEPARATOR + bucketName;
return Arrays.stream(FileUtil.ls(dir)).filter(file -> file.getName().startsWith(prefix)).map(file -> {
S3ObjectSummary summary = new S3ObjectSummary();
summary.setKey(file.getName());
return new S3ObjectSummary();
}).collect(Collectors.toList());
}
}
/*
* 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.pig.common.file.oss;
import com.pig4cloud.pig.common.file.core.FileProperties;
import com.pig4cloud.pig.common.file.core.FileTemplate;
import com.pig4cloud.pig.common.file.oss.http.OssEndpoint;
import com.pig4cloud.pig.common.file.oss.service.OssTemplate;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
/**
* aws 自动配置类
*
* @author lengleng
* @author 858695266
*/
@AllArgsConstructor
public class OssAutoConfiguration {
private final FileProperties properties;
@Bean
@Primary
@ConditionalOnMissingBean(OssTemplate.class)
@ConditionalOnProperty(name = "file.oss.enable", havingValue = "true")
public FileTemplate ossTemplate() {
return new OssTemplate(properties);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "file.oss.info", havingValue = "true")
public OssEndpoint ossEndpoint(OssTemplate template) {
return new OssEndpoint(template);
}
}
/*
* 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.pig.common.file.oss;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* aws 配置信息
*
* @author lengleng
* @author 858695266 配置文件添加: oss: enable: true endpoint: http://127.0.0.1:9000 #
* pathStyleAccess 采用nginx反向代理或者AWS S3 配置成true,支持第三方云存储配置成false pathStyleAccess: false
* access-key: lengleng secret-key: lengleng bucket-name: lengleng region: custom-domain:
* https://oss.xxx.com/lengleng
* <p>
* bucket 设置公共读权限
*/
@Data
@ConfigurationProperties(prefix = "oss")
public class OssProperties {
/**
* 对象存储服务的URL
*/
private String endpoint;
/**
* 自定义域名
*/
private String customDomain;
/**
* true path-style nginx 反向代理和S3默认支持 pathStyle {http://endpoint/bucketname} false
* supports virtual-hosted-style 阿里云等需要配置为 virtual-hosted-style
* 模式{http://bucketname.endpoint}
*/
private Boolean pathStyleAccess = true;
/**
* 应用ID
*/
private String appId;
/**
* 区域
*/
private String region;
/**
* Access key就像用户ID,可以唯一标识你的账户
*/
private String accessKey;
/**
* Secret key是你账户的密码
*/
private String secretKey;
/**
* 最大线程数,默认: 100
*/
private Integer maxConnections = 100;
}
/*
* 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.pig.common.file.oss.http;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.pig4cloud.pig.common.file.oss.service.OssTemplate;
import lombok.AllArgsConstructor;
import lombok.Cleanup;
import lombok.SneakyThrows;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* aws 对外提供服务端点
*
* @author lengleng
* @author 858695266
* <p>
* oss.info
*/
@RestController
@AllArgsConstructor
@RequestMapping("/oss")
@ConditionalOnProperty(name = "file.oss.info", havingValue = "true")
public class OssEndpoint {
private final OssTemplate template;
/**
* Bucket Endpoints
*/
@SneakyThrows
@PostMapping("/bucket/{bucketName}")
public Bucket createBucker(@PathVariable String bucketName) {
template.createBucket(bucketName);
return template.getBucket(bucketName).get();
}
@SneakyThrows
@GetMapping("/bucket")
public List<Bucket> getBuckets() {
return template.getAllBuckets();
}
@SneakyThrows
@GetMapping("/bucket/{bucketName}")
public Bucket getBucket(@PathVariable String bucketName) {
return template.getBucket(bucketName).orElseThrow(() -> new IllegalArgumentException("Bucket Name not found!"));
}
@SneakyThrows
@DeleteMapping("/bucket/{bucketName}")
@ResponseStatus(HttpStatus.ACCEPTED)
public void deleteBucket(@PathVariable String bucketName) {
template.removeBucket(bucketName);
}
/**
* Object Endpoints
*/
@SneakyThrows
@PostMapping("/object/{bucketName}")
public S3Object createObject(@RequestBody MultipartFile object, @PathVariable String bucketName) {
String name = object.getOriginalFilename();
@Cleanup
InputStream inputStream = object.getInputStream();
template.putObject(bucketName, name, inputStream, object.getSize(), object.getContentType());
return template.getObjectInfo(bucketName, name);
}
@SneakyThrows
@PostMapping("/object/{bucketName}/{objectName}")
public S3Object createObject(@RequestBody MultipartFile object, @PathVariable String bucketName,
@PathVariable String objectName) {
@Cleanup
InputStream inputStream = object.getInputStream();
template.putObject(bucketName, objectName, inputStream, object.getSize(), object.getContentType());
return template.getObjectInfo(bucketName, objectName);
}
@SneakyThrows
@GetMapping("/object/{bucketName}/{objectName}")
public List<S3ObjectSummary> filterObject(@PathVariable String bucketName, @PathVariable String objectName) {
return template.getAllObjectsByPrefix(bucketName, objectName, true);
}
@SneakyThrows
@GetMapping("/object/{bucketName}/{objectName}/{expires}")
public Map<String, Object> getObject(@PathVariable String bucketName, @PathVariable String objectName,
@PathVariable Integer expires) {
Map<String, Object> responseBody = new HashMap<>(8);
// Put Object info
responseBody.put("bucket", bucketName);
responseBody.put("object", objectName);
responseBody.put("url", template.getObjectURL(bucketName, objectName, expires));
responseBody.put("expires", expires);
return responseBody;
}
@SneakyThrows
@ResponseStatus(HttpStatus.ACCEPTED)
@DeleteMapping("/object/{bucketName}/{objectName}/")
public void deleteObject(@PathVariable String bucketName, @PathVariable String objectName) {
template.removeObject(bucketName, objectName);
}
}
/*
* 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.pig.common.file.oss.service;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.*;
import com.amazonaws.util.IOUtils;
import com.pig4cloud.pig.common.file.core.FileProperties;
import com.pig4cloud.pig.common.file.core.FileTemplate;
import lombok.Cleanup;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.beans.factory.InitializingBean;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
/**
* aws-s3 通用存储操作 支持所有兼容s3协议的云存储: {阿里云OSS,腾讯云COS,七牛云,京东云,minio 等}
*
* @author lengleng
* @author 858695266
* @date 2020/5/23 6:36 上午
* @since 1.0
*/
@RequiredArgsConstructor
public class OssTemplate implements InitializingBean, FileTemplate {
private final FileProperties properties;
private AmazonS3 amazonS3;
/**
* 创建bucket
* @param bucketName bucket名称
*/
@SneakyThrows
public void createBucket(String bucketName) {
if (!amazonS3.doesBucketExistV2(bucketName)) {
amazonS3.createBucket((bucketName));
}
}
/**
* 获取全部bucket
* <p>
*
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListBuckets">AWS
* API Documentation</a>
*/
@SneakyThrows
public List<Bucket> getAllBuckets() {
return amazonS3.listBuckets();
}
/**
* @param bucketName bucket名称
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListBuckets">AWS
* API Documentation</a>
*/
@SneakyThrows
public Optional<Bucket> getBucket(String bucketName) {
return amazonS3.listBuckets().stream().filter(b -> b.getName().equals(bucketName)).findFirst();
}
/**
* @param bucketName bucket名称
* @see <a href=
* "http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/DeleteBucket">AWS API
* Documentation</a>
*/
@SneakyThrows
public void removeBucket(String bucketName) {
amazonS3.deleteBucket(bucketName);
}
/**
* 根据文件前置查询文件
* @param bucketName bucket名称
* @param prefix 前缀
* @param recursive 是否递归查询
* @return S3ObjectSummary 列表
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListObjects">AWS
* API Documentation</a>
*/
@SneakyThrows
public List<S3ObjectSummary> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
ObjectListing objectListing = amazonS3.listObjects(bucketName, prefix);
return new ArrayList<>(objectListing.getObjectSummaries());
}
/**
* 获取文件外链
* @param bucketName bucket名称
* @param objectName 文件名称
* @param expires 过期时间 <=7
* @return url
* @see AmazonS3#generatePresignedUrl(String bucketName, String key, Date expiration)
*/
@SneakyThrows
public String getObjectURL(String bucketName, String objectName, Integer expires) {
Date date = new Date();
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
calendar.add(Calendar.DAY_OF_MONTH, expires);
URL url = amazonS3.generatePresignedUrl(bucketName, objectName, calendar.getTime());
return url.toString();
}
/**
* 获取文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @return 二进制流
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObject">AWS
* API Documentation</a>
*/
@SneakyThrows
public S3Object getObject(String bucketName, String objectName) {
return amazonS3.getObject(bucketName, objectName);
}
/**
* 上传文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @throws Exception
*/
public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
putObject(bucketName, objectName, stream, stream.available(), "application/octet-stream");
}
/**
* 上传文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @param contextType 文件类型
* @throws Exception
*/
public void putObject(String bucketName, String objectName, InputStream stream, String contextType)
throws Exception {
putObject(bucketName, objectName, stream, stream.available(), contextType);
}
/**
* 上传文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @param size 大小
* @param contextType 类型
* @throws Exception
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/PutObject">AWS
* API Documentation</a>
*/
public PutObjectResult putObject(String bucketName, String objectName, InputStream stream, long size,
String contextType) throws Exception {
// String fileName = getFileName(objectName);
byte[] bytes = IOUtils.toByteArray(stream);
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(size);
objectMetadata.setContentType(contextType);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
// 上传
return amazonS3.putObject(bucketName, objectName, byteArrayInputStream, objectMetadata);
}
/**
* 获取文件信息
* @param bucketName bucket名称
* @param objectName 文件名称
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObject">AWS
* API Documentation</a>
*/
public S3Object getObjectInfo(String bucketName, String objectName) throws Exception {
@Cleanup
S3Object object = amazonS3.getObject(bucketName, objectName);
return object;
}
/**
* 删除文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @throws Exception
* @see <a href=
* "http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/DeleteObject">AWS API
* Documentation</a>
*/
public void removeObject(String bucketName, String objectName) throws Exception {
amazonS3.deleteObject(bucketName, objectName);
}
@Override
public void afterPropertiesSet() {
ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.setMaxConnections(properties.getOss().getMaxConnections());
AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(
properties.getOss().getEndpoint(), properties.getOss().getRegion());
AWSCredentials awsCredentials = new BasicAWSCredentials(properties.getOss().getAccessKey(),
properties.getOss().getSecretKey());
AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
this.amazonS3 = AmazonS3Client.builder()
.withEndpointConfiguration(endpointConfiguration)
.withClientConfiguration(clientConfiguration)
.withCredentials(awsCredentialsProvider)
.disableChunkedEncoding()
.withPathStyleAccessEnabled(properties.getOss().getPathStyleAccess())
.build();
}
}
......@@ -23,7 +23,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-common-seata</artifactId>
......
......@@ -21,7 +21,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-common-security</artifactId>
......
package com.pig4cloud.pig.common.security.component;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.oauth2.core.endpoint.DefaultOAuth2AccessTokenResponseMapConverter;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
import java.util.Map;
/**
* 扩展原生的实现,支持 Long2String
*
* @author lengleng
* @date 2023/6/28
*/
public class PigCustomOAuth2AccessTokenResponseHttpMessageConverter
extends OAuth2AccessTokenResponseHttpMessageConverter {
private static final ParameterizedTypeReference<Map<String, Object>> STRING_OBJECT_MAP = new ParameterizedTypeReference<Map<String, Object>>() {
};
private Converter<OAuth2AccessTokenResponse, Map<String, Object>> accessTokenResponseParametersConverter = new DefaultOAuth2AccessTokenResponseMapConverter();
@Override
protected void writeInternal(OAuth2AccessTokenResponse tokenResponse, HttpOutputMessage outputMessage)
throws HttpMessageNotWritableException {
try {
Map<String, Object> tokenResponseParameters = this.accessTokenResponseParametersConverter
.convert(tokenResponse);
ObjectMapper objectMapper = SpringContextHolder.getBean(ObjectMapper.class);
GenericHttpMessageConverter<Object> jsonMessageConverter = new MappingJackson2HttpMessageConverter(
objectMapper);
jsonMessageConverter.write(tokenResponseParameters, STRING_OBJECT_MAP.getType(), MediaType.APPLICATION_JSON,
outputMessage);
}
catch (Exception ex) {
throw new HttpMessageNotWritableException(
"An error occurred writing the OAuth 2.0 Access Token Response: " + ex.getMessage(), ex);
}
}
}
......@@ -16,19 +16,20 @@
package com.pig4cloud.pig.common.security.component;
import cn.hutool.core.util.StrUtil;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.security.annotation.Inner;
import javax.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.access.AccessDeniedException;
import javax.servlet.http.HttpServletRequest;
/**
* @author lengleng
* @date 2022-06-04
......@@ -43,14 +44,18 @@ public class PigSecurityInnerAspect implements Ordered {
private final HttpServletRequest request;
@SneakyThrows
@Around("@within(inner) || @annotation(inner)")
public Object around(ProceedingJoinPoint point, Inner inner) {
@Before("@within(inner) || @annotation(inner)")
public void around(JoinPoint point, Inner inner) {
// 实际注入的inner实体由表达式后一个注解决定,即是方法上的@Inner注解实体,若方法上无@Inner注解,则获取类上的
if (inner == null) {
Class<?> clazz = point.getTarget().getClass();
inner = AnnotationUtils.findAnnotation(clazz, Inner.class);
}
String header = request.getHeader(SecurityConstants.FROM);
if (inner.value() && !SecurityConstants.FROM_IN.equals(header)) {
if (inner.value() && !StrUtil.equals(SecurityConstants.FROM_IN, header)) {
log.warn("访问接口 {} 没有权限", point.getSignature().getName());
throw new AccessDeniedException("Access is denied");
}
return point.proceed();
}
@Override
......
......@@ -16,6 +16,7 @@
package com.pig4cloud.pig.common.security.service;
import com.pig4cloud.pig.admin.api.dto.UserDTO;
import com.pig4cloud.pig.admin.api.dto.UserInfo;
import com.pig4cloud.pig.admin.api.feign.RemoteUserService;
import com.pig4cloud.pig.common.core.constant.CacheConstants;
......@@ -54,7 +55,9 @@ public class PigAppUserDetailsServiceImpl implements PigUserDetailsService {
return (PigUser) cache.get(phone).get();
}
R<UserInfo> result = remoteUserService.infoByMobile(phone);
UserDTO userDTO = new UserDTO();
userDTO.setPhone(phone);
R<UserInfo> result = remoteUserService.info(userDTO, SecurityConstants.FROM_IN);
UserDetails userDetails = getUserDetails(result);
if (cache != null) {
......@@ -80,7 +83,7 @@ public class PigAppUserDetailsServiceImpl implements PigUserDetailsService {
*/
@Override
public boolean support(String clientId, String grantType) {
return SecurityConstants.APP.equals(grantType);
return SecurityConstants.MOBILE.equals(grantType);
}
}
......@@ -19,7 +19,6 @@ import org.springframework.security.oauth2.server.authorization.client.Registere
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import org.springframework.util.StringUtils;
import java.time.Duration;
import java.util.Arrays;
......@@ -56,7 +55,6 @@ public class PigRemoteRegisteredClientRepository implements RegisteredClientRepo
*/
@Override
public void save(RegisteredClient registeredClient) {
throw new UnsupportedOperationException();
}
/**
......@@ -87,7 +85,8 @@ public class PigRemoteRegisteredClientRepository implements RegisteredClientRepo
@Cacheable(value = CacheConstants.CLIENT_DETAILS_KEY, key = "#clientId", unless = "#result == null")
public RegisteredClient findByClientId(String clientId) {
SysOauthClientDetails clientDetails = RetOps.of(clientDetailsService.getClientDetailsById(clientId))
SysOauthClientDetails clientDetails = RetOps
.of(clientDetailsService.getClientDetailsById(clientId, SecurityConstants.FROM_IN))
.getData()
.orElseThrow(() -> new OAuth2AuthorizationCodeRequestAuthenticationException(
new OAuth2Error("客户端查询异常,请检查数据库链接"), null));
......@@ -95,16 +94,12 @@ public class PigRemoteRegisteredClientRepository implements RegisteredClientRepo
RegisteredClient.Builder builder = RegisteredClient.withId(clientDetails.getClientId())
.clientId(clientDetails.getClientId())
.clientSecret(SecurityConstants.NOOP + clientDetails.getClientSecret())
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
.clientAuthenticationMethods(clientAuthenticationMethods -> {
clientAuthenticationMethods.add(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
clientAuthenticationMethods.add(ClientAuthenticationMethod.CLIENT_SECRET_POST);
});
// 授权模式
Optional.ofNullable(clientDetails.getAuthorizedGrantTypes())
.ifPresent(grants -> StringUtils.commaDelimitedListToSet(grants)
.forEach(s -> builder.authorizationGrantType(new AuthorizationGrantType(s))));
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
for (String authorizedGrantType : clientDetails.getAuthorizedGrantTypes()) {
builder.authorizationGrantType(new AuthorizationGrantType(authorizedGrantType));
}
// 回调地址
Optional.ofNullable(clientDetails.getWebServerRedirectUri())
.ifPresent(redirectUri -> Arrays.stream(redirectUri.split(StrUtil.COMMA))
......
......@@ -16,9 +16,11 @@
package com.pig4cloud.pig.common.security.service;
import com.pig4cloud.pig.admin.api.dto.UserDTO;
import com.pig4cloud.pig.admin.api.dto.UserInfo;
import com.pig4cloud.pig.admin.api.feign.RemoteUserService;
import com.pig4cloud.pig.common.core.constant.CacheConstants;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.util.R;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
......@@ -55,7 +57,9 @@ public class PigUserDetailsServiceImpl implements PigUserDetailsService {
return (PigUser) cache.get(username).get();
}
R<UserInfo> result = remoteUserService.info(username);
UserDTO userDTO = new UserDTO();
userDTO.setUsername(username);
R<UserInfo> result = remoteUserService.info(userDTO, SecurityConstants.FROM_IN);
UserDetails userDetails = getUserDetails(result);
if (cache != null) {
cache.put(username, userDetails);
......
......@@ -24,7 +24,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-common-swagger</artifactId>
......
......@@ -25,6 +25,7 @@ import io.swagger.v3.oas.models.security.Scopes;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.SpringDocUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.ServiceInstance;
......@@ -66,6 +67,9 @@ public class SwaggerAutoConfiguration {
String path = swaggerProperties.getServices().get(serviceInstance.getServiceId());
serverList.add(new Server().url(swaggerProperties.getGateway() + "/" + path));
openAPI.servers(serverList);
// 支持参数平铺
SpringDocUtils.getConfig().addSimpleTypesForParameterObject(Class.class);
return openAPI;
}
......
......@@ -6,7 +6,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-common-xss</artifactId>
......
......@@ -21,7 +21,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-common</artifactId>
......@@ -36,6 +36,7 @@
<module>pig-common-job</module>
<module>pig-common-log</module>
<module>pig-common-mybatis</module>
<module>pig-common-oss</module>
<module>pig-common-seata</module>
<module>pig-common-security</module>
<module>pig-common-feign</module>
......
......@@ -21,7 +21,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-gateway</artifactId>
......
......@@ -21,11 +21,11 @@ import java.util.Map;
* swagger 3.0 展示
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "springdoc.api-docs.enabled", matchIfMissing = true)
public class SpringDocConfiguration {
@Bean
@Lazy(false)
@ConditionalOnProperty(name = "springdoc.api-docs.enabled", matchIfMissing = true)
public List<GroupedOpenApi> apis(SwaggerUiConfigParameters swaggerUiConfigParameters,
SwaggerDocProperties swaggerProperties) {
List<GroupedOpenApi> groups = new ArrayList<>();
......
文件模式从 100755 更改为 100644
......@@ -12,101 +12,102 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>pig</artifactId>
<version>3.6.7</version>
</parent>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>pig</artifactId>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-register</artifactId>
<packaging>jar</packaging>
<name>pig-register</name>
<description>nacos 注册配置中心</description>
<artifactId>pig-register</artifactId>
<packaging>jar</packaging>
<name>pig-register</name>
<description>nacos 注册配置中心</description>
<properties>
<nacos.version>2.2.3</nacos.version>
</properties>
<properties>
<nacos.version>2.2.4</nacos.version>
</properties>
<dependencies>
<dependency>
<groupId>io.springboot.nacos</groupId>
<artifactId>nacos-config</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependencies>
<dependency>
<groupId>io.springboot.nacos</groupId>
<artifactId>nacos-config</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>io.springboot.nacos</groupId>
<artifactId>nacos-naming</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>io.springboot.nacos</groupId>
<artifactId>nacos-naming</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>io.springboot.nacos</groupId>
<artifactId>nacos-istio</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>io.springboot.nacos</groupId>
<artifactId>nacos-istio</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>io.springboot.nacos</groupId>
<artifactId>nacos-plugin-default-impl</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>io.springboot.nacos</groupId>
<artifactId>nacos-plugin-default-impl</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>io.springboot.nacos</groupId>
<artifactId>nacos-prometheus</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>io.springboot.nacos</groupId>
<artifactId>nacos-prometheus</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-system</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.woff</exclude>
<exclude>**/*.woff2</exclude>
<exclude>**/*.ttf</exclude>
<exclude>**/*.eot</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>**/*.woff</include>
<include>**/*.woff2</include>
<include>**/*.ttf</include>
<include>**/*.eot</include>
</includes>
</resource>
</resources>
</build>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-system</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.woff</exclude>
<exclude>**/*.woff2</exclude>
<exclude>**/*.ttf</exclude>
<exclude>**/*.eot</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>**/*.woff</include>
<include>**/*.woff2</include>
<include>**/*.ttf</include>
<include>**/*.eot</include>
</includes>
</resource>
</resources>
</build>
</project>
......@@ -46,6 +46,7 @@ public class PigNacosApplication {
System.setProperty(ConfigConstants.AUTH_ENABLED, "true");
System.setProperty(ConfigConstants.LOG_BASEDIR, "logs");
System.setProperty(ConfigConstants.LOG_ENABLED, "false");
System.setProperty(ConfigConstants.NACOS_CONTEXT_PATH, "/nacos");
return true;
}
......
......@@ -45,4 +45,9 @@ public interface ConfigConstants {
*/
String LOG_ENABLED = "server.tomcat.accesslog.enabled";
/**
* 路径 nacos context path
*/
String NACOS_CONTEXT_PATH = "server.servlet.contextPath";
}
......@@ -16,7 +16,6 @@
package com.alibaba.nacos.config;
import com.alibaba.nacos.console.filter.XssFilter;
import com.alibaba.nacos.core.code.ControllerMethodsCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
......@@ -65,17 +64,11 @@ public class ConsoleConfig {
config.addAllowedHeader("*");
config.setMaxAge(18000L);
config.addAllowedMethod("*");
config.addAllowedOriginPattern("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
@Bean
public XssFilter xssFilter() {
return new XssFilter();
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(ZoneId.systemDefault().toString());
......
......@@ -16,18 +16,19 @@
package com.alibaba.nacos.console.controller;
import cn.hutool.core.io.FileUtil;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.model.RestResultUtils;
import com.alibaba.nacos.sys.env.EnvUtil;
import com.alibaba.nacos.sys.module.ModuleState;
import com.alibaba.nacos.sys.module.ModuleStateHolder;
import com.alibaba.nacos.sys.utils.DiskUtils;
import lombok.SneakyThrows;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
......@@ -40,7 +41,7 @@ import java.util.Map;
@RequestMapping("/v1/console/server")
public class ServerStateController {
private static final String ANNOUNCEMENT_FILE = "announcement.conf";
private static final String ANNOUNCEMENT_FILE = "conf/announcement.conf";
/**
* Get server state of current server.
......@@ -55,14 +56,11 @@ public class ServerStateController {
return ResponseEntity.ok().body(serverState);
}
@SneakyThrows
@GetMapping("/announcement")
public RestResult<String> getAnnouncement() {
File announcementFile = new File(EnvUtil.getConfPath(), ANNOUNCEMENT_FILE);
String announcement = null;
if (announcementFile.exists() && announcementFile.isFile()) {
announcement = DiskUtils.readFile(announcementFile);
}
return RestResultUtils.success(announcement);
ClassPathResource resource = new ClassPathResource(ANNOUNCEMENT_FILE);
return RestResultUtils.success(FileUtil.readString(resource.getFile(), Charset.defaultCharset()));
}
}
#
# Copyright 1999-2018 Alibaba Group Holding Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Console Default Properties
spring.mvc.view.prefix=/jsp/
# the default suffix of page
spring.mvc.view.suffix=.jsp
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
#logging.level.root=DEBUG
# P0 key,For Debug. whether use address-server; true:use; false:not use;default:true
useAddressServer=true
# whether open interInterFaceFilter; true:open; false:close; if open, others can't call inner interface. default:false
openInnerInterfaceFilter=false
# quickStart stip dumpAll;only dump change config
isQuickStart=false
# server notify each otherd
notifyConnectTimeout=200
# server notify each other
notifySocketTimeout=8000
# whether health check
isHealthCheck=true
# health check max fail count
maxHealthCheckFailCount=12
# whether open spas; true:open; false:close
OPEN_SPAS=true
nacos.cmdb.dumpTaskInterval=3600
nacos.cmdb.eventTaskInterval=10
nacos.cmdb.labelTaskInterval=300
nacos.cmdb.loadDataAtStart=false
#management.endpoints.web.exposure.include=*
#spring.security.enabled=false
#management.security=false
#security.basic.enabled=false
#nacos.security.ignore.urls=/**
nacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/login,/v1/console/health,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**
management.metrics.export.elastic.enabled=false
#management.metrics.export.elastic.host=http://localhost:9200
# metrics for influx
management.metrics.export.influx.enabled=false
#management.metrics.export.influx.db=springboot
#management.metrics.export.influx.uri=http://localhost:8086
#management.metrics.export.influx.auto-create-db=true
#management.metrics.export.influx.consistency=one
#management.metrics.export.influx.compressed=true
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D
# default current work dir
server.tomcat.basedir=
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
CREATE SCHEMA nacos AUTHORIZATION nacos;
CREATE TABLE config_info (
id bigint NOT NULL generated by default as identity,
data_id varchar(255) NOT NULL,
group_id varchar(128) NOT NULL,
tenant_id varchar(128) default '',
app_name varchar(128),
content CLOB,
md5 varchar(32) DEFAULT NULL,
gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00',
gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00',
src_user varchar(128) DEFAULT NULL,
src_ip varchar(20) DEFAULT NULL,
c_desc varchar(256) DEFAULT NULL,
c_use varchar(64) DEFAULT NULL,
effect varchar(64) DEFAULT NULL,
type varchar(64) DEFAULT NULL,
c_schema LONG VARCHAR DEFAULT NULL,
encrypted_data_key LONG VARCHAR DEFAULT NULL,
constraint configinfo_id_key PRIMARY KEY (id),
constraint uk_configinfo_datagrouptenant UNIQUE (data_id,group_id,tenant_id));
CREATE INDEX configinfo_dataid_key_idx ON config_info(data_id);
CREATE INDEX configinfo_groupid_key_idx ON config_info(group_id);
CREATE INDEX configinfo_dataid_group_key_idx ON config_info(data_id, group_id);
CREATE TABLE his_config_info (
id bigint NOT NULL,
nid bigint NOT NULL generated by default as identity,
data_id varchar(255) NOT NULL,
group_id varchar(128) NOT NULL,
tenant_id varchar(128) default '',
app_name varchar(128),
content CLOB,
md5 varchar(32) DEFAULT NULL,
gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000',
gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000',
src_user varchar(128),
src_ip varchar(20) DEFAULT NULL,
op_type char(10) DEFAULT NULL,
encrypted_data_key LONG VARCHAR DEFAULT NULL,
constraint hisconfiginfo_nid_key PRIMARY KEY (nid));
CREATE INDEX hisconfiginfo_dataid_key_idx ON his_config_info(data_id);
CREATE INDEX hisconfiginfo_gmt_create_idx ON his_config_info(gmt_create);
CREATE INDEX hisconfiginfo_gmt_modified_idx ON his_config_info(gmt_modified);
CREATE TABLE config_info_beta (
id bigint NOT NULL generated by default as identity,
data_id varchar(255) NOT NULL,
group_id varchar(128) NOT NULL,
tenant_id varchar(128) default '',
app_name varchar(128),
content CLOB,
beta_ips varchar(1024),
md5 varchar(32) DEFAULT NULL,
gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00',
gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00',
src_user varchar(128),
src_ip varchar(20) DEFAULT NULL,
encrypted_data_key LONG VARCHAR DEFAULT NULL,
constraint configinfobeta_id_key PRIMARY KEY (id),
constraint uk_configinfobeta_datagrouptenant UNIQUE (data_id,group_id,tenant_id));
CREATE TABLE config_info_tag (
id bigint NOT NULL generated by default as identity,
data_id varchar(255) NOT NULL,
group_id varchar(128) NOT NULL,
tenant_id varchar(128) default '',
tag_id varchar(128) NOT NULL,
app_name varchar(128),
content CLOB,
md5 varchar(32) DEFAULT NULL,
gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00',
gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00',
src_user varchar(128),
src_ip varchar(20) DEFAULT NULL,
constraint configinfotag_id_key PRIMARY KEY (id),
constraint uk_configinfotag_datagrouptenanttag UNIQUE (data_id,group_id,tenant_id,tag_id));
CREATE TABLE config_info_aggr (
id bigint NOT NULL generated by default as identity,
data_id varchar(255) NOT NULL,
group_id varchar(128) NOT NULL,
tenant_id varchar(128) default '',
datum_id varchar(255) NOT NULL,
app_name varchar(128),
content CLOB,
gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00',
constraint configinfoaggr_id_key PRIMARY KEY (id),
constraint uk_configinfoaggr_datagrouptenantdatum UNIQUE (data_id,group_id,tenant_id,datum_id));
CREATE TABLE app_list (
id bigint NOT NULL generated by default as identity,
app_name varchar(128) NOT NULL,
is_dynamic_collect_disabled smallint DEFAULT 0,
last_sub_info_collected_time timestamp DEFAULT '1970-01-01 08:00:00.0',
sub_info_lock_owner varchar(128),
sub_info_lock_time timestamp DEFAULT '1970-01-01 08:00:00.0',
constraint applist_id_key PRIMARY KEY (id),
constraint uk_appname UNIQUE (app_name));
CREATE TABLE app_configdata_relation_subs (
id bigint NOT NULL generated by default as identity,
app_name varchar(128) NOT NULL,
data_id varchar(255) NOT NULL,
group_id varchar(128) NOT NULL,
gmt_modified timestamp DEFAULT '2010-05-05 00:00:00',
constraint configdatarelationsubs_id_key PRIMARY KEY (id),
constraint uk_app_sub_config_datagroup UNIQUE (app_name, data_id, group_id));
CREATE TABLE app_configdata_relation_pubs (
id bigint NOT NULL generated by default as identity,
app_name varchar(128) NOT NULL,
data_id varchar(255) NOT NULL,
group_id varchar(128) NOT NULL,
gmt_modified timestamp DEFAULT '2010-05-05 00:00:00',
constraint configdatarelationpubs_id_key PRIMARY KEY (id),
constraint uk_app_pub_config_datagroup UNIQUE (app_name, data_id, group_id));
CREATE TABLE config_tags_relation (
id bigint NOT NULL,
tag_name varchar(128) NOT NULL,
tag_type varchar(64) DEFAULT NULL,
data_id varchar(255) NOT NULL,
group_id varchar(128) NOT NULL,
tenant_id varchar(128) DEFAULT '',
nid bigint NOT NULL generated by default as identity,
constraint config_tags_id_key PRIMARY KEY (nid),
constraint uk_configtagrelation_configidtag UNIQUE (id, tag_name, tag_type));
CREATE INDEX config_tags_tenant_id_idx ON config_tags_relation(tenant_id);
CREATE TABLE group_capacity (
id bigint NOT NULL generated by default as identity,
group_id varchar(128) DEFAULT '',
quota int DEFAULT 0,
usage int DEFAULT 0,
max_size int DEFAULT 0,
max_aggr_count int DEFAULT 0,
max_aggr_size int DEFAULT 0,
max_history_count int DEFAULT 0,
gmt_create timestamp DEFAULT '2010-05-05 00:00:00',
gmt_modified timestamp DEFAULT '2010-05-05 00:00:00',
constraint group_capacity_id_key PRIMARY KEY (id),
constraint uk_group_id UNIQUE (group_id));
CREATE TABLE tenant_capacity (
id bigint NOT NULL generated by default as identity,
tenant_id varchar(128) DEFAULT '',
quota int DEFAULT 0,
usage int DEFAULT 0,
max_size int DEFAULT 0,
max_aggr_count int DEFAULT 0,
max_aggr_size int DEFAULT 0,
max_history_count int DEFAULT 0,
gmt_create timestamp DEFAULT '2010-05-05 00:00:00',
gmt_modified timestamp DEFAULT '2010-05-05 00:00:00',
constraint tenant_capacity_id_key PRIMARY KEY (id),
constraint uk_tenant_id UNIQUE (tenant_id));
CREATE TABLE tenant_info (
id bigint NOT NULL generated by default as identity,
kp varchar(128) NOT NULL,
tenant_id varchar(128) DEFAULT '',
tenant_name varchar(128) DEFAULT '',
tenant_desc varchar(256) DEFAULT NULL,
create_source varchar(32) DEFAULT NULL,
gmt_create bigint NOT NULL,
gmt_modified bigint NOT NULL,
constraint tenant_info_id_key PRIMARY KEY (id),
constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id));
CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id);
CREATE TABLE users (
username varchar(50) NOT NULL PRIMARY KEY,
password varchar(500) NOT NULL,
enabled boolean NOT NULL DEFAULT true
);
CREATE TABLE roles (
username varchar(50) NOT NULL,
role varchar(50) NOT NULL,
constraint uk_username_role UNIQUE (username,role)
);
CREATE TABLE permissions (
role varchar(50) NOT NULL,
resource varchar(512) NOT NULL,
action varchar(8) NOT NULL,
constraint uk_role_permission UNIQUE (role,resource,action)
);
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
......@@ -2,8 +2,8 @@ server:
port: 8848 #如何修改 pig-register 启动端口 >: https://t.cn/A6XGvTdb
tomcat:
basedir: logs
error:
include-message: always
servlet:
context-path: /nacos
db:
num: 1
......@@ -11,7 +11,7 @@ db:
password: ${MYSQL_PWD:root}
url:
0: jdbc:mysql://${MYSQL_HOST:pig-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pig_config}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
pool.config.connectionTimeout: 30000
nacos:
core:
......@@ -21,10 +21,11 @@ nacos:
key: serverIdentity
value: security
plugin.nacos.token.secret.key: SecretKey012345678901234567890123456789012345678901234567890123456789
enabled: false
system.type: nacos
security:
ignore:
urls: /actuator/**,/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
urls: /,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
spring:
datasource:
......
无论您是多年编程的高级工程师,还是刚刚入门的实习生,部署请完全参考<a href="https://sourl.cn/WaiyBH">微服务开发平台部署手册</a>操作。
......@@ -21,7 +21,7 @@
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-upms</artifactId>
<version>3.6.7</version>
<version>3.7.0-JDK8</version>
</parent>
<artifactId>pig-upms-api</artifactId>
......@@ -36,15 +36,10 @@
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-core</artifactId>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<!--feign 注解依赖-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-feign</artifactId>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
<optional>true</optional>
</dependency>
<!--mybatis 依赖-->
......
package com.pig4cloud.pig.admin.api.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 客户端请求验证码
*
* @author lengleng
* @date 2022/10/13
*/
@Data
public class AppSmsDTO {
/**
* 手机号
*/
@NotBlank(message = "手机号不能为空")
private String phone;
/**
* 手机号是否存在数据库
*/
private Boolean exist;
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。