init
This commit is contained in:
commit
583ca60498
|
@ -0,0 +1,21 @@
|
|||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
# 空格替代Tab缩进在各种编辑工具下效果一致
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
charset = utf-8
|
||||
end_of_line = crlf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.java]
|
||||
indent_style = tab
|
||||
|
||||
[*.{json,yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = false
|
|
@ -0,0 +1,27 @@
|
|||
# maven #
|
||||
target
|
||||
|
||||
logs
|
||||
|
||||
# windows #
|
||||
Thumbs.db
|
||||
|
||||
# Mac #
|
||||
.DS_Store
|
||||
|
||||
# eclipse #
|
||||
.settings
|
||||
.project
|
||||
.classpath
|
||||
.log
|
||||
*.class
|
||||
|
||||
# idea #
|
||||
.idea
|
||||
*.iml
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
/target
|
Binary file not shown.
|
@ -0,0 +1,119 @@
|
|||
#spring配置
|
||||
spring:
|
||||
redis:
|
||||
##redis 单机环境配置
|
||||
host: http://127.0.0.1/
|
||||
port: 6379
|
||||
timeout: 10000
|
||||
password: P@ssw0rd_redis
|
||||
database: 0
|
||||
ssl: false
|
||||
##redis 集群环境配置
|
||||
#cluster:
|
||||
# nodes: 47.108.70.243:7001,47.108.70.243:7002,47.108.70.243:7003
|
||||
# commandTimeout: 5000
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
druid:
|
||||
validation-query: select 1
|
||||
url: jdbc:mysql://36.147.33.60:13306/security?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: P@ssw0rd_mysql
|
||||
|
||||
#项目模块集中配置
|
||||
blade:
|
||||
esbUrl: 197.52.19.89
|
||||
esbPort: 39245
|
||||
#分布式锁配置
|
||||
lock:
|
||||
enabled: false
|
||||
address: redis://47.108.70.243:6379
|
||||
#多团队协作服务配置
|
||||
ribbon:
|
||||
rule:
|
||||
#开启配置
|
||||
enabled: false
|
||||
#负载均衡优先调用的ip段
|
||||
prior-ip-pattern:
|
||||
- 192.168.0.*
|
||||
- 47.108.70.243
|
||||
#通用开发生产环境数据库地址(特殊情况可在对应的子工程里配置覆盖)
|
||||
datasource:
|
||||
dev:
|
||||
url: jdbc:mysql://36.147.33.60:13306/security?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: P@ssw0rd_mysql
|
||||
|
||||
#
|
||||
# Emb(消息总线请求参数)配置 -sit
|
||||
sub:
|
||||
brokerServiceurl: pulsar://198.69.20.7:6000
|
||||
accessToken: eyJrZXlJZCI6InB1bHNhci13ejlwMmptYnBuIiwiYWxnIjoiSFMyNTYifQ.eyJzdWIiOiJwdWxzYXItd3o5cDJqbWJwbl9TSU1TIn0.ibMqmjqOJkNMWsxBJj-zLbGsG3VY5gX74G3MTIkMIHQ
|
||||
subscriptionName: SIMS
|
||||
corePoolSize: 1
|
||||
evnValue: pulsar-wz9p2jmbpn
|
||||
listenerName: pulsar-wz9p2jmbpn/vpc-espi8lwv/subnet-6o1k8cm0
|
||||
topicNames:
|
||||
- pulsar-wz9p2jmbpn/sso-common-info/M01010001
|
||||
- pulsar-wz9p2jmbpn/sso-common-info/M01010002
|
||||
- pulsar-wz9p2jmbpn/sso-common-info/M01030006
|
||||
maximumPoolSize: 300
|
||||
deptLeaderName: 机构负责人 #行政机构信息同步的机构负责人对应的角色名称
|
||||
|
||||
#security-desk-yml配置文件
|
||||
#影像平台
|
||||
images:
|
||||
local_path: E:\安防信息化项目\uploadFile\ #本地存放文件路径
|
||||
service_path: /home/test/apps/file/ # 服务器存放文件路径
|
||||
DM: HTBANK
|
||||
ip: 197.52.21.92 #为影像平台的ip地址
|
||||
socketPort: 8023 #为影像平台的socket端口
|
||||
httpPort: 9080 #为影像平台的http端口
|
||||
aimChannel: SIMS #渠道号
|
||||
modelCode: SIMS #索引对象内容模型代码
|
||||
filePartName: SIMS_PART #文档对象模型代码
|
||||
userName: sims #登录影像平台的用户名
|
||||
passWord: sims_admin #登录影像平台的密码
|
||||
|
||||
xyun:
|
||||
app-id: 500000053
|
||||
app-secret: B6rbJdILa1VEO9fmn6zj
|
||||
url: http://197.52.23.10
|
||||
# 公共号id
|
||||
pub-id: XT-cb5053a4-3d00-47e7-a0c3-d0ac693305b7
|
||||
pub-secret: 812739e21bf781370bebec37146c38a8
|
||||
# 企业注册号eid
|
||||
e-id: 1556583279
|
||||
|
||||
|
||||
# 单点登录配置参数
|
||||
single:
|
||||
auth-url: http://bam.sit.ynhtbank.com:9080/idp/oauth2/authorize #单点登录url
|
||||
client-id: SIMS #应用系统ID
|
||||
redirect-uri: http://197.52.29.131:8888/api/security-desk/authorize #重定向url
|
||||
response-type: code #响应类型
|
||||
client-secret: 3ac76afc760f4c8b9265992e28c924df
|
||||
auth-res-url: http://197.52.19.89:39245/SIMS #单点登录授权url
|
||||
index-url: http://197.52.29.131:8888/#/single-login #首页地址
|
||||
scvcd: 30430034 #上esb获取用户信息的服务码
|
||||
user-url: http://197.52.29.131:8000/security-auth/oauth/token
|
||||
chnl-tp: 41022
|
||||
|
||||
|
||||
#secutity-yml配置文件
|
||||
#导出文件的存储路径
|
||||
export:
|
||||
excel:
|
||||
path: D:\安全管理信息化平台\excel导出测试\
|
||||
|
||||
#swagger包扫描路径
|
||||
swagger:
|
||||
base-packages: org.security.trans
|
||||
|
||||
#通用配置参数
|
||||
common:
|
||||
projectRoleName: 安全员 #项目预算管理-项目结项后可以对结项项目进行操作的指属上一级机构的角色名称
|
||||
securityRoleName: 安全员 #安保指挥中心非现场检查整改通知书通知机构的角色
|
||||
payPlanRemindKeyName: payPlanRemindDay #付款计划提醒提前天数字典配置键值
|
||||
concatDeadlineRemindKeyName: concatDeadlineRemindDay #合同到期提醒提前天数字典配置键值
|
||||
service_path: /home/test/apps/file/ # 服务器存放文件路径-用于附件删除
|
|
@ -0,0 +1,39 @@
|
|||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
#driver-class-name: org.postgresql.Driver
|
||||
#driver-class-name: oracle.jdbc.OracleDriver
|
||||
#driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
druid:
|
||||
# MySql、PostgreSQL、SqlServer校验
|
||||
#validation-query: select 1
|
||||
# Oracle校验
|
||||
#validation-query: select 1 from dual
|
||||
|
||||
#项目模块集中配置
|
||||
blade:
|
||||
#工作流模块开发生产环境数据库地址
|
||||
datasource:
|
||||
flow:
|
||||
dev:
|
||||
# MySql
|
||||
url: jdbc:mysql://36.147.33.60:13306/security?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: P@ssw0rd_mysql
|
||||
# PostgreSQL
|
||||
#url: jdbc:postgresql://127.0.0.1:5432/bladex_flow
|
||||
#username: postgres
|
||||
#password: 123456
|
||||
# Oracle
|
||||
#url: jdbc:oracle:thin:@127.0.0.1:1521:orcl
|
||||
#username: BLADEX_FLOW
|
||||
#password: BLADEX_FLOW
|
||||
# SqlServer
|
||||
#url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=bladex_flow
|
||||
#username: bladex_flow
|
||||
#password: bladex_flow
|
||||
#准生产
|
||||
# dev:
|
||||
# url: jdbc:oceanbase://oceanbase.qprod.htb.srv:2883/siszsc?useUnicode=true&characterEncoding=utf-8&mode=mysql&rewriteBatchedStatements=true&socketTimeout=6000000&connectTimeout=60000&allowMultiQueries=true&useLocalSessionState=true
|
||||
# username: htb_prod_obcluster:siszsc:secretiy
|
||||
# password: SIS_pswd@123
|
|
@ -0,0 +1,111 @@
|
|||
#服务器配置
|
||||
server:
|
||||
undertow:
|
||||
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
|
||||
buffer-size: 1024
|
||||
# 是否分配的直接内存
|
||||
direct-buffers: true
|
||||
# 线程配置
|
||||
threads:
|
||||
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
|
||||
io: 16
|
||||
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
|
||||
worker: 400
|
||||
|
||||
#spring配置
|
||||
spring:
|
||||
cloud:
|
||||
sentinel:
|
||||
eager: true
|
||||
devtools:
|
||||
restart:
|
||||
log-condition-evaluation-delta: false
|
||||
livereload:
|
||||
port: 23333
|
||||
servlet:
|
||||
multipart:
|
||||
location: /home/test/apps/undertow/tmp
|
||||
|
||||
#feign配置
|
||||
feign:
|
||||
sentinel:
|
||||
enabled: true
|
||||
okhttp:
|
||||
enabled: true
|
||||
httpclient:
|
||||
enabled: true
|
||||
hystrix:
|
||||
enable: true
|
||||
client:
|
||||
config:
|
||||
default:
|
||||
readTimeout: 120000
|
||||
connectTimeout: 3000
|
||||
|
||||
|
||||
#对外暴露端口
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: "*"
|
||||
endpoint:
|
||||
health:
|
||||
show-details: always
|
||||
|
||||
#knife4j配置
|
||||
knife4j:
|
||||
#启用
|
||||
enable: true
|
||||
#基础认证
|
||||
basic:
|
||||
enable: false
|
||||
username: blade
|
||||
password: blade
|
||||
#增强配置
|
||||
setting:
|
||||
enableSwaggerModels: true
|
||||
enableDocumentManage: true
|
||||
enableHost: false
|
||||
enableHostText: http://localhost
|
||||
enableRequestCache: true
|
||||
enableFilterMultipartApis: false
|
||||
enableFilterMultipartApiMethodType: POST
|
||||
language: zh-CN
|
||||
enableFooter: false
|
||||
enableFooterCustom: true
|
||||
footerCustomContent: Copyright © 2021 SpringBlade All Rights Reserved
|
||||
|
||||
#swagger配置信息
|
||||
swagger:
|
||||
title: SpringBlade 接口文档系统
|
||||
description: SpringBlade 接口文档系统
|
||||
version: 3.0.3
|
||||
license: Powered By SpringBlade
|
||||
licenseUrl: https://bladex.vip
|
||||
terms-of-service-url: https://bladex.vip
|
||||
contact:
|
||||
name: smallchill
|
||||
email: smallchill@163.com
|
||||
url: https://gitee.com/smallc
|
||||
|
||||
#blade配置
|
||||
blade:
|
||||
xss:
|
||||
enabled: true
|
||||
skip-url:
|
||||
- /weixin
|
||||
secure:
|
||||
skip-url:
|
||||
- /test/**
|
||||
client:
|
||||
- client-id: sword
|
||||
path-patterns:
|
||||
- /sword/**
|
||||
- client-id: saber
|
||||
path-patterns:
|
||||
- /saber/**
|
||||
tenant:
|
||||
column: tenant_id
|
||||
tables:
|
||||
- blade_notice
|
|
@ -0,0 +1,125 @@
|
|||
#spring配置
|
||||
spring:
|
||||
redis:
|
||||
##redis 单机环境配置
|
||||
host: 197.32.39.34
|
||||
port: 16379
|
||||
timeout: 10000
|
||||
password:
|
||||
database: 0
|
||||
ssl: false
|
||||
##redis 集群环境配置
|
||||
#cluster:
|
||||
# nodes: 47.108.70.243:7001,47.108.70.243:7002,47.108.70.243:7003
|
||||
# commandTimeout: 5000
|
||||
datasource:
|
||||
driver-class-name: com.alipay.oceanbase.jdbc.Driver
|
||||
druid:
|
||||
validation-query: select 1
|
||||
url: jdbc:oceanbase://obap.htb.srv:2883/sis?useUnicode=true&characterEncoding=utf-8&mode=mysql&rewriteBatchedStatements=true&socketTimeout=6000000&connectTimeout=60000&allowMultiQueries=true&useLocalSessionState=true
|
||||
username: htb_ap_obcluster:sis:secretiy
|
||||
password: SECRETIY_P@ssw0rd@123
|
||||
|
||||
#项目模块集中配置
|
||||
blade:
|
||||
esbUrl: esb.htb.srv
|
||||
esbPort: 39245
|
||||
face:
|
||||
virtualTelNo: C00074
|
||||
leadDeptNo: 12023
|
||||
telIdentTp: HTBK
|
||||
#分布式锁配置
|
||||
lock:
|
||||
enabled: false
|
||||
address: redis://197.32.39.34:6379
|
||||
#多团队协作服务配置
|
||||
ribbon:
|
||||
rule:
|
||||
#开启配置
|
||||
enabled: true
|
||||
#负载均衡优先调用的ip段
|
||||
prior-ip-pattern:
|
||||
- 192.168.0.*
|
||||
- 197.32.39.34
|
||||
#通用开发生产环境数据库地址(特殊情况可在对应的子工程里配置覆盖)
|
||||
datasource:
|
||||
prod:
|
||||
url: jdbc:oceanbase://obap.htb.srv:2883/sis?useUnicode=true&characterEncoding=utf-8&mode=mysql&rewriteBatchedStatements=true&socketTimeout=6000000&connectTimeout=60000&allowMultiQueries=true&useLocalSessionState=true
|
||||
username: htb_ap_obcluster:sis:secretiy
|
||||
password: SECRETIY_P@ssw0rd@123
|
||||
|
||||
#security-busi-yml配置
|
||||
#通用配置参数
|
||||
common:
|
||||
projectRoleName: 安全员 #项目预算管理-项目结项后可以对结项项目进行操作的指属上一级机构的角色名称
|
||||
securityRoleName: 安全员 #安保指挥中心非现场检查整改通知书通知机构的角色
|
||||
payPlanRemindKeyName: payPlanRemindDay #付款计划提醒提前天数字典配置键值
|
||||
concatDeadlineRemindKeyName: concatDeadlineRemindDay #合同到期提醒提前天数字典配置键值
|
||||
service_path: /home/sis/apps/file/ # 服务器存放文件路径
|
||||
|
||||
#导出文件的存储路径
|
||||
export:
|
||||
excel:
|
||||
path: D:\云南红塔银行安保项目\excel导出测试\
|
||||
|
||||
appOauth:
|
||||
accessTokenUrl: http://197.52.23.10/gateway/oauth2/token/getAccessToken
|
||||
userContextUrl: http:/197.52.23.10/gateway/ticket/user/acquirecontext
|
||||
appIndexUrl: http://197.52.29.131:8889/index.html
|
||||
appId: SP1556583279
|
||||
secret: 111
|
||||
|
||||
#security-desk-yml配置信息
|
||||
# Emb(消息总线请求参数)配置 -sit
|
||||
sub:
|
||||
brokerServiceurl: pulsar://198.52.11.2:6000
|
||||
accessToken: eyJrZXlJZCI6InB1bHNhci1yd21hNW84dzVxIiwiYWxnIjoiSFMyNTYifQ.eyJzdWIiOiJwdWxzYXItcndtYTVvOHc1cV9TSU1TIn0.-0N6b4ebRDjsU7eVVbxXg6ft4ZeA_asrxR30zMDAyhc
|
||||
subscriptionName: SIMS
|
||||
corePoolSize: 1
|
||||
evnValue: pulsar-rwma5o8w5q
|
||||
listenerName: pulsar-rwma5o8w5q/vpc-8yjhs80x/subnet-druh4gye
|
||||
topicNames:
|
||||
- pulsar-rwma5o8w5q/sso-common-info/M01010001
|
||||
- pulsar-rwma5o8w5q/sso-common-info/M01010002
|
||||
- pulsar-rwma5o8w5q/sso-common-info/M01030006
|
||||
maximumPoolSize: 300
|
||||
deptLeaderName: 机构负责人 #行政机构信息同步的机构负责人对应的角色名称
|
||||
|
||||
|
||||
#影像平台
|
||||
images:
|
||||
# local_path: E:\安防信息化项目\uploadFile\ #本地存放文件路径
|
||||
service_path: /home/sis/apps/file/ # 服务器存放文件路径
|
||||
DM: HTBANK
|
||||
ip: nicmp.htb.srv #准生产影像平台的ip地址
|
||||
socketPort: 8023 #为影像平台的socket端口
|
||||
httpPort: 9080 #为影像平台的http端口
|
||||
aimChannel: SIMS #渠道号
|
||||
modelCode: SIMS #索引对象内容模型代码
|
||||
filePartName: SIMS_PART #文档对象模型代码
|
||||
userName: sims #登录影像平台的用户名
|
||||
passWord: F8upgG29 #登录影像平台的密码
|
||||
|
||||
xyun:
|
||||
app-id: 500000145
|
||||
app-secret: pzWlUBKsGQZFgIRWwDvV
|
||||
url: http://im.ynhtbank.cn
|
||||
# 公共号id
|
||||
pub-id: XT-d5a6d607-3549-465a-8477-601fc366039d
|
||||
pub-secret: 7e37f7ef5653889013060bfaaa69ccf7
|
||||
# 企业注册号eid
|
||||
e-id: 15750331
|
||||
|
||||
|
||||
# 单点登录配置参数
|
||||
single:
|
||||
auth-url: http://bamsso.htb.com:9080/idp/oauth2/authorize #单点登录url
|
||||
client-id: SIMS #应用系统ID
|
||||
redirect-uri: http://197.32.39.34:8888/api/security-desk/authorize #重定向url
|
||||
response-type: code #响应类型
|
||||
client-secret: 2c461fb0cb43442d8a82436ffd83f3cb
|
||||
auth-res-url: esb.htb.srv:39245/SIMS #单点登录授权url
|
||||
index-url: http://197.32.39.34:8888/#/single-login #首页地址
|
||||
scvcd: 30430034 #上esb获取用户信息的服务码
|
||||
user-url: http://197.32.39.34:8000/security-auth/oauth/token #应用系统获取token地址
|
||||
chnl-tp: 41022
|
|
@ -0,0 +1,111 @@
|
|||
#服务器配置
|
||||
server:
|
||||
undertow:
|
||||
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
|
||||
buffer-size: 1024
|
||||
# 是否分配的直接内存
|
||||
direct-buffers: true
|
||||
# 线程配置
|
||||
threads:
|
||||
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
|
||||
io: 16
|
||||
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
|
||||
worker: 400
|
||||
|
||||
#spring配置
|
||||
spring:
|
||||
cloud:
|
||||
sentinel:
|
||||
eager: true
|
||||
devtools:
|
||||
restart:
|
||||
log-condition-evaluation-delta: false
|
||||
livereload:
|
||||
port: 23333
|
||||
servlet:
|
||||
multipart:
|
||||
location: /home/sis/apps/undertow/tmp
|
||||
|
||||
#feign配置
|
||||
feign:
|
||||
sentinel:
|
||||
enabled: true
|
||||
okhttp:
|
||||
enabled: true
|
||||
httpclient:
|
||||
enabled: true
|
||||
hystrix:
|
||||
enable: true
|
||||
client:
|
||||
config:
|
||||
default:
|
||||
readTimeout: 120000
|
||||
connectTimeout: 3000
|
||||
|
||||
|
||||
#对外暴露端口
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: "*"
|
||||
endpoint:
|
||||
health:
|
||||
show-details: always
|
||||
|
||||
#knife4j配置
|
||||
knife4j:
|
||||
#启用
|
||||
enable: true
|
||||
#基础认证
|
||||
basic:
|
||||
enable: false
|
||||
username: blade
|
||||
password: blade
|
||||
#增强配置
|
||||
setting:
|
||||
enableSwaggerModels: true
|
||||
enableDocumentManage: true
|
||||
enableHost: false
|
||||
enableHostText: http://localhost
|
||||
enableRequestCache: true
|
||||
enableFilterMultipartApis: false
|
||||
enableFilterMultipartApiMethodType: POST
|
||||
language: zh-CN
|
||||
enableFooter: false
|
||||
enableFooterCustom: true
|
||||
footerCustomContent: Copyright © 2021 SpringBlade All Rights Reserved
|
||||
|
||||
#swagger配置信息
|
||||
swagger:
|
||||
title: SpringBlade 接口文档系统
|
||||
description: SpringBlade 接口文档系统
|
||||
version: 3.0.3
|
||||
license: Powered By SpringBlade
|
||||
licenseUrl: https://bladex.vip
|
||||
terms-of-service-url: https://bladex.vip
|
||||
contact:
|
||||
name: smallchill
|
||||
email: smallchill@163.com
|
||||
url: https://gitee.com/smallc
|
||||
|
||||
#blade配置
|
||||
blade:
|
||||
xss:
|
||||
enabled: true
|
||||
skip-url:
|
||||
- /weixin
|
||||
secure:
|
||||
skip-url:
|
||||
- /test/**
|
||||
client:
|
||||
- client-id: sword
|
||||
path-patterns:
|
||||
- /sword/**
|
||||
- client-id: saber
|
||||
path-patterns:
|
||||
- /saber/**
|
||||
tenant:
|
||||
column: tenant_id
|
||||
tables:
|
||||
- blade_notice
|
|
@ -0,0 +1,127 @@
|
|||
#spring配置
|
||||
spring:
|
||||
redis:
|
||||
##redis 单机环境配置
|
||||
host: 197.50.18.66
|
||||
port: 16379
|
||||
timeout: 10000
|
||||
password:
|
||||
database: 0
|
||||
ssl: false
|
||||
##redis 集群环境配置
|
||||
#cluster:
|
||||
# nodes: 47.108.70.243:7001,47.108.70.243:7002,47.108.70.243:7003
|
||||
# commandTimeout: 5000
|
||||
datasource:
|
||||
driver-class-name: com.alipay.oceanbase.jdbc.Driver
|
||||
druid:
|
||||
validation-query: select 1
|
||||
url: jdbc:oceanbase://oceanbase.qprod.htb.srv:2883/siszsc?useUnicode=true&characterEncoding=utf-8&mode=mysql&rewriteBatchedStatements=true&socketTimeout=6000000&connectTimeout=60000&allowMultiQueries=true&useLocalSessionState=true
|
||||
username: htb_prod_obcluster:siszsc:secretiy
|
||||
password: SIS_pswd@123
|
||||
|
||||
#项目模块集中配置
|
||||
blade:
|
||||
esbUrl: 197.34.18.16
|
||||
esbPort: 39245
|
||||
face:
|
||||
virtualTelNo: C00074
|
||||
leadDeptNo: 12023
|
||||
telIdentTp: HTBK
|
||||
#分布式锁配置
|
||||
lock:
|
||||
enabled: false
|
||||
address: redis://47.108.70.243:6379
|
||||
#多团队协作服务配置
|
||||
ribbon:
|
||||
rule:
|
||||
#开启配置
|
||||
enabled: true
|
||||
#负载均衡优先调用的ip段
|
||||
prior-ip-pattern:
|
||||
- 192.168.0.*
|
||||
- 47.108.70.243
|
||||
#通用开发生产环境数据库地址(特殊情况可在对应的子工程里配置覆盖)
|
||||
datasource:
|
||||
test:
|
||||
url: jdbc:oceanbase://oceanbase.qprod.htb.srv:2883/siszsc?useUnicode=true&characterEncoding=utf-8&mode=mysql&rewriteBatchedStatements=true&socketTimeout=6000000&connectTimeout=60000&allowMultiQueries=true&useLocalSessionState=true
|
||||
username: htb_prod_obcluster:siszsc:secretiy
|
||||
password: SIS_pswd@123
|
||||
# dev:
|
||||
# url: jdbc:oceanbase://oceanbase.test.htb.srv:2883/sisdev?useUnicode=true&characterEncoding=utf-8&mode=mysql&rewriteBatchedStatements=true&socketTimeout=6000000&connectTimeout=60000&allowMultiQueries=true&useLocalSessionState=true
|
||||
# username: htb_test_obcluster:secretiy:secretiydev
|
||||
# password: secretiydev
|
||||
|
||||
|
||||
#
|
||||
# Emb(消息总线请求参数)配置 -sit
|
||||
sub:
|
||||
brokerServiceurl: pulsar://198.69.20.7:6000
|
||||
accessToken: eyJrZXlJZCI6InB1bHNhci13ejlwMmptYnBuIiwiYWxnIjoiSFMyNTYifQ.eyJzdWIiOiJwdWxzYXItd3o5cDJqbWJwbl9TSU1TIn0.ibMqmjqOJkNMWsxBJj-zLbGsG3VY5gX74G3MTIkMIHQ
|
||||
subscriptionName: SIMS
|
||||
corePoolSize: 1
|
||||
evnValue: pulsar-wz9p2jmbpn
|
||||
listenerName: pulsar-wz9p2jmbpn/vpc-espi8lwv/subnet-6o1k8cm0
|
||||
topicNames:
|
||||
- pulsar-wz9p2jmbpn/sso-common-info/M01010001
|
||||
- pulsar-wz9p2jmbpn/sso-common-info/M01010002
|
||||
- pulsar-wz9p2jmbpn/sso-common-info/M01030006
|
||||
maximumPoolSize: 300
|
||||
deptLeaderName: 机构负责人 #行政机构信息同步的机构负责人对应的角色名称
|
||||
|
||||
#security-desk-yml配置文件
|
||||
#影像平台
|
||||
images:
|
||||
local_path: E:\安防信息化项目\uploadFile\ #本地存放文件路径
|
||||
service_path: /home/test/apps/file/ # 服务器存放文件路径
|
||||
DM: HTBANK
|
||||
ip: nicmp.qprod.htb.srv #为影像平台的ip地址
|
||||
socketPort: 8023 #为影像平台的socket端口
|
||||
httpPort: 9080 #为影像平台的http端口
|
||||
aimChannel: SIMS #渠道号
|
||||
modelCode: SIMS #索引对象内容模型代码
|
||||
filePartName: SIMS_PART #文档对象模型代码
|
||||
userName: sims #登录影像平台的用户名
|
||||
passWord: sims_admin #登录影像平台的密码
|
||||
|
||||
xyun:
|
||||
app-id: 500000053
|
||||
app-secret: B6rbJdILa1VEO9fmn6zj
|
||||
url: http://197.52.23.10
|
||||
# 公共号id
|
||||
pub-id: XT-cb5053a4-3d00-47e7-a0c3-d0ac693305b7
|
||||
pub-secret: 812739e21bf781370bebec37146c38a8
|
||||
# 企业注册号eid
|
||||
e-id: 1556583279
|
||||
|
||||
|
||||
# 单点登录配置参数
|
||||
single:
|
||||
auth-url: http://bam.sit.ynhtbank.com:9080/idp/oauth2/authorize #单点登录url
|
||||
client-id: SIMS #应用系统ID
|
||||
redirect-uri: http://197.52.29.131:8105/authorize #重定向url
|
||||
response-type: code #响应类型
|
||||
state: 123 #3位随机数字
|
||||
client-secret: 3ac76afc760f4c8b9265992e28c924df
|
||||
auth-res-url: http://197.52.26.105:20009/v1/SWD/SWD20001 #单点登录授权url
|
||||
index-url: http://197.52.29.131:8888/single-login #首页地址
|
||||
scvcd: 3043003401 #上esb获取用户信息的服务码
|
||||
user-url: localhost:8000/api/security-auth/oauth/token
|
||||
|
||||
|
||||
#ht-secutity-yml配置文件
|
||||
#导出文件的存储路径
|
||||
export:
|
||||
excel:
|
||||
path: D:\云南红塔银行安保项目\excel导出测试\
|
||||
|
||||
#swagger包扫描路径
|
||||
swagger:
|
||||
base-packages: org.security.trans
|
||||
|
||||
#通用配置参数
|
||||
common:
|
||||
projectRoleName: 安全员 #项目预算管理-项目结项后可以对结项项目进行操作的指属上一级机构的角色名称
|
||||
securityRoleName: 安全员 #安保指挥中心非现场检查整改通知书通知机构的角色
|
||||
payPlanRemindKeyName: payPlanRemindDay #付款计划提醒提前天数字典配置键值
|
||||
concatDeadlineRemindKeyName: concatDeadlineRemindDay #合同到期提醒提前天数字典配置键值
|
|
@ -0,0 +1,111 @@
|
|||
#服务器配置
|
||||
server:
|
||||
undertow:
|
||||
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
|
||||
buffer-size: 1024
|
||||
# 是否分配的直接内存
|
||||
direct-buffers: true
|
||||
# 线程配置
|
||||
threads:
|
||||
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
|
||||
io: 16
|
||||
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
|
||||
worker: 400
|
||||
|
||||
#spring配置
|
||||
spring:
|
||||
cloud:
|
||||
sentinel:
|
||||
eager: true
|
||||
devtools:
|
||||
restart:
|
||||
log-condition-evaluation-delta: false
|
||||
livereload:
|
||||
port: 23333
|
||||
servlet:
|
||||
multipart:
|
||||
location: /home/test/apps/undertow/tmp
|
||||
|
||||
#feign配置
|
||||
feign:
|
||||
sentinel:
|
||||
enabled: true
|
||||
okhttp:
|
||||
enabled: true
|
||||
httpclient:
|
||||
enabled: true
|
||||
hystrix:
|
||||
enable: true
|
||||
client:
|
||||
config:
|
||||
default:
|
||||
readTimeout: 120000
|
||||
connectTimeout: 3000
|
||||
|
||||
|
||||
#对外暴露端口
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: "*"
|
||||
endpoint:
|
||||
health:
|
||||
show-details: always
|
||||
|
||||
#knife4j配置
|
||||
knife4j:
|
||||
#启用
|
||||
enable: true
|
||||
#基础认证
|
||||
basic:
|
||||
enable: false
|
||||
username: blade
|
||||
password: blade
|
||||
#增强配置
|
||||
setting:
|
||||
enableSwaggerModels: true
|
||||
enableDocumentManage: true
|
||||
enableHost: false
|
||||
enableHostText: http://localhost
|
||||
enableRequestCache: true
|
||||
enableFilterMultipartApis: false
|
||||
enableFilterMultipartApiMethodType: POST
|
||||
language: zh-CN
|
||||
enableFooter: false
|
||||
enableFooterCustom: true
|
||||
footerCustomContent: Copyright © 2021 SpringBlade All Rights Reserved
|
||||
|
||||
#swagger配置信息
|
||||
swagger:
|
||||
title: SpringBlade 接口文档系统
|
||||
description: SpringBlade 接口文档系统
|
||||
version: 3.0.3
|
||||
license: Powered By SpringBlade
|
||||
licenseUrl: https://bladex.vip
|
||||
terms-of-service-url: https://bladex.vip
|
||||
contact:
|
||||
name: smallchill
|
||||
email: smallchill@163.com
|
||||
url: https://gitee.com/smallc
|
||||
|
||||
#blade配置
|
||||
blade:
|
||||
xss:
|
||||
enabled: true
|
||||
skip-url:
|
||||
- /weixin
|
||||
secure:
|
||||
skip-url:
|
||||
- /test/**
|
||||
client:
|
||||
- client-id: sword
|
||||
path-patterns:
|
||||
- /sword/**
|
||||
- client-id: saber
|
||||
path-patterns:
|
||||
- /saber/**
|
||||
tenant:
|
||||
column: tenant_id
|
||||
tables:
|
||||
- blade_notice
|
|
@ -0,0 +1,185 @@
|
|||
|
||||
#user nobody;
|
||||
worker_processes 1;
|
||||
|
||||
#error_log logs/error.log;
|
||||
#error_log logs/error.log notice;
|
||||
#error_log logs/error.log info;
|
||||
|
||||
#pid logs/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
client_max_body_size 50m;
|
||||
|
||||
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
# '$status $body_bytes_sent "$http_referer" '
|
||||
# '"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
#access_log logs/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
#keepalive_timeout 0;
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
|
||||
#server {
|
||||
# listen 80;
|
||||
# server_name localhost;
|
||||
|
||||
#charset koi8-r;
|
||||
|
||||
#access_log logs/host.access.log main;
|
||||
|
||||
# location / {
|
||||
# root html;
|
||||
# index index.html index.htm;
|
||||
# }
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
# error_page 500 502 503 504 /50x.html;
|
||||
# location = /50x.html {
|
||||
# root html;
|
||||
# }
|
||||
|
||||
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# proxy_pass http://127.0.0.1;
|
||||
#}
|
||||
|
||||
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# root html;
|
||||
# fastcgi_pass 127.0.0.1:9000;
|
||||
# fastcgi_index index.php;
|
||||
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
|
||||
# include fastcgi_params;
|
||||
#}
|
||||
|
||||
# deny access to .htaccess files, if Apache's document root
|
||||
# concurs with nginx's one
|
||||
#
|
||||
#location ~ /\.ht {
|
||||
# deny all;
|
||||
#}
|
||||
# }
|
||||
server {
|
||||
listen 8887;
|
||||
server_name web-test;
|
||||
location ^~ /sis/ {
|
||||
proxy_pass http://127.0.0.1:8889;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8888;
|
||||
server_name web;
|
||||
#root /home/test/apps/security-manage/security/dist;
|
||||
|
||||
##location /file/ {
|
||||
## root /home/test/apps;
|
||||
## autoindex on;
|
||||
##}
|
||||
|
||||
#location ^~ /sis/ {
|
||||
# proxy_pass http://127.0.0.1:8889;
|
||||
#}
|
||||
|
||||
location /map-resouce/ {
|
||||
root /home/test/apps/map;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /home/test/apps/security-pc/dist;
|
||||
index index.html;
|
||||
}
|
||||
|
||||
location ^~ /oauth/redirect {
|
||||
rewrite ^(.*)$ /index.html break;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_buffering off;
|
||||
rewrite ^/api/(.*)$ /$1 break;
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8889; #监听端口
|
||||
server_name app; #服务器名
|
||||
location /sis/api/ {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_buffering off;
|
||||
rewrite ^/sis/api/(.*)$ /$1 break;
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
}
|
||||
|
||||
location ^~ /sis {
|
||||
alias /home/test/apps/security-app/dist/sis;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /@router;
|
||||
}
|
||||
|
||||
location @router {
|
||||
rewrite ^.*$ /index.html last;
|
||||
}
|
||||
}
|
||||
|
||||
# another virtual host using mix of IP-, name-, and port-based configuration
|
||||
#
|
||||
#server {
|
||||
# listen 8000;
|
||||
# listen somename:8080;
|
||||
# server_name somename alias another.alias;
|
||||
|
||||
# location / {
|
||||
# root html;
|
||||
# index index.html index.htm;
|
||||
# }
|
||||
#}
|
||||
|
||||
|
||||
# HTTPS server
|
||||
#
|
||||
#server {
|
||||
# listen 443 ssl;
|
||||
# server_name localhost;
|
||||
|
||||
# ssl_certificate cert.pem;
|
||||
# ssl_certificate_key cert.key;
|
||||
|
||||
# ssl_session_cache shared:SSL:1m;
|
||||
# ssl_session_timeout 5m;
|
||||
|
||||
# ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
# ssl_prefer_server_ciphers on;
|
||||
|
||||
# location / {
|
||||
# root html;
|
||||
# index index.html index.htm;
|
||||
# }
|
||||
#}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
#user nobody;
|
||||
worker_processes 1;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
client_max_body_size 50m;
|
||||
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
|
||||
server {
|
||||
listen 8888;
|
||||
server_name web;
|
||||
|
||||
location /map-resouce/ {
|
||||
root /home/sis/apps/map;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /home/sis/apps/security-pc/dist;
|
||||
index index.html;
|
||||
}
|
||||
|
||||
location ^~ /oauth/redirect {
|
||||
rewrite ^(.*)$ /index.html break;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_buffering off;
|
||||
rewrite ^/api/(.*)$ /$1 break;
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8889; #监听端口
|
||||
server_name app; #服务器名
|
||||
|
||||
location /sis/api/ {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_buffering off;
|
||||
rewrite ^/sis/api/(.*)$ /$1 break;
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
}
|
||||
|
||||
location ^~ /sis {
|
||||
alias /home/sis/apps/security-app/dist/sis;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
|
||||
#user nobody;
|
||||
worker_processes 1;
|
||||
|
||||
#error_log logs/error.log;
|
||||
#error_log logs/error.log notice;
|
||||
#error_log logs/error.log info;
|
||||
|
||||
#pid logs/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
client_max_body_size 50m;
|
||||
|
||||
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
# '$status $body_bytes_sent "$http_referer" '
|
||||
# '"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
#access_log logs/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
#keepalive_timeout 0;
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
|
||||
#server {
|
||||
# listen 80;
|
||||
# server_name localhost;
|
||||
|
||||
#charset koi8-r;
|
||||
|
||||
#access_log logs/host.access.log main;
|
||||
|
||||
# location / {
|
||||
# root html;
|
||||
# index index.html index.htm;
|
||||
# }
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
# error_page 500 502 503 504 /50x.html;
|
||||
# location = /50x.html {
|
||||
# root html;
|
||||
# }
|
||||
|
||||
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# proxy_pass http://127.0.0.1;
|
||||
#}
|
||||
|
||||
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# root html;
|
||||
# fastcgi_pass 127.0.0.1:9000;
|
||||
# fastcgi_index index.php;
|
||||
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
|
||||
# include fastcgi_params;
|
||||
#}
|
||||
|
||||
# deny access to .htaccess files, if Apache's document root
|
||||
# concurs with nginx's one
|
||||
#
|
||||
#location ~ /\.ht {
|
||||
# deny all;
|
||||
#}
|
||||
# }
|
||||
|
||||
server {
|
||||
listen 8888;
|
||||
server_name web;
|
||||
#root /home/test/apps/security-manage/security/dist;
|
||||
|
||||
#location /file/ {
|
||||
# root /home/test/apps;
|
||||
# autoindex on;
|
||||
#}
|
||||
|
||||
location /map-resouce/ {
|
||||
root /home/test/apps/map;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /home/test/apps/security-pc/dist;
|
||||
index index.html;
|
||||
}
|
||||
|
||||
location ^~ /nacos {
|
||||
proxy_pass http://197.50.18.66:8848/nacos;
|
||||
}
|
||||
|
||||
location ^~ /oauth/redirect {
|
||||
rewrite ^(.*)$ /index.html break;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_buffering off;
|
||||
rewrite ^/api/(.*)$ /$1 break;
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
}
|
||||
location ^~ /sis/ {
|
||||
proxy_pass http://127.0.0.1:8889;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8889; #监听端口
|
||||
server_name app; #服务器名
|
||||
location /sis/api/ {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_buffering off;
|
||||
rewrite ^/sis/api/(.*)$ /$1 break;
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
}
|
||||
|
||||
location ^~ /sis {
|
||||
alias /home/test/apps/security-app/dist/sis;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
|
||||
# another virtual host using mix of IP-, name-, and port-based configuration
|
||||
#
|
||||
#server {
|
||||
# listen 8000;
|
||||
# listen somename:8080;
|
||||
# server_name somename alias another.alias;
|
||||
|
||||
# location / {
|
||||
# root html;
|
||||
# index index.html index.htm;
|
||||
# }
|
||||
#}
|
||||
|
||||
|
||||
# HTTPS server
|
||||
#
|
||||
#server {
|
||||
# listen 443 ssl;
|
||||
# server_name localhost;
|
||||
|
||||
# ssl_certificate cert.pem;
|
||||
# ssl_certificate_key cert.key;
|
||||
|
||||
# ssl_session_cache shared:SSL:1m;
|
||||
# ssl_session_timeout 5m;
|
||||
|
||||
# ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
# ssl_prefer_server_ciphers on;
|
||||
|
||||
# location / {
|
||||
# root html;
|
||||
# index index.html index.htm;
|
||||
# }
|
||||
#}
|
||||
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
-- 业务表部分 开始
|
||||
-- 检查整改表
|
||||
delete from t_inspection;
|
||||
-- 检查整改明细表
|
||||
delete from t_inspection_line;
|
||||
-- 应急演练、教育培训
|
||||
delete from t_task_handin;
|
||||
-- 任务下发
|
||||
delete from t_task;
|
||||
-- 案件材料报送
|
||||
delete from t_prevent_material;
|
||||
-- 风险提示
|
||||
delete from t_prevent_risk;
|
||||
-- 考核评价表
|
||||
delete from t_assessment;
|
||||
-- 考核评价明细表
|
||||
delete from t_assessment_detail;
|
||||
-- 值班备勤
|
||||
delete from t_duty_records;
|
||||
-- 值班备勤明细
|
||||
delete from t_duty_records_lines;
|
||||
-- 工作报备表
|
||||
delete from t_work_filing;
|
||||
-- 工作提醒表
|
||||
delete from t_note_remind;
|
||||
-- 非现场检查表
|
||||
delete from t_scc_check;
|
||||
-- 非现场检查明细表
|
||||
delete from t_scc_check_lines;
|
||||
-- 整改通知书表
|
||||
delete from t_scc_unlocale_check;
|
||||
-- 整改通知书明细表
|
||||
delete from t_scc_unlocale_check_line;
|
||||
-- 联系接警记录表
|
||||
delete from t_scc_answer_alarm;
|
||||
-- 警情处理表
|
||||
delete from t_scc_alarm_push;
|
||||
-- 模板管理表
|
||||
-- delete from t_file_template;
|
||||
-- 法律法规表
|
||||
delete from t_law;
|
||||
-- 设备检查表
|
||||
delete from t_device_inspection;
|
||||
-- 设备检查明细表
|
||||
delete from t_device_inspection_line;
|
||||
-- 项目管理-预算
|
||||
delete from t_budget_item;
|
||||
-- 项目管理-项目信息
|
||||
delete from t_project;
|
||||
delete from t_project_check;
|
||||
delete from t_project_contract;
|
||||
delete from t_project_establishment;
|
||||
delete from t_project_implementation;
|
||||
delete from t_project_over_history;
|
||||
delete from t_project_pay_plan;
|
||||
delete from t_project_purchase;
|
||||
delete from t_publicity;
|
||||
-- 工作交接记录表
|
||||
delete from t_handover_history;
|
||||
-- 交接人员组
|
||||
delete from t_work_handover_users;
|
||||
-- 设备信息
|
||||
delete from t_device;
|
||||
-- 宣传报道
|
||||
delete from t_publicity;
|
||||
-- 相关方公司
|
||||
delete from t_out_company;
|
||||
-- 相关方人员
|
||||
delete from t_out_employee;
|
||||
delete from t_out_family;
|
||||
delete from t_out_job_record;
|
||||
-- 附件表中删除 除模板管理 以外的数据
|
||||
delete from t_file where link_id not in (select id from t_file_template);
|
||||
-- 业务表结束
|
||||
|
||||
-- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
-- flowable业务表 开始
|
||||
-- 历史流程实例
|
||||
delete from act_hi_actinst;
|
||||
-- 历史流程附件
|
||||
delete from act_hi_attachment;
|
||||
-- 历史说明性信息
|
||||
delete from act_hi_comment;
|
||||
-- 历史流程运行中细节信息
|
||||
delete from act_hi_detail;
|
||||
-- 历史参与人员表
|
||||
delete from act_hi_entitylink;
|
||||
-- 历史流程中的用户关系
|
||||
delete from act_hi_identitylink;
|
||||
-- 历史流程实例
|
||||
delete from act_hi_procinst;
|
||||
-- 历史人物实例
|
||||
delete from act_hi_taskinst;
|
||||
-- 每一次执行(execution)可能带上的数据
|
||||
delete from act_hi_tsk_log;
|
||||
-- 历史流程变量
|
||||
delete from act_hi_varinst;
|
||||
|
||||
|
||||
-- 运行中的流程实例
|
||||
delete from act_ru_actinst;
|
||||
-- 正在运行的任务表
|
||||
delete from act_ru_deadletter_job;
|
||||
delete from act_ru_entitylink;
|
||||
-- 运行时事件
|
||||
delete from act_ru_event_subscr;
|
||||
-- 历史作业表
|
||||
delete from act_ru_history_job;
|
||||
-- 运行时用户关系
|
||||
delete from act_ru_identitylink;
|
||||
-- 运行时作业表
|
||||
delete from act_ru_job;
|
||||
-- 暂停作业表
|
||||
delete from act_ru_suspended_job;
|
||||
-- 运行时任务表
|
||||
delete from act_ru_task;
|
||||
-- 定时作业表
|
||||
delete from act_ru_timer_job;
|
||||
-- 运行时变量表
|
||||
delete from act_ru_variable;
|
||||
|
||||
|
||||
-- 运行时流程执行实例
|
||||
UPDATE act_ru_execution SET REV_ = '2';
|
||||
update act_ru_execution set parent_id_ = null;
|
||||
delete from act_ru_execution;
|
||||
-- flowable业务表 结束
|
||||
|
||||
-- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
-- 检查整改表
|
||||
delete from t_inspection;
|
||||
-- 检查整改明细表
|
||||
delete from t_inspection_line;
|
||||
-- 应急演练、教育培训
|
||||
delete from t_task_handin;
|
||||
-- 任务下发
|
||||
delete from t_task;
|
||||
-- 案件材料报送
|
||||
delete from t_prevent_material;
|
||||
-- 风险提示
|
||||
delete from t_prevent_risk;
|
||||
-- 考核评价表
|
||||
delete from t_assessment;
|
||||
-- 考核评价明细表
|
||||
delete from t_assessment_detail;
|
||||
-- 值班备勤
|
||||
delete from t_duty_records;
|
||||
-- 值班备勤明细
|
||||
delete from t_duty_records_lines;
|
||||
-- 工作报备表
|
||||
delete from t_work_filing;
|
||||
-- 工作提醒表
|
||||
delete from t_note_remind;
|
||||
-- 非现场检查表
|
||||
delete from t_scc_check;
|
||||
-- 非现场检查明细表
|
||||
delete from t_scc_check_lines;
|
||||
-- 整改通知书表
|
||||
delete from t_scc_unlocale_check;
|
||||
-- 整改通知书明细表
|
||||
delete from t_scc_unlocale_check_line;
|
||||
-- 联系接警记录表
|
||||
delete from t_scc_answer_alarm;
|
||||
-- 警情处理表
|
||||
delete from t_scc_alarm_push;
|
||||
-- 模板管理表
|
||||
-- delete from t_file_template;
|
||||
-- 法律法规表
|
||||
delete from t_law;
|
||||
-- 设备检查表
|
||||
delete from t_device_inspection;
|
||||
-- 设备检查明细表
|
||||
delete from t_device_inspection_line;
|
||||
-- 项目管理-预算
|
||||
delete from t_budget_item;
|
||||
-- 项目管理-项目信息
|
||||
delete from t_project;
|
||||
delete from t_project_check;
|
||||
delete from t_project_contract;
|
||||
delete from t_project_establishment;
|
||||
delete from t_project_implementation;
|
||||
delete from t_project_over_history;
|
||||
delete from t_project_pay_plan;
|
||||
delete from t_project_purchase;
|
||||
delete from t_publicity;
|
||||
-- 工作交接记录表
|
||||
delete from t_handover_history;
|
||||
-- 交接人员组
|
||||
delete from t_work_handover_users;
|
||||
-- 设备信息
|
||||
delete from t_device;
|
||||
-- 宣传报道
|
||||
delete from t_publicity;
|
||||
-- 相关方公司
|
||||
delete from t_out_company;
|
||||
-- 相关方人员
|
||||
delete from t_out_employee;
|
||||
delete from t_out_family;
|
||||
delete from t_out_job_record;
|
||||
-- 附件表中删除 除模板管理 以外的数据
|
||||
delete from t_file where link_id not in (select id from t_file_template);
|
|
@ -0,0 +1,80 @@
|
|||
-- 历史流程实例
|
||||
delete from act_hi_actinst;
|
||||
-- 历史流程附件
|
||||
delete from act_hi_attachment;
|
||||
-- 历史说明性信息
|
||||
delete from act_hi_comment;
|
||||
-- 历史流程运行中细节信息
|
||||
delete from act_hi_detail;
|
||||
-- 历史参与人员表
|
||||
delete from act_hi_entitylink;
|
||||
-- 历史流程中的用户关系
|
||||
delete from act_hi_identitylink;
|
||||
-- 历史流程实例
|
||||
delete from act_hi_procinst;
|
||||
-- 历史人物实例
|
||||
delete from act_hi_taskinst;
|
||||
-- 每一次执行(execution)可能带上的数据
|
||||
delete from act_hi_tsk_log;
|
||||
-- 历史流程变量
|
||||
delete from act_hi_varinst;
|
||||
|
||||
|
||||
-- 运行中的流程实例
|
||||
delete from act_ru_actinst;
|
||||
-- 正在运行的任务表
|
||||
delete from act_ru_deadletter_job;
|
||||
delete from act_ru_entitylink;
|
||||
-- 运行时事件
|
||||
delete from act_ru_event_subscr;
|
||||
-- 历史作业表
|
||||
delete from act_ru_history_job;
|
||||
-- 运行时用户关系
|
||||
delete from act_ru_identitylink;
|
||||
-- 运行时作业表
|
||||
delete from act_ru_job;
|
||||
-- 暂停作业表
|
||||
delete from act_ru_suspended_job;
|
||||
-- 运行时任务表
|
||||
delete from act_ru_task;
|
||||
-- 定时作业表
|
||||
delete from act_ru_timer_job;
|
||||
-- 运行时变量表
|
||||
delete from act_ru_variable;
|
||||
-- 运行时流程执行实例
|
||||
update act_ru_execution set REV_ = '2';
|
||||
update act_ru_execution set parent_id_ = null;
|
||||
delete from act_ru_execution;
|
||||
|
||||
|
||||
-- 系统业务表与flowable关联字段
|
||||
-- 考核评价
|
||||
update t_assessment set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 设备检查/整改/持续整改
|
||||
update t_device_inspection set process_definition_id = null, process_instance_id = null, ins_process_definition_id = null, ins_process_instance_id = null, rec_process_definition_id = null, rec_process_instance_id = null, state = '0';
|
||||
-- 设备检查明细
|
||||
update t_device_inspection_line set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 值班备勤
|
||||
update t_duty_records set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 现场检查
|
||||
update t_inspection set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 现场检查整改
|
||||
update t_inspection_line set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 案件材料报送
|
||||
update t_prevent_material set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 风险提示
|
||||
update t_prevent_risk set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 警情处理
|
||||
update t_scc_alarm_push set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 联系接警记录
|
||||
update t_scc_answer_alarm set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 非现场检查
|
||||
update t_scc_check set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 非现场检查整改
|
||||
update t_scc_unlocale_check set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 非现场检查整改明细
|
||||
update t_scc_unlocale_check_line set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
-- 教育培训/应急演练
|
||||
update t_task_handin set process_definition_id = null, process_instance_id = null, state = '0';
|
||||
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
INSERT INTO
|
||||
`blade_user`
|
||||
VALUES
|
||||
(
|
||||
1123598821738675201,
|
||||
'000000',
|
||||
NULL,
|
||||
1,
|
||||
'admin',
|
||||
'90b9aa7e25f80cf4f64e990b78a9fc5ebd6cecad',
|
||||
'管理员',
|
||||
'管理员',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png',
|
||||
'admin@bladex.vip',
|
||||
'123333333333',
|
||||
'2018-08-08 00:00:00',
|
||||
1,
|
||||
'1123598816738675201',
|
||||
'1580387563597537281',
|
||||
'1123598817738675201',
|
||||
1123598821738675201,
|
||||
1123598813738675201,
|
||||
'2018-08-08 00:00:00',
|
||||
1123598821738675201,
|
||||
'2018-08-08 00:00:00',
|
||||
1,
|
||||
0
|
||||
);
|
|
@ -0,0 +1,201 @@
|
|||
CREATE TABLE `config_info` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
|
||||
`group_id` varchar(255) DEFAULT NULL,
|
||||
`content` longtext NOT NULL COMMENT 'content',
|
||||
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
|
||||
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
|
||||
`src_user` text COMMENT 'source user',
|
||||
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
|
||||
`app_name` varchar(128) DEFAULT NULL,
|
||||
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
|
||||
`c_desc` varchar(256) DEFAULT NULL,
|
||||
`c_use` varchar(64) DEFAULT NULL,
|
||||
`effect` varchar(64) DEFAULT NULL,
|
||||
`type` varchar(64) DEFAULT NULL,
|
||||
`c_schema` text,
|
||||
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
|
||||
|
||||
/******************************************/
|
||||
/* 数据库全名 = nacos_config */
|
||||
/* 表名称 = config_info_aggr */
|
||||
/******************************************/
|
||||
CREATE TABLE `config_info_aggr` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
|
||||
`group_id` varchar(255) NOT NULL COMMENT 'group_id',
|
||||
`datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
|
||||
`content` longtext NOT NULL COMMENT '内容',
|
||||
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
|
||||
`app_name` varchar(128) DEFAULT NULL,
|
||||
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';
|
||||
|
||||
|
||||
/******************************************/
|
||||
/* 数据库全名 = nacos_config */
|
||||
/* 表名称 = config_info_beta */
|
||||
/******************************************/
|
||||
CREATE TABLE `config_info_beta` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
|
||||
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
|
||||
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
|
||||
`content` longtext NOT NULL COMMENT 'content',
|
||||
`beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
|
||||
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
|
||||
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
|
||||
`src_user` text COMMENT 'source user',
|
||||
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
|
||||
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
|
||||
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
|
||||
|
||||
/******************************************/
|
||||
/* 数据库全名 = nacos_config */
|
||||
/* 表名称 = config_info_tag */
|
||||
/******************************************/
|
||||
CREATE TABLE `config_info_tag` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
|
||||
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
|
||||
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
|
||||
`tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
|
||||
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
|
||||
`content` longtext NOT NULL COMMENT 'content',
|
||||
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
|
||||
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
|
||||
`src_user` text COMMENT 'source user',
|
||||
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
|
||||
|
||||
/******************************************/
|
||||
/* 数据库全名 = nacos_config */
|
||||
/* 表名称 = config_tags_relation */
|
||||
/******************************************/
|
||||
CREATE TABLE `config_tags_relation` (
|
||||
`id` bigint(20) NOT NULL COMMENT 'id',
|
||||
`tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
|
||||
`tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
|
||||
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
|
||||
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
|
||||
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
|
||||
`nid` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (`nid`),
|
||||
UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
|
||||
KEY `idx_tenant_id` (`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
|
||||
|
||||
/******************************************/
|
||||
/* 数据库全名 = nacos_config */
|
||||
/* 表名称 = group_capacity */
|
||||
/******************************************/
|
||||
CREATE TABLE `group_capacity` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
|
||||
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
|
||||
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
|
||||
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
|
||||
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
|
||||
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
|
||||
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
|
||||
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_group_id` (`group_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
|
||||
|
||||
/******************************************/
|
||||
/* 数据库全名 = nacos_config */
|
||||
/* 表名称 = his_config_info */
|
||||
/******************************************/
|
||||
CREATE TABLE `his_config_info` (
|
||||
`id` bigint(20) unsigned NOT NULL,
|
||||
`nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`data_id` varchar(255) NOT NULL,
|
||||
`group_id` varchar(128) NOT NULL,
|
||||
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
|
||||
`content` longtext NOT NULL,
|
||||
`md5` varchar(32) DEFAULT NULL,
|
||||
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`src_user` text,
|
||||
`src_ip` varchar(50) DEFAULT NULL,
|
||||
`op_type` char(10) DEFAULT NULL,
|
||||
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
|
||||
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
|
||||
PRIMARY KEY (`nid`),
|
||||
KEY `idx_gmt_create` (`gmt_create`),
|
||||
KEY `idx_gmt_modified` (`gmt_modified`),
|
||||
KEY `idx_did` (`data_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
|
||||
|
||||
|
||||
/******************************************/
|
||||
/* 数据库全名 = nacos_config */
|
||||
/* 表名称 = tenant_capacity */
|
||||
/******************************************/
|
||||
CREATE TABLE `tenant_capacity` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
|
||||
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
|
||||
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
|
||||
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
|
||||
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
|
||||
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
|
||||
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
|
||||
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tenant_id` (`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
|
||||
|
||||
|
||||
CREATE TABLE `tenant_info` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`kp` varchar(128) NOT NULL COMMENT 'kp',
|
||||
`tenant_id` varchar(128) default '' COMMENT 'tenant_id',
|
||||
`tenant_name` varchar(128) default '' COMMENT 'tenant_name',
|
||||
`tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
|
||||
`create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
|
||||
`gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
|
||||
`gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
|
||||
KEY `idx_tenant_id` (`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
|
||||
|
||||
CREATE TABLE `users` (
|
||||
`username` varchar(50) NOT NULL PRIMARY KEY,
|
||||
`password` varchar(500) NOT NULL,
|
||||
`enabled` boolean NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE `roles` (
|
||||
`username` varchar(50) NOT NULL,
|
||||
`role` varchar(50) NOT NULL,
|
||||
UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
|
||||
);
|
||||
|
||||
CREATE TABLE `permissions` (
|
||||
`role` varchar(50) NOT NULL,
|
||||
`resource` varchar(255) NOT NULL,
|
||||
`action` varchar(8) NOT NULL,
|
||||
UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
|
||||
);
|
||||
|
||||
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
|
||||
|
||||
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
|
|
@ -0,0 +1,193 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
|
||||
<groupId>org.security</groupId>
|
||||
<artifactId>security-manage</artifactId>
|
||||
<version>2.8.1.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<bladex.project.version>2.8.1.RELEASE</bladex.project.version>
|
||||
|
||||
<java.version>1.8</java.version>
|
||||
<maven.plugin.version>3.8.1</maven.plugin.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
||||
<flowable.version>6.4.2</flowable.version>
|
||||
|
||||
<spring.boot.version>2.2.13.RELEASE</spring.boot.version>
|
||||
<spring.cloud.version>Hoxton.SR11</spring.cloud.version>
|
||||
<spring.platform.version>Cairo-SR8</spring.platform.version>
|
||||
<jasypt.version>3.0.3</jasypt.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
<module>security-auth</module>
|
||||
<module>security-common</module>
|
||||
<module>security-gateway</module>
|
||||
<module>security-ops</module>
|
||||
<module>security-ops-api</module>
|
||||
<module>security-service</module>
|
||||
<module>security-service-api</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.ulisesbocchio</groupId>
|
||||
<artifactId>jasypt-spring-boot-starter</artifactId>
|
||||
<version>${jasypt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade.platform</groupId>
|
||||
<artifactId>blade-bom</artifactId>
|
||||
<version>${bladex.project.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.security</groupId>
|
||||
<artifactId>security-common</artifactId>
|
||||
<version>${bladex.project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring.cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.spring.platform</groupId>
|
||||
<artifactId>platform-bom</artifactId>
|
||||
<version>${spring.platform.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.name}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
<finalName>${project.build.finalName}</finalName>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<tasks>
|
||||
<!--suppress UnresolvedMavenProperty -->
|
||||
<copy overwrite="true"
|
||||
tofile="${session.executionRootDirectory}/target/${project.artifactId}.jar"
|
||||
file="${project.build.directory}/${project.artifactId}.jar" />
|
||||
</tasks>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.spotify</groupId>
|
||||
<artifactId>dockerfile-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven.plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
<compilerArgs>
|
||||
<arg>-parameters</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<!-- <repository>-->
|
||||
<!-- <id>aliyun-repos</id>-->
|
||||
<!--<!– <url>https://maven.aliyun.com/nexus/content/groups/public/</url>–>-->
|
||||
<!-- <snapshots>-->
|
||||
<!-- <enabled>false</enabled>-->
|
||||
<!-- </snapshots>-->
|
||||
<!-- </repository>-->
|
||||
<repository>
|
||||
<id>blade-release</id>
|
||||
<name>Release Repository</name>
|
||||
<url>http://nexus.bladex.vip/repository/maven-releases/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<!-- <pluginRepository>-->
|
||||
<!-- <id>aliyun-plugin</id>-->
|
||||
<!--<!– <url>https://maven.aliyun.com/nexus/content/groups/public/</url>–>-->
|
||||
<!-- <snapshots>-->
|
||||
<!-- <enabled>false</enabled>-->
|
||||
<!-- </snapshots>-->
|
||||
<!-- </pluginRepository>-->
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,32 @@
|
|||
## 目前主要支持的oauth协议
|
||||
一、 授权码模式
|
||||
授权码模式(authorization_code)主要针对第三方应用,是最为复杂也最为安全的一种模式,操作步骤如下
|
||||
1. 访问地址:http://localhost:8100/oauth/authorize?client_id=blade&redirect_uri=http://example.com&code=233333&response_type=code
|
||||
2. 获取跳转后的code值(http://example.com/?code=VhYNLR)之后,调用 http://localhost/blade-auth/oauth/token 传入对应的参数
|
||||
|
||||
请求头:
|
||||
Authorization : Basic YmxhZGU6YmxhZGU= ("YmxhZGU6YmxhZGU="为clientId:clientSecret串转换为的base64编码)
|
||||
|
||||
表单:
|
||||
grant_type:authorization_code
|
||||
scope:all
|
||||
code:VhYNLR
|
||||
redirect_uri: http://example.com
|
||||
|
||||
二、 密码模式
|
||||
密码模式(password)主要针对自家应用,可信度较高,所以可以使用简便安全共存的模式,操作步骤如下
|
||||
1. 直接调用 http://localhost/blade-auth/oauth/token 传入对应的参数
|
||||
|
||||
请求头:
|
||||
Authorization : Basic YmxhZGU6YmxhZGU= ("YmxhZGU6YmxhZGU="为clientId:clientSecret串转换为的base64编码)
|
||||
|
||||
表单:
|
||||
grant_type:password
|
||||
scope:all
|
||||
username:admin
|
||||
password:123456
|
||||
|
||||
## 获取到token后如何获取用户信息
|
||||
1. 拼接请求头
|
||||
Authorization :bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoidGVzdCIsInVzZXJfbmFtZSI6ImFkbWluIiwic2NvcGUiOlsiYWxsIl0sImV4cCI6MTU1MzE2MTA5NSwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6IjE0YmMyYjAyLTgxY2UtNDFiNC04ZTI3LTA5YWE0ZmU4ZWMwYyIsImNsaWVudF9pZCI6ImJsYWRlIn0.jTmioQDq-fSNNn7YCwl3wP0JE-etSWtzLDe545mDbP4
|
||||
2. 调用 http://localhost/blade-auth/oauth/user-info 既可获得对应用户信息
|
|
@ -0,0 +1,169 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
<artifactId>security-manage</artifactId>
|
||||
<groupId>org.security</groupId>
|
||||
<version>2.8.1.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>security-auth</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>${bladex.project.version}</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.alipay.oceanbase</groupId>-->
|
||||
<!-- <artifactId>oceanbase-client</artifactId>-->
|
||||
<!-- <version>2.2.8.1</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.security</groupId>
|
||||
<artifactId>security-common</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.security</groupId>
|
||||
<artifactId>security-scope-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.security</groupId>
|
||||
<artifactId>security-desk-api</artifactId>
|
||||
<version>${bladex.project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-db</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.oracle.database.jdbc</groupId>
|
||||
<artifactId>ojdbc7</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>ojdbc7</artifactId>
|
||||
<groupId>com.oracle</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>1.1.22</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-cloud</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-metrics</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>druid</artifactId>
|
||||
<groupId>com.alibaba</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-swagger</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-social</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.security</groupId>
|
||||
<artifactId>security-user-api</artifactId>
|
||||
<version>${bladex.project.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>druid</artifactId>
|
||||
<groupId>com.alibaba</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.security</groupId>
|
||||
<artifactId>security-system-api</artifactId>
|
||||
<version>${bladex.project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.oauth</groupId>
|
||||
<artifactId>spring-security-oauth2</artifactId>
|
||||
<version>2.3.5.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<version>2.2.0.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-jwt</artifactId>
|
||||
</dependency>
|
||||
<!-- 验证码 -->
|
||||
<dependency>
|
||||
<groupId>com.github.whvcse</groupId>
|
||||
<artifactId>easy-captcha</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-secure</artifactId>
|
||||
</dependency>
|
||||
<!-- 链路追踪、服务监控 -->
|
||||
<!--<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-trace</artifactId>
|
||||
</dependency>-->
|
||||
<!-- 解决Java11无法运行的问题 -->
|
||||
<!--<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<version>2.2.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.xml.bind</groupId>
|
||||
<artifactId>jaxb-core</artifactId>
|
||||
<version>2.2.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.xml.bind</groupId>
|
||||
<artifactId>jaxb-impl</artifactId>
|
||||
<version>2.2.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
<version>1.1.1</version>
|
||||
</dependency>-->
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth;
|
||||
|
||||
|
||||
import org.security.common.constant.CommonConstant;
|
||||
import org.springblade.core.launch.BladeApplication;
|
||||
import org.springframework.cloud.client.SpringCloudApplication;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
/**
|
||||
* 用户认证服务器
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@EnableFeignClients("org.security")
|
||||
@SpringCloudApplication
|
||||
public class AuthApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
BladeApplication.run(CommonConstant.APPLICATION_AUTH_NAME, AuthApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.security.auth.granter.BladeTokenGranter;
|
||||
import org.security.auth.service.BladeClientDetailsServiceImpl;
|
||||
import org.security.auth.service.IXYunAuthService;
|
||||
import org.security.system.user.feign.IUserClient;
|
||||
import org.springblade.core.redis.cache.BladeRedis;
|
||||
import org.springblade.core.social.props.SocialProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
|
||||
import org.springframework.security.oauth2.provider.TokenGranter;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
|
||||
import org.springframework.security.oauth2.provider.token.TokenStore;
|
||||
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 认证服务器配置
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Order
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
@EnableAuthorizationServer
|
||||
public class BladeAuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
private final UserDetailsService userDetailsService;
|
||||
|
||||
private final TokenStore tokenStore;
|
||||
|
||||
private final TokenEnhancer jwtTokenEnhancer;
|
||||
|
||||
private final JwtAccessTokenConverter jwtAccessTokenConverter;
|
||||
|
||||
private final BladeRedis bladeRedis;
|
||||
|
||||
private final IUserClient userClient;
|
||||
|
||||
private final SocialProperties socialProperties;
|
||||
|
||||
private final XYunProperties xYunProperties;
|
||||
|
||||
private final IXYunAuthService xYunService;
|
||||
|
||||
@Override
|
||||
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
|
||||
//获取自定义tokenGranter
|
||||
TokenGranter tokenGranter = BladeTokenGranter.getTokenGranter(authenticationManager, endpoints, bladeRedis, userClient, socialProperties, xYunProperties, xYunService);
|
||||
|
||||
//配置端点
|
||||
endpoints.tokenStore(tokenStore)
|
||||
.authenticationManager(authenticationManager)
|
||||
.userDetailsService(userDetailsService)
|
||||
.tokenGranter(tokenGranter);
|
||||
|
||||
//扩展token返回结果
|
||||
if (jwtAccessTokenConverter != null && jwtTokenEnhancer != null) {
|
||||
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
|
||||
List<TokenEnhancer> enhancerList = new ArrayList<>();
|
||||
enhancerList.add(jwtTokenEnhancer);
|
||||
enhancerList.add(jwtAccessTokenConverter);
|
||||
tokenEnhancerChain.setTokenEnhancers(enhancerList);
|
||||
//jwt增强
|
||||
endpoints.tokenEnhancer(tokenEnhancerChain).accessTokenConverter(jwtAccessTokenConverter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置客户端信息
|
||||
*/
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void configure(ClientDetailsServiceConfigurer clients) {
|
||||
BladeClientDetailsServiceImpl clientDetailsService = new BladeClientDetailsServiceImpl(dataSource);
|
||||
clients.withClientDetails(clientDetailsService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
|
||||
oauthServer
|
||||
.allowFormAuthenticationForClients()
|
||||
.tokenKeyAccess("permitAll()")
|
||||
.checkTokenAccess("isAuthenticated()");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
|
||||
/**
|
||||
* 自定义登录成功配置
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
@EnableResourceServer
|
||||
public class BladeResourceServerConfiguration extends ResourceServerConfigurerAdapter {
|
||||
|
||||
/**
|
||||
* 自定义登录成功处理器
|
||||
*/
|
||||
private final AuthenticationSuccessHandler appLoginInSuccessHandler;
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void configure(HttpSecurity http) {
|
||||
http.headers().frameOptions().disable();
|
||||
http.formLogin()
|
||||
.successHandler(appLoginInSuccessHandler)
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.antMatchers(
|
||||
"/actuator/**",
|
||||
"/oauth/captcha",
|
||||
"/oauth/logout",
|
||||
"/oauth/clear-cache",
|
||||
"/oauth/render/**",
|
||||
"/oauth/callback/**",
|
||||
"/oauth/revoke/**",
|
||||
"/oauth/refresh/**",
|
||||
"/token/**",
|
||||
"/mobile/**",
|
||||
"/app/auth",
|
||||
"/v2/api-docs").permitAll()
|
||||
.anyRequest().authenticated().and()
|
||||
.csrf().disable();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.config;
|
||||
|
||||
import org.security.auth.support.BladeJwtTokenEnhancer;
|
||||
import org.springblade.core.jwt.props.JwtProperties;
|
||||
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.Configuration;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
||||
import org.springframework.security.oauth2.provider.token.TokenStore;
|
||||
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
|
||||
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
|
||||
|
||||
/**
|
||||
* JwtTokenStore
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "blade.security.oauth2", name = "storeType", havingValue = "jwt", matchIfMissing = true)
|
||||
public class JwtTokenStoreConfiguration {
|
||||
|
||||
/**
|
||||
* 使用jwtTokenStore存储token
|
||||
*/
|
||||
@Bean
|
||||
public TokenStore jwtTokenStore(JwtProperties jwtProperties) {
|
||||
return new JwtTokenStore(jwtAccessTokenConverter(jwtProperties));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于生成jwt
|
||||
*/
|
||||
@Bean
|
||||
public JwtAccessTokenConverter jwtAccessTokenConverter(JwtProperties jwtProperties) {
|
||||
JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
|
||||
accessTokenConverter.setSigningKey(jwtProperties.getSignKey());
|
||||
return accessTokenConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于扩展jwt
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = "jwtTokenEnhancer")
|
||||
public TokenEnhancer jwtTokenEnhancer(JwtAccessTokenConverter jwtAccessTokenConverter, JwtProperties jwtProperties) {
|
||||
return new BladeJwtTokenEnhancer(jwtAccessTokenConverter, jwtProperties);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.security.auth.support.BladePasswordEncoderFactories;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
/**
|
||||
* Security配置
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public AuthenticationManager authenticationManagerBean() {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return BladePasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
protected void configure(HttpSecurity http) {
|
||||
http.httpBasic().and().csrf().disable();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.security.auth.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "xyun")
|
||||
@Data
|
||||
public class XYunProperties {
|
||||
private String appId;
|
||||
private String appSecret;
|
||||
private String pubId;
|
||||
private String pubSecret;
|
||||
private String url;
|
||||
private String eId;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.constant;
|
||||
|
||||
/**
|
||||
* 授权校验常量
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public interface AuthConstant {
|
||||
|
||||
/**
|
||||
* 密码加密规则
|
||||
*/
|
||||
String ENCRYPT = "{blade}";
|
||||
|
||||
/**
|
||||
* blade_client表字段
|
||||
*/
|
||||
String CLIENT_FIELDS = "client_id, CONCAT('{noop}',client_secret) as client_secret, resource_ids, scope, authorized_grant_types, " +
|
||||
"web_server_redirect_uri, authorities, access_token_validity, " +
|
||||
"refresh_token_validity, additional_information, autoapprove";
|
||||
|
||||
/**
|
||||
* blade_client查询语句
|
||||
*/
|
||||
String BASE_STATEMENT = "select " + CLIENT_FIELDS + " from blade_client";
|
||||
|
||||
/**
|
||||
* blade_client查询排序
|
||||
*/
|
||||
String DEFAULT_FIND_STATEMENT = BASE_STATEMENT + " order by client_id";
|
||||
|
||||
/**
|
||||
* 查询client_id
|
||||
*/
|
||||
String DEFAULT_SELECT_STATEMENT = BASE_STATEMENT + " where client_id = ?";
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package org.security.auth.endpoint;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.security.system.user.feign.IUserClient;
|
||||
import org.security.system.user.vo.UserVO;
|
||||
import org.springblade.core.launch.constant.TokenConstant;
|
||||
import org.springblade.core.secure.TokenInfo;
|
||||
import org.springblade.core.secure.utils.SecureUtil;
|
||||
import org.springblade.core.tenant.annotation.NonDS;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author zj 2022/9/5
|
||||
*/
|
||||
@NonDS
|
||||
@Slf4j
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class AuthEndPoint {
|
||||
private final IUserClient iUserClient;
|
||||
|
||||
/**
|
||||
* app用户验证生成token
|
||||
*
|
||||
* @param code 工号
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/app/auth")
|
||||
public R appAuth(String code) {
|
||||
R<UserVO> userResult = iUserClient.getUserByCode(code);
|
||||
UserVO userVO = userResult.getData();
|
||||
if (!userResult.isSuccess() || Objects.isNull(userVO)) {
|
||||
return R.fail("用户未在安防系统注册");
|
||||
}
|
||||
TokenInfo jwt = SecureUtil.createJWT(getAppTokenMap(userVO), "app", "security", "access_token");
|
||||
HashMap<String, String> res = new HashMap<>();
|
||||
res.put("code", userVO.getCode());
|
||||
res.put("userName", userVO.getRealName());
|
||||
res.put("token", jwt.getToken());
|
||||
return R.data(res);
|
||||
}
|
||||
|
||||
private Map<String, Object> getAppTokenMap(UserVO userVO) {
|
||||
Map<String, Object> info = new HashMap<>(16);
|
||||
info.put(TokenConstant.CLIENT_ID, "app");
|
||||
info.put(TokenConstant.USER_ID, Func.toStr(userVO.getId()));
|
||||
info.put(TokenConstant.DEPT_ID, Func.toStr(userVO.getDeptId()));
|
||||
info.put(TokenConstant.POST_ID, Func.toStr(userVO.getPostId()));
|
||||
info.put(TokenConstant.ROLE_ID, Func.toStr(userVO.getRoleId()));
|
||||
info.put(TokenConstant.TENANT_ID, userVO.getTenantId());
|
||||
info.put(TokenConstant.OAUTH_ID, "");
|
||||
info.put(TokenConstant.ACCOUNT, userVO.getAccount());
|
||||
info.put(TokenConstant.USER_NAME, userVO.getRealName());
|
||||
info.put(TokenConstant.NICK_NAME, userVO.getName());
|
||||
info.put(TokenConstant.REAL_NAME, userVO.getRealName());
|
||||
info.put(TokenConstant.ROLE_NAME, userVO.getRoleName());
|
||||
info.put(TokenConstant.AVATAR, userVO.getAvatar());
|
||||
info.put(TokenConstant.DETAIL, "web");
|
||||
info.put(TokenConstant.LICENSE, "security");
|
||||
return info;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.endpoint;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||
import org.springblade.core.social.props.SocialProperties;
|
||||
import org.springblade.core.social.utils.SocialUtil;
|
||||
import org.springblade.core.tenant.annotation.NonDS;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* SocialEndpoint
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@NonDS
|
||||
@Slf4j
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@ConditionalOnProperty(value = "social.enabled", havingValue = "true")
|
||||
public class BladeSocialEndpoint {
|
||||
|
||||
private final SocialProperties socialProperties;
|
||||
|
||||
/**
|
||||
* 授权完毕跳转
|
||||
*/
|
||||
@RequestMapping("/oauth/render/{source}")
|
||||
public void renderAuth(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
|
||||
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
|
||||
String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
|
||||
response.sendRedirect(authorizeUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取认证信息
|
||||
*/
|
||||
@RequestMapping("/oauth/callback/{source}")
|
||||
public Object login(@PathVariable("source") String source, AuthCallback callback) {
|
||||
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
|
||||
return authRequest.login(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销授权
|
||||
*/
|
||||
@RequestMapping("/oauth/revoke/{source}/{token}")
|
||||
public Object revokeAuth(@PathVariable("source") String source, @PathVariable("token") String token) {
|
||||
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
|
||||
return authRequest.revoke(AuthToken.builder().accessToken(token).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 续期令牌
|
||||
*/
|
||||
@RequestMapping("/oauth/refresh/{source}")
|
||||
public Object refreshAuth(@PathVariable("source") String source, String token) {
|
||||
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
|
||||
return authRequest.refresh(AuthToken.builder().refreshToken(token).build());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.endpoint;
|
||||
|
||||
import com.wf.captcha.SpecCaptcha;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.security.common.cache.CacheNames;
|
||||
import org.springblade.core.cache.utils.CacheUtil;
|
||||
import org.springblade.core.jwt.JwtUtil;
|
||||
import org.springblade.core.jwt.props.JwtProperties;
|
||||
import org.springblade.core.launch.constant.TokenConstant;
|
||||
import org.springblade.core.redis.cache.BladeRedis;
|
||||
import org.springblade.core.secure.BladeUser;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tenant.annotation.NonDS;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import static org.springblade.core.cache.constant.CacheConstant.*;
|
||||
|
||||
/**
|
||||
* BladeEndPoint
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@NonDS
|
||||
@Slf4j
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class BladeTokenEndPoint {
|
||||
|
||||
private final BladeRedis bladeRedis;
|
||||
private final JwtProperties jwtProperties;
|
||||
|
||||
@GetMapping("/oauth/user-info")
|
||||
public R<Authentication> currentUser(Authentication authentication) {
|
||||
return R.data(authentication);
|
||||
}
|
||||
|
||||
@GetMapping("/oauth/captcha")
|
||||
public Kv captcha() {
|
||||
log.info("获取验证码");
|
||||
SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 5);
|
||||
String verCode = specCaptcha.text().toLowerCase();
|
||||
String key = StringUtil.randomUUID();
|
||||
// 存入redis并设置过期时间为30分钟
|
||||
bladeRedis.setEx(CacheNames.CAPTCHA_KEY + key, verCode, Duration.ofMinutes(30));
|
||||
// 将key和base64返回给前端
|
||||
return Kv.create().set("key", key).set("image", specCaptcha.toBase64());
|
||||
}
|
||||
|
||||
@GetMapping("/oauth/logout")
|
||||
public Kv logout() {
|
||||
BladeUser user = AuthUtil.getUser();
|
||||
if (user != null && jwtProperties.getState()) {
|
||||
String token = JwtUtil.getToken(WebUtil.getRequest().getHeader(TokenConstant.HEADER));
|
||||
JwtUtil.removeAccessToken(user.getTenantId(), String.valueOf(user.getUserId()), token);
|
||||
}
|
||||
return Kv.create().set("success", "true").set("msg", "success");
|
||||
}
|
||||
|
||||
@GetMapping("/oauth/clear-cache")
|
||||
public Kv clearCache() {
|
||||
CacheUtil.clear(BIZ_CACHE);
|
||||
CacheUtil.clear(USER_CACHE);
|
||||
CacheUtil.clear(DICT_CACHE);
|
||||
CacheUtil.clear(FLOW_CACHE);
|
||||
CacheUtil.clear(SYS_CACHE);
|
||||
CacheUtil.clear(PARAM_CACHE);
|
||||
CacheUtil.clear(RESOURCE_CACHE);
|
||||
CacheUtil.clear(MENU_CACHE);
|
||||
CacheUtil.clear(DICT_CACHE, Boolean.FALSE);
|
||||
CacheUtil.clear(MENU_CACHE, Boolean.FALSE);
|
||||
CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
|
||||
CacheUtil.clear(PARAM_CACHE, Boolean.FALSE);
|
||||
return Kv.create().set("success", "true").set("msg", "success");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.granter;
|
||||
|
||||
import org.security.auth.config.XYunProperties;
|
||||
import org.security.auth.service.IXYunAuthService;
|
||||
import org.security.system.user.feign.IUserClient;
|
||||
import org.springblade.core.redis.cache.BladeRedis;
|
||||
import org.springblade.core.social.props.SocialProperties;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
|
||||
import org.springframework.security.oauth2.provider.CompositeTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.TokenGranter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自定义拓展TokenGranter
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class BladeTokenGranter {
|
||||
|
||||
/**
|
||||
* 自定义tokenGranter
|
||||
*/
|
||||
public static TokenGranter getTokenGranter(
|
||||
final AuthenticationManager authenticationManager, final AuthorizationServerEndpointsConfigurer endpoints,
|
||||
BladeRedis bladeRedis, IUserClient userClient, SocialProperties socialProperties, XYunProperties xYunProperties,
|
||||
IXYunAuthService xYunService) {
|
||||
// 默认tokenGranter集合
|
||||
List<TokenGranter> granters = new ArrayList<>(Collections.singletonList(endpoints.getTokenGranter()));
|
||||
// 增加验证码模式
|
||||
granters.add(new CaptchaTokenGranter(authenticationManager, endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), bladeRedis));
|
||||
// 增加第三方登陆模式
|
||||
granters.add(new SocialTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), userClient, socialProperties));
|
||||
// 香云登陆模式
|
||||
granters.add(new XYunTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), userClient, xYunProperties, xYunService));
|
||||
//单点登录模式
|
||||
granters.add(new SingleSignOnTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), userClient));
|
||||
// 组合tokenGranter集合
|
||||
return new CompositeTokenGranter(granters);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package org.security.auth.granter;
|
||||
|
||||
import org.security.auth.utils.TokenUtil;
|
||||
import org.security.common.cache.CacheNames;
|
||||
import org.springblade.core.redis.cache.BladeRedis;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springframework.security.authentication.*;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
|
||||
import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException;
|
||||
import org.springframework.security.oauth2.provider.*;
|
||||
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 验证码TokenGranter
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class CaptchaTokenGranter extends AbstractTokenGranter {
|
||||
|
||||
private static final String GRANT_TYPE = "captcha";
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
private BladeRedis bladeRedis;
|
||||
|
||||
public CaptchaTokenGranter(AuthenticationManager authenticationManager,
|
||||
AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, BladeRedis bladeRedis) {
|
||||
this(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
|
||||
this.bladeRedis = bladeRedis;
|
||||
}
|
||||
|
||||
protected CaptchaTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices,
|
||||
ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) {
|
||||
super(tokenServices, clientDetailsService, requestFactory, grantType);
|
||||
this.authenticationManager = authenticationManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
// 增加验证码判断
|
||||
String key = request.getHeader(TokenUtil.CAPTCHA_HEADER_KEY);
|
||||
String code = request.getHeader(TokenUtil.CAPTCHA_HEADER_CODE);
|
||||
// 获取验证码
|
||||
String redisCode = bladeRedis.get(CacheNames.CAPTCHA_KEY + key);
|
||||
// 判断验证码
|
||||
if (code == null || !StringUtil.equalsIgnoreCase(redisCode, code)) {
|
||||
throw new UserDeniedAuthorizationException(TokenUtil.CAPTCHA_NOT_CORRECT);
|
||||
}
|
||||
|
||||
Map<String, String> parameters = new LinkedHashMap<String, String>(tokenRequest.getRequestParameters());
|
||||
String username = parameters.get("username");
|
||||
String password = parameters.get("password");
|
||||
// Protect from downstream leaks of password
|
||||
parameters.remove("password");
|
||||
|
||||
Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password);
|
||||
((AbstractAuthenticationToken) userAuth).setDetails(parameters);
|
||||
try {
|
||||
userAuth = authenticationManager.authenticate(userAuth);
|
||||
}
|
||||
catch (AccountStatusException | BadCredentialsException ase) {
|
||||
//covers expired, locked, disabled cases (mentioned in section 5.2, draft 31)
|
||||
throw new InvalidGrantException(ase.getMessage());
|
||||
}
|
||||
// If the username/password are wrong the spec says we should send 400/invalid grant
|
||||
|
||||
if (userAuth == null || !userAuth.isAuthenticated()) {
|
||||
throw new InvalidGrantException("Could not authenticate user: " + username);
|
||||
}
|
||||
|
||||
OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
|
||||
return new OAuth2Authentication(storedOAuth2Request, userAuth);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package org.security.auth.granter;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.security.auth.config.XYunProperties;
|
||||
import org.security.auth.constant.AuthConstant;
|
||||
import org.security.auth.service.BladeUserDetails;
|
||||
import org.security.auth.service.IXYunAuthService;
|
||||
import org.security.auth.utils.TokenUtil;
|
||||
import org.security.desk.xyun.res.AuthToken;
|
||||
import org.security.desk.xyun.res.AuthUser;
|
||||
import org.security.system.user.entity.User;
|
||||
import org.security.system.user.entity.UserInfo;
|
||||
import org.security.system.user.feign.IUserClient;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
|
||||
import org.springframework.security.oauth2.provider.*;
|
||||
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 单点登录
|
||||
*
|
||||
* @author wzf
|
||||
*/
|
||||
@Slf4j
|
||||
public class SingleSignOnTokenGranter extends AbstractTokenGranter {
|
||||
private static final String GRANT_TYPE = "singleSignOn";
|
||||
|
||||
private final IUserClient userClient;
|
||||
|
||||
|
||||
protected SingleSignOnTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService,
|
||||
OAuth2RequestFactory requestFactory, IUserClient userClient) {
|
||||
super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
|
||||
this.userClient = userClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
String tenantId = Func.toStr(request.getHeader(TokenUtil.TENANT_HEADER_KEY), TokenUtil.DEFAULT_TENANT_ID);
|
||||
Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
|
||||
String userCode = parameters.get("username");
|
||||
R<UserInfo> clientUser = userClient.userInfo(TokenUtil.DEFAULT_TENANT_ID, userCode);
|
||||
if (!clientUser.isSuccess() || null == clientUser.getData() || null == clientUser.getData().getUser()) {
|
||||
throw new InvalidGrantException("单点登录失败,获取平台用户信息失败,工号:" + userCode);
|
||||
}
|
||||
User user = clientUser.getData().getUser();
|
||||
log.info(">>>>>> 查询平台user成功:" + user.getId() + ";" + user.getName());
|
||||
BladeUserDetails bladeUserDetails = new BladeUserDetails(user.getId(), tenantId,
|
||||
clientUser.getData().getOauthId(), user.getName(), user.getRealName(), user.getDeptId(),
|
||||
user.getPostId(), user.getRoleId(), Func.join(clientUser.getData().getRoles()),
|
||||
Func.toStr(user.getAvatar(), TokenUtil.DEFAULT_AVATAR),
|
||||
user.getName(), AuthConstant.ENCRYPT + user.getPassword(), null, true, true,
|
||||
true, true,
|
||||
AuthorityUtils.commaSeparatedStringToAuthorityList(Func.join(clientUser.getData().getRoles())));
|
||||
log.info("-----------------开始组装认证数据,关闭密码校验-----------------");
|
||||
log.info("-----------------生成userAuth-----------------");
|
||||
Authentication userAuth = new UsernamePasswordAuthenticationToken(bladeUserDetails, null, bladeUserDetails.getAuthorities());
|
||||
log.info("-----------------setDetails-----------------");
|
||||
((AbstractAuthenticationToken) userAuth).setDetails(parameters);
|
||||
log.info("-----------------组装storedOAuth2Request-----------------");
|
||||
OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
|
||||
log.info("-----------------返回 OAuth2Authentication-----------------");
|
||||
return new OAuth2Authentication(storedOAuth2Request, userAuth);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.granter;
|
||||
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import org.security.auth.constant.AuthConstant;
|
||||
import org.security.auth.service.BladeUserDetails;
|
||||
import org.security.auth.utils.TokenUtil;
|
||||
import org.security.system.user.entity.User;
|
||||
import org.security.system.user.entity.UserInfo;
|
||||
import org.security.system.user.entity.UserOauth;
|
||||
import org.security.system.user.feign.IUserClient;
|
||||
import org.springblade.core.social.props.SocialProperties;
|
||||
import org.springblade.core.social.utils.SocialUtil;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
import org.springblade.core.tool.utils.BeanUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
|
||||
import org.springframework.security.oauth2.provider.*;
|
||||
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 第三方登录认证类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class SocialTokenGranter extends AbstractTokenGranter {
|
||||
private static final String GRANT_TYPE = "social";
|
||||
private static final Integer AUTH_SUCCESS_CODE = 2000;
|
||||
|
||||
private final IUserClient userClient;
|
||||
private final SocialProperties socialProperties;
|
||||
|
||||
protected SocialTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, IUserClient userClient, SocialProperties socialProperties) {
|
||||
super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
|
||||
this.userClient = userClient;
|
||||
this.socialProperties = socialProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
|
||||
// 请求头租户信息
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
String tenantId = Func.toStr(request.getHeader(TokenUtil.TENANT_HEADER_KEY), TokenUtil.DEFAULT_TENANT_ID);
|
||||
|
||||
Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
|
||||
// 开放平台来源
|
||||
String sourceParameter = parameters.get("source");
|
||||
// 匹配是否有别名定义
|
||||
String source = socialProperties.getAlias().getOrDefault(sourceParameter, sourceParameter);
|
||||
// 开放平台授权码
|
||||
String code = parameters.get("code");
|
||||
// 开放平台状态吗
|
||||
String state = parameters.get("state");
|
||||
|
||||
// 获取开放平台授权数据
|
||||
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
|
||||
AuthCallback authCallback = new AuthCallback();
|
||||
authCallback.setCode(code);
|
||||
authCallback.setState(state);
|
||||
AuthResponse authResponse = authRequest.login(authCallback);
|
||||
AuthUser authUser;
|
||||
if (authResponse.getCode() == AUTH_SUCCESS_CODE) {
|
||||
authUser = (AuthUser) authResponse.getData();
|
||||
} else {
|
||||
throw new InvalidGrantException("social grant failure, auth response is not success");
|
||||
}
|
||||
|
||||
// 组装数据
|
||||
UserOauth userOauth = Objects.requireNonNull(BeanUtil.copy(authUser, UserOauth.class));
|
||||
userOauth.setSource(authUser.getSource());
|
||||
userOauth.setTenantId(tenantId);
|
||||
userOauth.setUuid(authUser.getUuid());
|
||||
|
||||
// 远程调用,获取认证信息
|
||||
R<UserInfo> result = userClient.userAuthInfo(userOauth);
|
||||
BladeUserDetails bladeUserDetails;
|
||||
if (result.isSuccess()) {
|
||||
User user = result.getData().getUser();
|
||||
Kv detail = result.getData().getDetail();
|
||||
if (user == null) {
|
||||
throw new InvalidGrantException("social grant failure, user is null");
|
||||
}
|
||||
bladeUserDetails = new BladeUserDetails(user.getId(),
|
||||
tenantId, result.getData().getOauthId(), user.getName(), user.getRealName(), user.getDeptId(), user.getPostId(), user.getRoleId(), Func.join(result.getData().getRoles()), Func.toStr(userOauth.getAvatar(), TokenUtil.DEFAULT_AVATAR),
|
||||
userOauth.getUsername(), AuthConstant.ENCRYPT + user.getPassword(), detail, true, true, true, true,
|
||||
AuthorityUtils.commaSeparatedStringToAuthorityList(Func.join(result.getData().getRoles())));
|
||||
} else {
|
||||
throw new InvalidGrantException("social grant failure, feign client return error");
|
||||
}
|
||||
|
||||
// 组装认证数据,关闭密码校验
|
||||
Authentication userAuth = new UsernamePasswordAuthenticationToken(bladeUserDetails, null, bladeUserDetails.getAuthorities());
|
||||
((AbstractAuthenticationToken) userAuth).setDetails(parameters);
|
||||
OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
|
||||
|
||||
// 返回 OAuth2Authentication
|
||||
return new OAuth2Authentication(storedOAuth2Request, userAuth);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package org.security.auth.granter;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.security.auth.config.XYunProperties;
|
||||
import org.security.auth.constant.AuthConstant;
|
||||
import org.security.auth.service.BladeUserDetails;
|
||||
import org.security.auth.service.IXYunAuthService;
|
||||
import org.security.auth.utils.TokenUtil;
|
||||
import org.security.system.user.entity.User;
|
||||
import org.security.system.user.entity.UserInfo;
|
||||
import org.security.system.user.feign.IUserClient;
|
||||
import org.security.desk.xyun.res.AuthToken;
|
||||
import org.security.desk.xyun.res.AuthUser;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
|
||||
import org.springframework.security.oauth2.provider.*;
|
||||
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 第三方登录认证类
|
||||
*
|
||||
* @author Arlex
|
||||
*/
|
||||
@Slf4j
|
||||
public class XYunTokenGranter extends AbstractTokenGranter {
|
||||
private static final String GRANT_TYPE = "xyun";
|
||||
|
||||
private final IUserClient userClient;
|
||||
private final XYunProperties xYunProperties;
|
||||
private final IXYunAuthService xYunService;
|
||||
|
||||
protected XYunTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService,
|
||||
OAuth2RequestFactory requestFactory, IUserClient userClient, XYunProperties xYunProperties,
|
||||
IXYunAuthService xYunService) {
|
||||
super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
|
||||
this.userClient = userClient;
|
||||
this.xYunProperties = xYunProperties;
|
||||
this.xYunService = xYunService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
|
||||
log.info(">>>>>> 香云端认证开始;appId:" + xYunProperties.getAppId() + "secret:" + xYunProperties.getAppSecret());
|
||||
// 请求头租户信息
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
String tenantId = Func.toStr(request.getHeader(TokenUtil.TENANT_HEADER_KEY), TokenUtil.DEFAULT_TENANT_ID);
|
||||
Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
|
||||
String ticket = parameters.get("ticket");
|
||||
log.info(">>>>>> 当前ticket:" + ticket);
|
||||
if (null == ticket) {
|
||||
throw new InvalidGrantException("香云登录失败,ticket为空!");
|
||||
}
|
||||
R<AuthToken> tokenRes = xYunService.getAccessToken();
|
||||
if (!tokenRes.isSuccess()) {
|
||||
throw new InvalidGrantException(tokenRes.getMsg());
|
||||
}
|
||||
|
||||
R<AuthUser> userRes = xYunService.getUserInfo(ticket, tokenRes.getData().getAccessToken());
|
||||
if (!userRes.isSuccess()) {
|
||||
throw new InvalidGrantException("香云登录失败,错误信息:" + userRes.getMsg());
|
||||
}
|
||||
AuthUser authUser = userRes.getData();
|
||||
log.info(">>>>>> 获得香云user成功:" + authUser.toString());
|
||||
|
||||
R<UserInfo> clientUser = userClient.userInfo(TokenUtil.DEFAULT_TENANT_ID, authUser.getJobNo());
|
||||
if (!clientUser.isSuccess() || null == clientUser.getData() || null == clientUser.getData().getUser()) {
|
||||
throw new InvalidGrantException("香云登录失败,获取平台用户信息失败,工号:" + authUser.getJobNo());
|
||||
}
|
||||
User user = clientUser.getData().getUser();
|
||||
log.info(">>>>>> 查询平台user成功:" + user.getId() + ";" + user.getName());
|
||||
Kv detail = clientUser.getData().getDetail();
|
||||
detail.set("xYunAccessToken", tokenRes.getData().getAccessToken());
|
||||
detail.set("xYunRefreshToken", tokenRes.getData().getRefreshToken());
|
||||
BladeUserDetails bladeUserDetails = new BladeUserDetails(user.getId(), tenantId,
|
||||
clientUser.getData().getOauthId(), user.getName(), user.getRealName(), user.getDeptId(),
|
||||
user.getPostId(), user.getRoleId(), Func.join(clientUser.getData().getRoles()),
|
||||
Func.toStr(user.getAvatar(), TokenUtil.DEFAULT_AVATAR),
|
||||
user.getName(), authUser.getJobNo(), AuthConstant.ENCRYPT + user.getPassword(), detail, true, true,
|
||||
true, true,
|
||||
AuthorityUtils.commaSeparatedStringToAuthorityList(Func.join(clientUser.getData().getRoles())));
|
||||
|
||||
log.info(">>>>>> 开始组装认证数据,关闭密码校验");
|
||||
log.info(">>>>>> 生成userAuth");
|
||||
Authentication userAuth = new UsernamePasswordAuthenticationToken(bladeUserDetails, null, bladeUserDetails.getAuthorities());
|
||||
log.info(">>>>>> setDetails");
|
||||
((AbstractAuthenticationToken) userAuth).setDetails(parameters);
|
||||
log.info(">>>>>> 组装storedOAuth2Request");
|
||||
OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
|
||||
log.info(">>>>>> 开始组装认证数据,关闭密码校验");
|
||||
|
||||
return new OAuth2Authentication(storedOAuth2Request, userAuth);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.handler;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.security.auth.utils.TokenUtil;
|
||||
import org.springblade.core.tool.jackson.JsonUtil;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
|
||||
import org.springframework.security.oauth2.provider.*;
|
||||
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* APP登录成功处理器
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@Component("appLoginInSuccessHandler")
|
||||
public class AppLoginInSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
|
||||
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
private final ClientDetailsService clientDetailsService;
|
||||
|
||||
private final AuthorizationServerTokenServices authorizationServerTokenServices;
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
|
||||
log.info("【AppLoginInSuccessHandler】 onAuthenticationSuccess authentication={}", authentication);
|
||||
|
||||
String[] tokens = TokenUtil.extractAndDecodeHeader();
|
||||
if (tokens.length != 2) {
|
||||
throw new UnapprovedClientAuthenticationException("client对应的配置信息不存在");
|
||||
}
|
||||
String clientId = tokens[0];
|
||||
String clientSecret = tokens[1];
|
||||
|
||||
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
|
||||
if (clientDetails == null) {
|
||||
throw new UnapprovedClientAuthenticationException("clientId 对应的配置信息不存在" + clientId);
|
||||
} else if (!passwordEncoder.matches(clientSecret, clientDetails.getClientSecret())) {
|
||||
throw new UnapprovedClientAuthenticationException("clientSecret 不匹配" + clientId);
|
||||
}
|
||||
|
||||
TokenRequest tokenRequest = new TokenRequest(new HashMap<>(16), clientId, clientDetails.getScope(), "app");
|
||||
OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
|
||||
OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
|
||||
OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
|
||||
|
||||
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
|
||||
response.getWriter().write(JsonUtil.toJson(token));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.service;
|
||||
|
||||
import org.security.auth.constant.AuthConstant;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* 客户端信息
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Component
|
||||
public class BladeClientDetailsServiceImpl extends JdbcClientDetailsService {
|
||||
|
||||
public BladeClientDetailsServiceImpl(DataSource dataSource) {
|
||||
super(dataSource);
|
||||
setSelectClientDetailsSql(AuthConstant.DEFAULT_SELECT_STATEMENT);
|
||||
setFindClientDetailsSql(AuthConstant.DEFAULT_FIND_STATEMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存客户端信息
|
||||
*
|
||||
* @param clientId 客户端id
|
||||
*/
|
||||
@Override
|
||||
public ClientDetails loadClientByClientId(String clientId) {
|
||||
try {
|
||||
return super.loadClientByClientId(clientId);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.service;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 用户信息拓展
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Getter
|
||||
public class BladeUserDetails extends User {
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private final Long userId;
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
private final String tenantId;
|
||||
/**
|
||||
* 第三方认证ID
|
||||
*/
|
||||
private final String oauthId;
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
private final String name;
|
||||
/**
|
||||
* 真名
|
||||
*/
|
||||
private final String realName;
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
private final String account;
|
||||
/**
|
||||
* 部门id
|
||||
*/
|
||||
private final String deptId;
|
||||
/**
|
||||
* 岗位id
|
||||
*/
|
||||
private final String postId;
|
||||
/**
|
||||
* 角色id
|
||||
*/
|
||||
private final String roleId;
|
||||
/**
|
||||
* 角色名
|
||||
*/
|
||||
private final String roleName;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private final String avatar;
|
||||
/**
|
||||
* 用户详情
|
||||
*/
|
||||
private final Kv detail;
|
||||
|
||||
public BladeUserDetails(Long userId, String tenantId, String oauthId, String name, String realName, String deptId, String postId, String roleId, String roleName, String avatar, String username, String password, Kv detail, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
|
||||
this.userId = userId;
|
||||
this.tenantId = tenantId;
|
||||
this.oauthId = oauthId;
|
||||
this.name = name;
|
||||
this.realName = realName;
|
||||
this.account = username;
|
||||
this.deptId = deptId;
|
||||
this.postId = postId;
|
||||
this.roleId = roleId;
|
||||
this.roleName = roleName;
|
||||
this.avatar = avatar;
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
public BladeUserDetails(Long userId, String tenantId, String oauthId, String name, String realName, String deptId, String postId, String roleId, String roleName, String avatar, String username, String account, String password, Kv detail, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
|
||||
this.userId = userId;
|
||||
this.tenantId = tenantId;
|
||||
this.oauthId = oauthId;
|
||||
this.name = name;
|
||||
this.realName = realName;
|
||||
this.account = account;
|
||||
this.deptId = deptId;
|
||||
this.postId = postId;
|
||||
this.roleId = roleId;
|
||||
this.roleName = roleName;
|
||||
this.avatar = avatar;
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.security.auth.constant.AuthConstant;
|
||||
import org.security.auth.utils.TokenUtil;
|
||||
import org.security.system.entity.Tenant;
|
||||
import org.security.system.feign.ISysClient;
|
||||
import org.security.system.user.entity.User;
|
||||
import org.security.system.user.entity.UserInfo;
|
||||
import org.security.system.user.enums.UserEnum;
|
||||
import org.security.system.user.feign.IUserClient;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringPool;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class BladeUserDetailsServiceImpl implements UserDetailsService {
|
||||
|
||||
private final IUserClient userClient;
|
||||
private final ISysClient sysClient;
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public BladeUserDetails loadUserByUsername(String username) {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
// 获取租户ID
|
||||
String headerTenant = request.getHeader(TokenUtil.TENANT_HEADER_KEY);
|
||||
String paramTenant = request.getParameter(TokenUtil.TENANT_PARAM_KEY);
|
||||
if (StringUtil.isAllBlank(headerTenant, paramTenant)) {
|
||||
throw new UserDeniedAuthorizationException(TokenUtil.TENANT_NOT_FOUND);
|
||||
}
|
||||
String tenantId = StringUtils.isBlank(headerTenant) ? paramTenant : headerTenant;
|
||||
|
||||
// 获取租户信息
|
||||
R<Tenant> tenant = sysClient.getTenant(tenantId);
|
||||
if (tenant.isSuccess()) {
|
||||
if (TokenUtil.judgeTenant(tenant.getData())) {
|
||||
throw new UserDeniedAuthorizationException(TokenUtil.USER_HAS_NO_TENANT_PERMISSION);
|
||||
}
|
||||
} else {
|
||||
throw new UserDeniedAuthorizationException(TokenUtil.USER_HAS_NO_TENANT);
|
||||
}
|
||||
|
||||
// 获取用户类型
|
||||
String userType = Func.toStr(request.getHeader(TokenUtil.USER_TYPE_HEADER_KEY), TokenUtil.DEFAULT_USER_TYPE);
|
||||
|
||||
// 远程调用返回数据
|
||||
R<UserInfo> result;
|
||||
// 根据不同用户类型调用对应的接口返回数据,用户可自行拓展
|
||||
if (userType.equals(UserEnum.WEB.getName())) {
|
||||
result = userClient.userInfo(tenantId, username, UserEnum.WEB.getName());
|
||||
} else if (userType.equals(UserEnum.APP.getName())) {
|
||||
result = userClient.userInfo(tenantId, username, UserEnum.APP.getName());
|
||||
} else {
|
||||
result = userClient.userInfo(tenantId, username, UserEnum.OTHER.getName());
|
||||
}
|
||||
|
||||
// 判断返回信息
|
||||
if (result.isSuccess()) {
|
||||
UserInfo userInfo = result.getData();
|
||||
User user = userInfo.getUser();
|
||||
if (user == null || user.getId() == null) {
|
||||
throw new UsernameNotFoundException(TokenUtil.USER_NOT_FOUND);
|
||||
}
|
||||
if (Func.isEmpty(userInfo.getRoles())) {
|
||||
throw new UserDeniedAuthorizationException(TokenUtil.USER_HAS_NO_ROLE);
|
||||
}
|
||||
return new BladeUserDetails(user.getId(),
|
||||
user.getTenantId(), StringPool.EMPTY, user.getName(), user.getRealName(), user.getDeptId(), user.getPostId(), user.getRoleId(), Func.join(result.getData().getRoles()), Func.toStr(user.getAvatar(), TokenUtil.DEFAULT_AVATAR),
|
||||
username, AuthConstant.ENCRYPT + user.getPassword(), userInfo.getDetail(), true, true, true, true,
|
||||
AuthorityUtils.commaSeparatedStringToAuthorityList(Func.join(result.getData().getRoles())));
|
||||
} else {
|
||||
throw new UsernameNotFoundException(result.getMsg());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package org.security.auth.service;
|
||||
|
||||
import org.security.desk.xyun.res.AuthToken;
|
||||
import org.security.desk.xyun.res.AuthUser;
|
||||
import org.springblade.core.tool.api.R;
|
||||
|
||||
public interface IXYunAuthService {
|
||||
R<AuthToken> getAccessToken();
|
||||
R<AuthUser> getUserInfo(String ticket, String accessToken);
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package org.security.auth.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.security.auth.config.XYunProperties;
|
||||
import org.security.common.constant.CommonConstant;
|
||||
import org.security.desk.xyun.res.AuthResponse;
|
||||
import org.security.desk.xyun.res.AuthToken;
|
||||
import org.security.desk.xyun.res.AuthUser;
|
||||
import org.springblade.core.redis.cache.BladeRedis;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.ResourceAccessException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class IXYunAuthServiceImpl implements IXYunAuthService {
|
||||
private final XYunProperties xYunProperties;
|
||||
private final BladeRedis bladeRedis;
|
||||
|
||||
@Override
|
||||
public R getAccessToken() {
|
||||
String redisToken = bladeRedis.get(CommonConstant.XYUN_ACCESSTOKEN_REDIS_KEY);
|
||||
if (!Func.isNull(redisToken) && !Func.isEmpty(redisToken)) {
|
||||
AuthToken authToken = new AuthToken();
|
||||
authToken.setAccessToken(redisToken);
|
||||
authToken.setRefreshToken(bladeRedis.get(CommonConstant.XYUN_REFRESHTOKEN_REDIS_KEY));
|
||||
return R.data(authToken);
|
||||
}
|
||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||
factory.setReadTimeout(10000);
|
||||
factory.setConnectTimeout(10000);
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
||||
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
|
||||
|
||||
HashMap<String, Object> tokenMap = new HashMap<>();
|
||||
tokenMap.put("appId", xYunProperties.getAppId());
|
||||
tokenMap.put("secret", xYunProperties.getAppSecret());
|
||||
tokenMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
||||
tokenMap.put("scope", "app");
|
||||
HttpEntity<HashMap<String, Object>> tokenHttpEntity = new HttpEntity<>(tokenMap, headers);
|
||||
ParameterizedTypeReference<AuthResponse<AuthToken>> tokenTypeRef =
|
||||
new ParameterizedTypeReference<AuthResponse<AuthToken>>() {
|
||||
};
|
||||
AuthResponse<AuthToken> tokenResponse;
|
||||
String tokenUrl = xYunProperties.getUrl() + "/gateway/oauth2/token/getAccessToken";
|
||||
log.info(">>>>>> 获取token url:" + tokenUrl);
|
||||
try {
|
||||
tokenResponse = template.exchange(tokenUrl, HttpMethod.POST, tokenHttpEntity, tokenTypeRef).getBody();
|
||||
} catch (ResourceAccessException e) {
|
||||
return R.fail("香云登录失败,获取accessToken超时,url:" + tokenUrl);
|
||||
}
|
||||
if (!tokenResponse.isSuccess()) {
|
||||
return R.fail("香云登录失败,香云获取token失败,错误码:" + tokenResponse.getErrorCode());
|
||||
}
|
||||
AuthToken authToken = tokenResponse.getData();
|
||||
bladeRedis.setEx(CommonConstant.XYUN_ACCESSTOKEN_REDIS_KEY, authToken.getAccessToken(), Duration.ofSeconds(authToken.getExpireIn()));
|
||||
bladeRedis.setEx(CommonConstant.XYUN_REFRESHTOKEN_REDIS_KEY, authToken.getRefreshToken(), Duration.ofSeconds(authToken.getExpireIn()));
|
||||
return R.data(authToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R getUserInfo(String ticket, String accessToken) {
|
||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||
factory.setReadTimeout(10000);
|
||||
factory.setConnectTimeout(10000);
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
||||
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
|
||||
HashMap<String, Object> userMap = new HashMap<>();
|
||||
userMap.put("appid", xYunProperties.getAppId());
|
||||
userMap.put("ticket", ticket);
|
||||
log.info(">>>>>> 获得香云accessToken成功:" + accessToken);
|
||||
HttpEntity<HashMap<String, Object>> userHttpEntity = new HttpEntity<>(userMap, headers);
|
||||
ParameterizedTypeReference<AuthResponse<AuthUser>> userTypeRef =
|
||||
new ParameterizedTypeReference<AuthResponse<AuthUser>>() {
|
||||
};
|
||||
AuthResponse<AuthUser> userResponse;
|
||||
String userUrl = xYunProperties.getUrl() + "/gateway/ticket/user/acquirecontext?accessToken=" + accessToken;
|
||||
log.info(">>>>>> 获取user url:" + userUrl);
|
||||
try {
|
||||
userResponse = template.exchange(userUrl, HttpMethod.POST, userHttpEntity, userTypeRef).getBody();
|
||||
} catch (ResourceAccessException e) {
|
||||
return R.fail("香云登录失败,获取用户信息超时,url:" + userUrl);
|
||||
}
|
||||
log.info(JSONObject.toJSONString(userResponse));
|
||||
if (!userResponse.isSuccess()) {
|
||||
return R.fail("香云登录失败,香云获取用户信息失败,错误码:"
|
||||
+ userResponse.getErrorCode() + "; " + userResponse.getError());
|
||||
}
|
||||
return R.data(userResponse.getData());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.support;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.security.auth.service.BladeUserDetails;
|
||||
import org.security.auth.utils.TokenUtil;
|
||||
import org.springblade.core.jwt.JwtUtil;
|
||||
import org.springblade.core.jwt.props.JwtProperties;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
||||
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* jwt返回参数增强
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class BladeJwtTokenEnhancer implements TokenEnhancer {
|
||||
|
||||
private final JwtAccessTokenConverter jwtAccessTokenConverter;
|
||||
private final JwtProperties jwtProperties;
|
||||
|
||||
@Override
|
||||
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
|
||||
BladeUserDetails principal = (BladeUserDetails) authentication.getUserAuthentication().getPrincipal();
|
||||
|
||||
//token参数增强
|
||||
Map<String, Object> info = new HashMap<>(16);
|
||||
info.put(TokenUtil.CLIENT_ID, TokenUtil.getClientIdFromHeader());
|
||||
info.put(TokenUtil.USER_ID, Func.toStr(principal.getUserId()));
|
||||
info.put(TokenUtil.DEPT_ID, Func.toStr(principal.getDeptId()));
|
||||
info.put(TokenUtil.POST_ID, Func.toStr(principal.getPostId()));
|
||||
info.put(TokenUtil.ROLE_ID, Func.toStr(principal.getRoleId()));
|
||||
info.put(TokenUtil.TENANT_ID, principal.getTenantId());
|
||||
info.put(TokenUtil.OAUTH_ID, principal.getOauthId());
|
||||
info.put(TokenUtil.ACCOUNT, principal.getAccount());
|
||||
info.put(TokenUtil.USER_NAME, principal.getUsername());
|
||||
info.put(TokenUtil.NICK_NAME, principal.getName());
|
||||
info.put(TokenUtil.REAL_NAME, principal.getRealName());
|
||||
info.put(TokenUtil.ROLE_NAME, principal.getRoleName());
|
||||
info.put(TokenUtil.AVATAR, principal.getAvatar());
|
||||
info.put(TokenUtil.DETAIL, principal.getDetail());
|
||||
info.put(TokenUtil.LICENSE, TokenUtil.LICENSE_NAME);
|
||||
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);
|
||||
|
||||
//token状态设置
|
||||
if (jwtProperties.getState()) {
|
||||
OAuth2AccessToken oAuth2AccessToken = jwtAccessTokenConverter.enhance(accessToken, authentication);
|
||||
String tokenValue = oAuth2AccessToken.getValue();
|
||||
String tenantId = principal.getTenantId();
|
||||
String userId = Func.toStr(principal.getUserId());
|
||||
JwtUtil.addAccessToken(tenantId, userId, tokenValue, accessToken.getExpiresIn());
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.support;
|
||||
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
/**
|
||||
* 无密码加密
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class BladeNoOpPasswordEncoder implements PasswordEncoder {
|
||||
|
||||
@Override
|
||||
public String encode(CharSequence rawPassword) {
|
||||
return rawPassword.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
||||
return rawPassword.toString().equals(encodedPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singleton {@link BladeNoOpPasswordEncoder}.
|
||||
*/
|
||||
public static PasswordEncoder getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private static final PasswordEncoder INSTANCE = new BladeNoOpPasswordEncoder();
|
||||
|
||||
private BladeNoOpPasswordEncoder() {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.support;
|
||||
|
||||
import org.springblade.core.tool.utils.DigestUtil;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
/**
|
||||
* 自定义密码加密
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class BladePasswordEncoder implements PasswordEncoder {
|
||||
|
||||
@Override
|
||||
public String encode(CharSequence rawPassword) {
|
||||
return DigestUtil.hex((String) rawPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
||||
return encodedPassword.equals(encode(rawPassword));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
package org.security.auth.support;
|
||||
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
|
||||
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 自定义密码工厂
|
||||
*
|
||||
* @author Rob Winch, Chill
|
||||
* @since 5.0
|
||||
*/
|
||||
public class BladePasswordEncoderFactories {
|
||||
|
||||
/**
|
||||
* Creates a {@link DelegatingPasswordEncoder} with default mappings. Additional
|
||||
* mappings may be added and the encoding will be updated to conform with best
|
||||
* practices. However, due to the nature of {@link DelegatingPasswordEncoder} the
|
||||
* updates should not impact users. The mappings current are:
|
||||
*
|
||||
* <ul>
|
||||
* <li>blade - {@link BladePasswordEncoder} (sha1(md5("password")))</li>
|
||||
* <li>bcrypt - {@link BCryptPasswordEncoder} (Also used for encoding)</li>
|
||||
* <li>noop - {@link BladeNoOpPasswordEncoder}</li>
|
||||
* <li>pbkdf2 - {@link Pbkdf2PasswordEncoder}</li>
|
||||
* <li>scrypt - {@link SCryptPasswordEncoder}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return the {@link PasswordEncoder} to use
|
||||
*/
|
||||
public static PasswordEncoder createDelegatingPasswordEncoder() {
|
||||
String encodingId = "blade";
|
||||
Map<String, PasswordEncoder> encoders = new HashMap<>(16);
|
||||
encoders.put(encodingId, new BladePasswordEncoder());
|
||||
encoders.put("bcrypt", new BCryptPasswordEncoder());
|
||||
encoders.put("noop", BladeNoOpPasswordEncoder.getInstance());
|
||||
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
|
||||
encoders.put("scrypt", new SCryptPasswordEncoder());
|
||||
|
||||
return new DelegatingPasswordEncoder(encodingId, encoders);
|
||||
}
|
||||
|
||||
private BladePasswordEncoderFactories() {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.auth.utils;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.security.common.constant.TenantConstant;
|
||||
import org.security.system.entity.Tenant;
|
||||
import org.springblade.core.launch.constant.TokenConstant;
|
||||
import org.springblade.core.tenant.BladeTenantProperties;
|
||||
import org.springblade.core.tool.constant.BladeConstant;
|
||||
import org.springblade.core.tool.jackson.JsonUtil;
|
||||
import org.springblade.core.tool.utils.*;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
|
||||
import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 认证工具类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class TokenUtil {
|
||||
|
||||
public final static String AVATAR = TokenConstant.AVATAR;
|
||||
public final static String ACCOUNT = TokenConstant.ACCOUNT;
|
||||
public final static String USER_NAME = TokenConstant.USER_NAME;
|
||||
public final static String NICK_NAME = TokenConstant.NICK_NAME;
|
||||
public final static String REAL_NAME = TokenConstant.REAL_NAME;
|
||||
public final static String USER_ID = TokenConstant.USER_ID;
|
||||
public final static String DEPT_ID = TokenConstant.DEPT_ID;
|
||||
public final static String POST_ID = TokenConstant.POST_ID;
|
||||
public final static String ROLE_ID = TokenConstant.ROLE_ID;
|
||||
public final static String ROLE_NAME = TokenConstant.ROLE_NAME;
|
||||
public final static String TENANT_ID = TokenConstant.TENANT_ID;
|
||||
public final static String OAUTH_ID = TokenConstant.OAUTH_ID;
|
||||
public final static String CLIENT_ID = TokenConstant.CLIENT_ID;
|
||||
public final static String DETAIL = TokenConstant.DETAIL;
|
||||
public final static String LICENSE = TokenConstant.LICENSE;
|
||||
public final static String LICENSE_NAME = TokenConstant.LICENSE_NAME;
|
||||
|
||||
public final static String CAPTCHA_HEADER_KEY = "Captcha-Key";
|
||||
public final static String CAPTCHA_HEADER_CODE = "Captcha-Code";
|
||||
public final static String CAPTCHA_NOT_CORRECT = "验证码不正确";
|
||||
public final static String TENANT_HEADER_KEY = "Tenant-Id";
|
||||
public final static String TENANT_PARAM_KEY = "tenant_id";
|
||||
public final static String DEFAULT_TENANT_ID = "000000";
|
||||
public final static String TENANT_NOT_FOUND = "租户ID未找到";
|
||||
public final static String USER_TYPE_HEADER_KEY = "User-Type";
|
||||
public final static String DEFAULT_USER_TYPE = "web";
|
||||
public final static String USER_NOT_FOUND = "用户名或密码错误";
|
||||
public final static String USER_HAS_NO_ROLE = "未获得用户的角色信息";
|
||||
public final static String USER_HAS_NO_TENANT = "未获得用户的租户信息";
|
||||
public final static String USER_HAS_NO_TENANT_PERMISSION = "租户授权已过期,请联系管理员";
|
||||
public final static String HEADER_KEY = "Authorization";
|
||||
public final static String HEADER_PREFIX = "Basic ";
|
||||
public final static String DEFAULT_AVATAR = "";
|
||||
|
||||
private static BladeTenantProperties tenantProperties;
|
||||
|
||||
/**
|
||||
* 获取租户配置
|
||||
*
|
||||
* @return tenantProperties
|
||||
*/
|
||||
private static BladeTenantProperties getTenantProperties() {
|
||||
if (tenantProperties == null) {
|
||||
tenantProperties = SpringUtil.getBean(BladeTenantProperties.class);
|
||||
}
|
||||
return tenantProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static String[] extractAndDecodeHeader() {
|
||||
String header = WebUtil.getRequest().getHeader(TokenUtil.HEADER_KEY);
|
||||
if (header == null || !header.startsWith(TokenUtil.HEADER_PREFIX)) {
|
||||
throw new UnapprovedClientAuthenticationException("请求头中无client信息");
|
||||
}
|
||||
|
||||
byte[] base64Token = header.substring(6).getBytes(Charsets.UTF_8_NAME);
|
||||
|
||||
byte[] decoded;
|
||||
try {
|
||||
decoded = Base64.getDecoder().decode(base64Token);
|
||||
} catch (IllegalArgumentException var7) {
|
||||
throw new BadCredentialsException("Failed to decode basic authentication token");
|
||||
}
|
||||
|
||||
String token = new String(decoded, Charsets.UTF_8_NAME);
|
||||
int index = token.indexOf(StringPool.COLON);
|
||||
if (index == -1) {
|
||||
throw new BadCredentialsException("Invalid basic authentication token");
|
||||
} else {
|
||||
return new String[]{token.substring(0, index), token.substring(index + 1)};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求头中的客户端id
|
||||
*/
|
||||
public static String getClientIdFromHeader() {
|
||||
String[] tokens = extractAndDecodeHeader();
|
||||
return tokens[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token过期时间(次日凌晨3点)
|
||||
*
|
||||
* @return expire
|
||||
*/
|
||||
public static int getTokenValiditySecond() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||
cal.set(Calendar.HOUR_OF_DAY, 3);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
return (int) (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取refreshToken过期时间
|
||||
*
|
||||
* @return expire
|
||||
*/
|
||||
public static int getRefreshTokenValiditySeconds() {
|
||||
return 60 * 60 * 24 * 15;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断租户权限
|
||||
*
|
||||
* @param tenant 租户信息
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean judgeTenant(Tenant tenant) {
|
||||
if (tenant == null || tenant.getId() == null) {
|
||||
throw new UserDeniedAuthorizationException(TokenUtil.USER_HAS_NO_TENANT);
|
||||
}
|
||||
if (StringUtil.equalsIgnoreCase(tenant.getTenantId(), BladeConstant.ADMIN_TENANT_ID)) {
|
||||
return false;
|
||||
}
|
||||
Date expireTime = tenant.getExpireTime();
|
||||
if (getTenantProperties().getLicense()) {
|
||||
String licenseKey = tenant.getLicenseKey();
|
||||
String decrypt = DesUtil.decryptFormHex(licenseKey, TenantConstant.DES_KEY);
|
||||
expireTime = JsonUtil.parse(decrypt, Tenant.class).getExpireTime();
|
||||
}
|
||||
if (expireTime != null && expireTime.before(DateUtil.now())) {
|
||||
throw new UserDeniedAuthorizationException(TokenUtil.USER_HAS_NO_TENANT_PERMISSION);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
url: ${blade.datasource.dev.url}
|
||||
username: ${blade.datasource.dev.username}
|
||||
password: ${blade.datasource.dev.password}
|
||||
|
||||
#第三方登陆
|
||||
social:
|
||||
enabled: true
|
||||
domain: http://127.0.0.1:1888
|
||||
|
||||
xyun:
|
||||
app-id: 500000053
|
||||
app-secret: B6rbJdILa1VEO9fmn6zj
|
||||
url: http://197.52.23.10
|
||||
# 公共号id
|
||||
pub-id: XT-cb5053a4-3d00-47e7-a0c3-d0ac693305b7
|
||||
pub-secret: 812739e21bf781370bebec37146c38a8
|
||||
# 企业注册号eid
|
||||
e-id: 1556583279
|
|
@ -0,0 +1,21 @@
|
|||
#数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
url: ${blade.datasource.prod.url}
|
||||
username: ${blade.datasource.prod.username}
|
||||
password: ${blade.datasource.prod.password}
|
||||
|
||||
#第三方登陆
|
||||
social:
|
||||
enabled: true
|
||||
domain: http://127.0.0.1:1888
|
||||
|
||||
xyun:
|
||||
app-id: 500000145
|
||||
app-secret: pzWlUBKsGQZFgIRWwDvV
|
||||
url: http://im.ynhtbank.cn
|
||||
# 公共号id
|
||||
pub-id: XT-d5a6d607-3549-465a-8477-601fc366039d
|
||||
pub-secret: 7e37f7ef5653889013060bfaaa69ccf7
|
||||
# 企业注册号eid
|
||||
e-id: 15750331
|
|
@ -0,0 +1,22 @@
|
|||
#数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
url: ${blade.datasource.test.url}
|
||||
username: ${blade.datasource.test.username}
|
||||
password: ${blade.datasource.test.password}
|
||||
|
||||
#第三方登陆
|
||||
social:
|
||||
enabled: true
|
||||
domain: http://127.0.0.1:1888
|
||||
|
||||
|
||||
xyun:
|
||||
app-id: 500000053
|
||||
app-secret: B6rbJdILa1VEO9fmn6zj
|
||||
url: http://197.52.23.10
|
||||
# 公共号id
|
||||
pub-id: XT-cb5053a4-3d00-47e7-a0c3-d0ac693305b7
|
||||
pub-secret: 812739e21bf781370bebec37146c38a8
|
||||
# 企业注册号eid
|
||||
e-id: 1556583279
|
|
@ -0,0 +1,51 @@
|
|||
# 在使用Spring默认数据源Hikari的情况下配置以下配置项
|
||||
spring:
|
||||
datasource:
|
||||
hikari:
|
||||
# 自动提交从池中返回的连接
|
||||
auto-commit: true
|
||||
# 连接池中维护的最小空闲连接数
|
||||
minimum-idle: 10
|
||||
# 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
|
||||
maximum-pool-size: 60
|
||||
# 空闲连接超时时间,默认值600000(10分钟),大于等于max-lifetime且max-lifetime>0,会被重置为0;不等于0且小于10秒,会被重置为10秒。
|
||||
# 只有空闲连接数大于最大连接数且空闲时间超过该值,才会被释放
|
||||
idle-timeout: 30000
|
||||
# 连接最大存活时间.不等于0且小于30秒,会被重置为默认值30分钟.设置应该比mysql设置的超时时间短
|
||||
max-lifetime: 1800000
|
||||
# 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
|
||||
connection-timeout: 30000
|
||||
# 连接测试查询
|
||||
connection-test-query: select 1
|
||||
#connection-test-query: select 1 from dual
|
||||
|
||||
#swagger文档
|
||||
swagger:
|
||||
base-packages:
|
||||
- org.springblade
|
||||
- org.springframework.security.oauth2.provider.endpoint
|
||||
|
||||
#第三方登陆
|
||||
social:
|
||||
oauth:
|
||||
GITHUB:
|
||||
client-id: 233************
|
||||
client-secret: 233************************************
|
||||
redirect-uri: ${social.domain}/oauth/redirect/github
|
||||
GITEE:
|
||||
client-id: 233************
|
||||
client-secret: 233************************************
|
||||
redirect-uri: ${social.domain}/oauth/redirect/gitee
|
||||
WECHAT_OPEN:
|
||||
client-id: 233************
|
||||
client-secret: 233************************************
|
||||
redirect-uri: ${social.domain}/oauth/redirect/wechat
|
||||
QQ:
|
||||
client-id: 233************
|
||||
client-secret: 233************************************
|
||||
redirect-uri: ${social.domain}/oauth/redirect/qq
|
||||
DINGTALK:
|
||||
client-id: 233************
|
||||
client-secret: 233************************************
|
||||
redirect-uri: ${social.domain}/oauth/redirect/dingtalk
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<configuration>
|
||||
<property name="logdir" value="../logs/security-auth"/>
|
||||
<!-- 控制台输出日志 -->
|
||||
<!-- 彩色日志依赖的渲染类 -->
|
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
|
||||
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
|
||||
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
|
||||
<!-- 彩色日志格式 -->
|
||||
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||
<charset>utf8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
<!-- 按用户输出日志 -->
|
||||
<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
|
||||
<discriminator>
|
||||
<Key>txcode</Key>
|
||||
<DefaultValue>security-auth</DefaultValue>
|
||||
</discriminator>
|
||||
<sift>
|
||||
<appender name="FILE-${userid}" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<File>${logdir}/${txcode}.log</File>
|
||||
<Append>false</Append>
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} %msg%n</Pattern>
|
||||
</layout>
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<FileNamePattern>${logdir}/${txcode}.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
|
||||
<MaxHistory>20</MaxHistory>
|
||||
<maxFileSize>5MB</maxFileSize>
|
||||
<totalSizeCap>1024MB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
</sift>
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<includeCallerData>true</includeCallerData>
|
||||
<discardingThreshold>-1</discardingThreshold>
|
||||
<queueSize>1024</queueSize>
|
||||
<appender-ref ref="SIFT"/>
|
||||
</appender>
|
||||
|
||||
<!-- <logger name="dao" level="DEBUG"/>-->
|
||||
<!-- <logger name="net.sf.ehcache" level="INFO"/>-->
|
||||
<!-- <logger name="druid.sql" level="INFO"/>-->
|
||||
|
||||
|
||||
<!-- MyBatis log configure -->
|
||||
<logger name="com.apache.ibatis" level="INFO"/>
|
||||
<logger name="org.mybatis.spring" level="DEBUG"/>
|
||||
<logger name="java.sql.Connection" level="DEBUG"/>
|
||||
<logger name="java.sql.Statement" level="DEBUG"/>
|
||||
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
|
||||
|
||||
<!-- 减少部分debug日志 -->
|
||||
<logger name="druid.sql" level="INFO"/>
|
||||
<logger name="org.apache.shiro" level="INFO"/>
|
||||
<logger name="org.mybatis.spring" level="INFO"/>
|
||||
<logger name="org.springframework" level="INFO"/>
|
||||
<logger name="org.springframework.context" level="WARN"/>
|
||||
<logger name="org.springframework.beans" level="WARN"/>
|
||||
<logger name="com.baomidou.mybatisplus" level="INFO"/>
|
||||
<logger name="org.apache.ibatis.io" level="INFO"/>
|
||||
<logger name="org.apache.velocity" level="INFO"/>
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="io.undertow" level="INFO"/>
|
||||
<logger name="org.xnio.nio" level="INFO"/>
|
||||
<logger name="org.thymeleaf" level="INFO"/>
|
||||
<logger name="springfox.documentation" level="INFO"/>
|
||||
<logger name="org.hibernate.validator" level="INFO"/>
|
||||
<logger name="com.netflix.loadbalancer" level="INFO"/>
|
||||
<logger name="com.netflix.hystrix" level="INFO"/>
|
||||
<logger name="com.netflix.zuul" level="INFO"/>
|
||||
<logger name="de.codecentric" level="INFO"/>
|
||||
<!-- cache INFO -->
|
||||
<logger name="net.sf.ehcache" level="INFO"/>
|
||||
<logger name="org.springframework.cache" level="INFO"/>
|
||||
<!-- cloud -->
|
||||
<logger name="org.apache.http" level="INFO"/>
|
||||
<logger name="com.netflix.discovery" level="INFO"/>
|
||||
<logger name="com.netflix.eureka" level="INFO"/>
|
||||
<!-- 业务日志 -->
|
||||
<Logger name="org.security" level="DEBUG" />
|
||||
<Logger name="org.springblade.core.version" level="INFO"/>
|
||||
|
||||
<!-- 减少nacos日志 -->
|
||||
<logger name="com.alibaba.nacos" level="ERROR"/>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
<appender-ref ref="ASYNC"/>
|
||||
</root>
|
||||
</configuration>
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>security-manage</artifactId>
|
||||
<groupId>org.security</groupId>
|
||||
<version>2.8.1.RELEASE</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>security-common</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>${bladex.project.version}</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-launch</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-ribbon</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-auto</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.coobird</groupId>
|
||||
<artifactId>thumbnailator</artifactId>
|
||||
<version>0.4.8</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
<finalName>${project.name}</finalName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.common.cache;
|
||||
|
||||
/**
|
||||
* 缓存名
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public interface CacheNames {
|
||||
|
||||
String CAPTCHA_KEY = "blade:auth::blade:captcha:";
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.common.config;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 公共封装包配置类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
public class BladeCommonConfiguration {
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package org.security.common.config;
|
||||
|
||||
import feign.RequestInterceptor;
|
||||
import feign.RequestTemplate;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@Slf4j
|
||||
public class FeignClientRequestInterceptor implements RequestInterceptor {
|
||||
private final String AuthHeader = "blade-Auth";
|
||||
|
||||
@Override
|
||||
public void apply(RequestTemplate template) {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (null != attributes) {
|
||||
HttpServletRequest request = attributes.getRequest();
|
||||
if (null != request) {
|
||||
String bladeAuth = request.getHeader(AuthHeader);
|
||||
if (null != bladeAuth) {
|
||||
log.info("<<<<<< Add Header " + AuthHeader + ": " + bladeAuth);
|
||||
template.header(AuthHeader, bladeAuth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.common.constant;
|
||||
|
||||
/**
|
||||
* 通用常量
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public interface CommonConstant {
|
||||
|
||||
/**
|
||||
* 系统id
|
||||
*/
|
||||
String SYS_ID = "SIMS";
|
||||
/**
|
||||
* 人脸代码库
|
||||
*/
|
||||
String FACE_LIB_CODE = "sims001";;
|
||||
/**
|
||||
* 生物识别系统场景码
|
||||
*/
|
||||
String FACE_SCE_CODE = "3005";
|
||||
|
||||
String SEQ_NO = "seqNo";
|
||||
/**
|
||||
* sword 系统名
|
||||
*/
|
||||
String SWORD_NAME = "sword";
|
||||
|
||||
/**
|
||||
* saber 系统名
|
||||
*/
|
||||
String SABER_NAME = "saber";
|
||||
|
||||
/**
|
||||
* 顶级父节点id
|
||||
*/
|
||||
Long TOP_PARENT_ID = 0L;
|
||||
|
||||
/**
|
||||
* 顶级父节点名称
|
||||
*/
|
||||
String TOP_PARENT_NAME = "顶级";
|
||||
|
||||
/**
|
||||
* 未封存状态值
|
||||
*/
|
||||
Integer NOT_SEALED_ID = 0;
|
||||
|
||||
/**
|
||||
* 默认密码
|
||||
*/
|
||||
String DEFAULT_PASSWORD = "123456";
|
||||
|
||||
/**
|
||||
* 默认密码参数值
|
||||
*/
|
||||
String DEFAULT_PARAM_PASSWORD = "account.initPassword";
|
||||
|
||||
/**
|
||||
* 默认排序字段
|
||||
*/
|
||||
String SORT_FIELD = "sort";
|
||||
|
||||
/**
|
||||
* 数据权限类型
|
||||
*/
|
||||
Integer DATA_SCOPE_CATEGORY = 1;
|
||||
|
||||
/**
|
||||
* 接口权限类型
|
||||
*/
|
||||
Integer API_SCOPE_CATEGORY = 2;
|
||||
|
||||
String XYUN_ACCESSTOKEN_REDIS_KEY = "xYunAccessToken";
|
||||
String XYUN_REFRESHTOKEN_REDIS_KEY = "xYunRefreshToken";
|
||||
|
||||
String APPLICATION_AUTH_NAME = "security-auth";
|
||||
String APPLICATION_GATEWAY_NAME = "security-gateway";
|
||||
String APPLICATION_DEVELOP_NAME = "security-develop";
|
||||
String APPLICATION_FLOW_NAME = "security-flow";
|
||||
String APPLICATION_DESK_NAME = "security-desk";
|
||||
String APPLICATION_SYSTEM_NAME = "security-system";
|
||||
String APPLICATION_USER_NAME = "security-user";
|
||||
String APPLICATION_LOG_NAME = "security-log";
|
||||
String APPLICATION_FLOWDESIGN_NAME = "security-flow-design";
|
||||
String APPLICATION_SWAGGER_NAME = "security-swagger";
|
||||
String APPLICATION_SECURITY = "security-busi";
|
||||
}
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.common.constant;
|
||||
|
||||
|
||||
import org.springblade.core.launch.constant.AppConstant;
|
||||
|
||||
import static org.springblade.core.launch.constant.AppConstant.APPLICATION_NAME_PREFIX;
|
||||
|
||||
/**
|
||||
* 启动常量
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public interface LauncherConstant {
|
||||
|
||||
/**
|
||||
* xxljob
|
||||
*/
|
||||
String APPLICATION_XXLJOB_NAME = APPLICATION_NAME_PREFIX + "xxljob";
|
||||
|
||||
/**
|
||||
* xxljob
|
||||
*/
|
||||
String APPLICATION_XXLJOB_ADMIN_NAME = APPLICATION_NAME_PREFIX + "xxljob-admin";
|
||||
|
||||
/**
|
||||
* nacos dev 地址
|
||||
*/
|
||||
String NACOS_DEV_ADDR = "127.0.0.1:8848";
|
||||
|
||||
/**
|
||||
* nacos prod 地址
|
||||
*/
|
||||
String NACOS_PROD_ADDR = "127.0.0.1:8848";
|
||||
|
||||
/**
|
||||
* nacos test 地址
|
||||
*/
|
||||
String NACOS_TEST_ADDR = "127.0.0.1:8848";
|
||||
|
||||
/**
|
||||
* sentinel dev 地址
|
||||
*/
|
||||
String SENTINEL_DEV_ADDR = "47.108.70.243:8858";
|
||||
|
||||
/**
|
||||
* sentinel prod 地址
|
||||
*/
|
||||
String SENTINEL_PROD_ADDR = "172.30.0.58:8858";
|
||||
|
||||
/**
|
||||
* sentinel test 地址
|
||||
*/
|
||||
String SENTINEL_TEST_ADDR = "172.30.0.58:8858";
|
||||
|
||||
/**
|
||||
* seata dev 地址
|
||||
*/
|
||||
String SEATA_DEV_ADDR = "47.108.70.243:8091";
|
||||
|
||||
/**
|
||||
* seata prod 地址
|
||||
*/
|
||||
String SEATA_PROD_ADDR = "172.30.0.68:8091";
|
||||
|
||||
/**
|
||||
* seata test 地址
|
||||
*/
|
||||
String SEATA_TEST_ADDR = "172.30.0.68:8091";
|
||||
|
||||
/**
|
||||
* zipkin dev 地址
|
||||
*/
|
||||
String ZIPKIN_DEV_ADDR = "http://47.108.70.243:9411";
|
||||
|
||||
/**
|
||||
* zipkin prod 地址
|
||||
*/
|
||||
String ZIPKIN_PROD_ADDR = "http://172.30.0.71:9411";
|
||||
|
||||
/**
|
||||
* zipkin test 地址
|
||||
*/
|
||||
String ZIPKIN_TEST_ADDR = "http://172.30.0.71:9411";
|
||||
|
||||
/**
|
||||
* elk dev 地址
|
||||
*/
|
||||
String ELK_DEV_ADDR = "47.108.70.243:9000";
|
||||
|
||||
/**
|
||||
* elk prod 地址
|
||||
*/
|
||||
String ELK_PROD_ADDR = "172.30.0.72:9000";
|
||||
|
||||
/**
|
||||
* elk test 地址
|
||||
*/
|
||||
String ELK_TEST_ADDR = "172.30.0.72:9000";
|
||||
|
||||
/**
|
||||
* seata file模式
|
||||
*/
|
||||
String FILE_MODE = "file";
|
||||
|
||||
/**
|
||||
* seata nacos模式
|
||||
*/
|
||||
String NACOS_MODE = "nacos";
|
||||
|
||||
/**
|
||||
* seata default模式
|
||||
*/
|
||||
String DEFAULT_MODE = "default";
|
||||
|
||||
/**
|
||||
* seata group后缀
|
||||
*/
|
||||
String GROUP_NAME = "-group";
|
||||
|
||||
/**
|
||||
* seata 服务组格式
|
||||
*
|
||||
* @param appName 服务名
|
||||
* @return group
|
||||
*/
|
||||
static String seataServiceGroup(String appName) {
|
||||
return appName.concat(GROUP_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态获取nacos地址
|
||||
*
|
||||
* @param profile 环境变量
|
||||
* @return addr
|
||||
*/
|
||||
static String nacosAddr(String profile) {
|
||||
switch (profile) {
|
||||
case (AppConstant.PROD_CODE):
|
||||
return NACOS_PROD_ADDR;
|
||||
case (AppConstant.TEST_CODE):
|
||||
return NACOS_TEST_ADDR;
|
||||
default:
|
||||
return NACOS_DEV_ADDR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态获取sentinel地址
|
||||
*
|
||||
* @param profile 环境变量
|
||||
* @return addr
|
||||
*/
|
||||
static String sentinelAddr(String profile) {
|
||||
switch (profile) {
|
||||
case (AppConstant.PROD_CODE):
|
||||
return SENTINEL_PROD_ADDR;
|
||||
case (AppConstant.TEST_CODE):
|
||||
return SENTINEL_TEST_ADDR;
|
||||
default:
|
||||
return SENTINEL_DEV_ADDR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态获取seata地址
|
||||
*
|
||||
* @param profile 环境变量
|
||||
* @return addr
|
||||
*/
|
||||
static String seataAddr(String profile) {
|
||||
switch (profile) {
|
||||
case (AppConstant.PROD_CODE):
|
||||
return SEATA_PROD_ADDR;
|
||||
case (AppConstant.TEST_CODE):
|
||||
return SEATA_TEST_ADDR;
|
||||
default:
|
||||
return SEATA_DEV_ADDR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态获取zipkin地址
|
||||
*
|
||||
* @param profile 环境变量
|
||||
* @return addr
|
||||
*/
|
||||
static String zipkinAddr(String profile) {
|
||||
switch (profile) {
|
||||
case (AppConstant.PROD_CODE):
|
||||
return ZIPKIN_PROD_ADDR;
|
||||
case (AppConstant.TEST_CODE):
|
||||
return ZIPKIN_TEST_ADDR;
|
||||
default:
|
||||
return ZIPKIN_DEV_ADDR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态获取elk地址
|
||||
*
|
||||
* @param profile 环境变量
|
||||
* @return addr
|
||||
*/
|
||||
static String elkAddr(String profile) {
|
||||
switch (profile) {
|
||||
case (AppConstant.PROD_CODE):
|
||||
return ELK_PROD_ADDR;
|
||||
case (AppConstant.TEST_CODE):
|
||||
return ELK_TEST_ADDR;
|
||||
default:
|
||||
return ELK_DEV_ADDR;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.common.constant;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 租户常量
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public interface TenantConstant {
|
||||
|
||||
/**
|
||||
* 租户默认密码KEY
|
||||
*/
|
||||
String PASSWORD_KEY = "tenant.default.password";
|
||||
|
||||
/**
|
||||
* 租户默认账号额度KEY
|
||||
*/
|
||||
String ACCOUNT_NUMBER_KEY = "tenant.default.accountNumber";
|
||||
|
||||
/**
|
||||
* 租户默认菜单集合KEY
|
||||
*/
|
||||
String ACCOUNT_MENU_CODE_KEY = "tenant.default.menuCode";
|
||||
|
||||
/**
|
||||
* 租户默认密码
|
||||
*/
|
||||
String DEFAULT_PASSWORD = "123456";
|
||||
|
||||
/**
|
||||
* 租户授权码默认16位密钥
|
||||
*/
|
||||
String DES_KEY = "0000000000000000";
|
||||
|
||||
/**
|
||||
* 租户默认账号额度
|
||||
*/
|
||||
Integer DEFAULT_ACCOUNT_NUMBER = -1;
|
||||
|
||||
/**
|
||||
* 租户默认菜单集合
|
||||
*/
|
||||
List<String> MENU_CODES = Arrays.asList(
|
||||
"desk", "flow", "work", "monitor", "resource", "role", "user", "dept", "dictbiz", "topmenu"
|
||||
);
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.common.launch;
|
||||
|
||||
import org.security.common.constant.LauncherConstant;
|
||||
import org.springblade.core.auto.service.AutoService;
|
||||
import org.springblade.core.launch.service.LauncherService;
|
||||
import org.springblade.core.launch.utils.PropsUtil;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 启动参数拓展
|
||||
*
|
||||
* @author smallchil
|
||||
*/
|
||||
@AutoService(LauncherService.class)
|
||||
public class LauncherServiceImpl implements LauncherService {
|
||||
|
||||
@Override
|
||||
public void launcher(SpringApplicationBuilder builder, String appName, String profile, boolean isLocalDev) {
|
||||
Properties props = System.getProperties();
|
||||
// 通用注册
|
||||
PropsUtil.setProperty(props, "spring.cloud.nacos.discovery.server-addr", LauncherConstant.nacosAddr(profile));
|
||||
PropsUtil.setProperty(props, "spring.cloud.nacos.config.server-addr", LauncherConstant.nacosAddr(profile));
|
||||
PropsUtil.setProperty(props, "spring.cloud.sentinel.transport.dashboard", LauncherConstant.sentinelAddr(profile));
|
||||
PropsUtil.setProperty(props, "spring.zipkin.base-url", LauncherConstant.zipkinAddr(profile));
|
||||
PropsUtil.setProperty(props, "spring.datasource.dynamic.enabled", "false");
|
||||
|
||||
// 开启elk日志
|
||||
// PropsUtil.setProperty(props, "blade.log.elk.destination", LauncherConstant.elkAddr(profile));
|
||||
|
||||
// seata注册地址
|
||||
// PropsUtil.setProperty(props, "seata.service.grouplist.default", LauncherConstant.seataAddr(profile));
|
||||
// seata注册group格式
|
||||
// PropsUtil.setProperty(props, "seata.tx-service-group", LauncherConstant.seataServiceGroup(appName));
|
||||
// seata配置服务group
|
||||
// PropsUtil.setProperty(props, "seata.service.vgroup-mapping.".concat(LauncherConstant.seataServiceGroup(appName)), LauncherConstant.DEFAULT_MODE);
|
||||
// seata注册模式配置
|
||||
// PropsUtil.setProperty(props, "seata.registry.type", LauncherConstant.NACOS_MODE);
|
||||
// PropsUtil.setProperty(props, "seata.registry.nacos.server-addr", LauncherConstant.nacosAddr(profile));
|
||||
// PropsUtil.setProperty(props, "seata.config.type", LauncherConstant.NACOS_MODE);
|
||||
// PropsUtil.setProperty(props, "seata.config.nacos.server-addr", LauncherConstant.nacosAddr(profile));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.common.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.coobird.thumbnailator.Thumbnails;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import sun.misc.BASE64Decoder;
|
||||
import sun.misc.BASE64Encoder;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InterfaceAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 通用工具类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
public class CommonUtil {
|
||||
public static String getIpAddress() {
|
||||
Enumeration en;
|
||||
try {
|
||||
en = NetworkInterface.getNetworkInterfaces();
|
||||
} catch (SocketException var8) {
|
||||
log.error(var8.getMessage());
|
||||
return "127.0.0.1";
|
||||
}
|
||||
|
||||
ArrayList tmpMacList = new ArrayList();
|
||||
|
||||
while(en.hasMoreElements()) {
|
||||
NetworkInterface iface = (NetworkInterface)en.nextElement();
|
||||
List<InterfaceAddress> addrs = iface.getInterfaceAddresses();
|
||||
Iterator var4 = addrs.iterator();
|
||||
|
||||
while(var4.hasNext()) {
|
||||
InterfaceAddress addr = (InterfaceAddress)var4.next();
|
||||
InetAddress ip = addr.getAddress();
|
||||
if (ip != null) {
|
||||
String newIP = ip.toString().replace("/", "");
|
||||
if (!newIP.contains("127")) {
|
||||
tmpMacList.add(newIP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tmpMacList.size() <= 0) {
|
||||
return "127.0.0.1";
|
||||
} else {
|
||||
List<String> unique = (List)tmpMacList.stream().distinct().collect(Collectors.toList());
|
||||
return (String)unique.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMacAddress() {
|
||||
ArrayList tmpMacList = new ArrayList();
|
||||
|
||||
try {
|
||||
Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
label53:
|
||||
while(en.hasMoreElements()) {
|
||||
NetworkInterface iface = (NetworkInterface)en.nextElement();
|
||||
List<InterfaceAddress> addrs = iface.getInterfaceAddresses();
|
||||
Iterator var5 = addrs.iterator();
|
||||
|
||||
while(true) {
|
||||
byte[] mac;
|
||||
do {
|
||||
NetworkInterface network;
|
||||
do {
|
||||
if (!var5.hasNext()) {
|
||||
continue label53;
|
||||
}
|
||||
|
||||
InterfaceAddress addr = (InterfaceAddress)var5.next();
|
||||
InetAddress ip = addr.getAddress();
|
||||
network = NetworkInterface.getByInetAddress(ip);
|
||||
} while(network == null);
|
||||
|
||||
mac = network.getHardwareAddress();
|
||||
} while(mac == null);
|
||||
|
||||
sb.delete(0, sb.length());
|
||||
|
||||
for(int i = 0; i < mac.length; ++i) {
|
||||
sb.append(String.format("%02X%s", mac[i], i < mac.length - 1 ? "-" : ""));
|
||||
}
|
||||
|
||||
tmpMacList.add(sb.toString());
|
||||
}
|
||||
}
|
||||
} catch (Exception var11) {
|
||||
log.error(var11.getMessage());
|
||||
return "00-50-56-9C-0D-0A";
|
||||
}
|
||||
|
||||
if (tmpMacList.size() <= 0) {
|
||||
return "00-50-56-9C-0D-0A";
|
||||
} else {
|
||||
List<String> unique = (List)tmpMacList.stream().distinct().collect(Collectors.toList());
|
||||
return (String)unique.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static String compressBase64Image(String formatName, String base64, int maxLength, Double quality, Double step) throws IOException {
|
||||
if (base64.length() > maxLength) {
|
||||
BASE64Decoder decoder = new BASE64Decoder();
|
||||
byte[] bytes = decoder.decodeBuffer(base64);
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
|
||||
BufferedImage src = ImageIO.read(stream);
|
||||
int width = src.getWidth();
|
||||
int height = src.getHeight();
|
||||
BufferedImage output = Thumbnails.of(src).size(src.getWidth(), src.getHeight()).asBufferedImage();
|
||||
String result = imageToBase64(formatName, output);
|
||||
quality = null == quality ? 0.95 : quality;
|
||||
output = Thumbnails.of(output).scale(quality).asBufferedImage();
|
||||
step = null == step ? 0.05 : step;
|
||||
base64 = imageToBase64(formatName, output);
|
||||
if (base64.length() > maxLength) {
|
||||
base64 = compressBase64Image(formatName, base64, maxLength, quality - step, step);
|
||||
}
|
||||
}
|
||||
return base64;
|
||||
}
|
||||
|
||||
private static String imageToBase64(String formatName, BufferedImage bufferedImage) throws IOException {
|
||||
Base64 encoder = new Base64();
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
ImageIO.write(bufferedImage, formatName, byteArrayOutputStream);
|
||||
return new String(encoder.encode(byteArrayOutputStream.toByteArray()));
|
||||
}
|
||||
|
||||
public static String multipartFileToBase64(MultipartFile file) {
|
||||
String base64 = "";
|
||||
if (null != file) {
|
||||
BASE64Encoder encoder = new BASE64Encoder();
|
||||
try {
|
||||
base64 = encoder.encode(file.getBytes());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
return base64.replaceAll("\r\n", "");
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package org.security.common.utils;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class InputStreamAESUtil {
|
||||
// 加密盐
|
||||
private static final String key = "mb69ZaWX7NhdsbJR";
|
||||
// 加密向量
|
||||
private static final String initVector = "fquxS65OPV9WEOgx";
|
||||
|
||||
public static InputStream encryptStream(InputStream is) throws Exception {
|
||||
byte[] nonEncryptedByteArray = IOUtils.toByteArray(is);
|
||||
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes(StandardCharsets.UTF_8));
|
||||
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
|
||||
byte[] encryptedByteArray = cipher.doFinal(nonEncryptedByteArray);
|
||||
return new ByteArrayInputStream(encryptedByteArray);
|
||||
}
|
||||
|
||||
public static InputStream decryptStream(InputStream is) throws Exception {
|
||||
byte[] encryptToDecryptByteArray = IOUtils.toByteArray(is);
|
||||
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes(StandardCharsets.UTF_8));
|
||||
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
|
||||
byte[] decryptedByteArray = cipher.doFinal(encryptToDecryptByteArray);
|
||||
return new ByteArrayInputStream(decryptedByteArray);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.security.common.launch.LauncherServiceImpl
|
|
@ -0,0 +1,5 @@
|
|||
==================================================================
|
||||
= =
|
||||
= 安防信息化管理 =
|
||||
= =
|
||||
==================================================================
|
|
@ -0,0 +1,115 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>security-manage</artifactId>
|
||||
<groupId>org.security</groupId>
|
||||
<version>2.8.1.RELEASE</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>security-gateway</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>${bladex.project.version}</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!--Blade-->
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-launch</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.security</groupId>
|
||||
<artifactId>security-common</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-launch</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-metrics</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-jwt</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
</dependency>
|
||||
<!--Spring-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||
</dependency>
|
||||
<!--Hystrix-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- Nacos -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-client</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-client</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-client</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway;
|
||||
|
||||
import org.security.common.constant.CommonConstant;
|
||||
import org.springblade.core.launch.BladeApplication;
|
||||
import org.springframework.cloud.client.SpringCloudApplication;
|
||||
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* 项目启动
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@EnableHystrix
|
||||
@EnableScheduling
|
||||
@SpringCloudApplication
|
||||
public class GateWayApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
BladeApplication.run(CommonConstant.APPLICATION_GATEWAY_NAME, GateWayApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.config;
|
||||
|
||||
|
||||
import org.security.gateway.handler.ErrorExceptionHandler;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.web.ResourceProperties;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.reactive.error.ErrorAttributes;
|
||||
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
import org.springframework.web.reactive.result.view.ViewResolver;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 异常处理配置类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureBefore(ErrorWebFluxAutoConfiguration.class)
|
||||
@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
|
||||
public class ErrorHandlerConfiguration {
|
||||
|
||||
private final ServerProperties serverProperties;
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
private final ResourceProperties resourceProperties;
|
||||
|
||||
private final List<ViewResolver> viewResolvers;
|
||||
|
||||
private final ServerCodecConfigurer serverCodecConfigurer;
|
||||
|
||||
public ErrorHandlerConfiguration(ServerProperties serverProperties,
|
||||
ResourceProperties resourceProperties,
|
||||
ObjectProvider<List<ViewResolver>> viewResolversProvider,
|
||||
ServerCodecConfigurer serverCodecConfigurer,
|
||||
ApplicationContext applicationContext) {
|
||||
this.serverProperties = serverProperties;
|
||||
this.applicationContext = applicationContext;
|
||||
this.resourceProperties = resourceProperties;
|
||||
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
|
||||
this.serverCodecConfigurer = serverCodecConfigurer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
|
||||
ErrorExceptionHandler exceptionHandler = new ErrorExceptionHandler(
|
||||
errorAttributes,
|
||||
this.resourceProperties,
|
||||
this.serverProperties.getError(),
|
||||
this.applicationContext);
|
||||
exceptionHandler.setViewResolvers(this.viewResolvers);
|
||||
exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
|
||||
exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
|
||||
return exceptionHandler;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.security.gateway.props.AuthProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.web.cors.reactive.CorsUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 路由配置信息
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
@EnableConfigurationProperties({AuthProperties.class})
|
||||
public class RouterFunctionConfiguration {
|
||||
|
||||
/**
|
||||
* 这里为支持的请求头,如果有自定义的header字段请自己添加
|
||||
*/
|
||||
private static final String ALLOWED_HEADERS = "X-Requested-With, Tenant-Id, Blade-Auth, Content-Type, Authorization, credential, X-XSRF-TOKEN, token, username, client, knfie4j-gateway-request, request-origion";
|
||||
private static final String ALLOWED_METHODS = "GET,POST,PUT,DELETE,OPTIONS,HEAD";
|
||||
private static final String ALLOWED_ORIGIN = "*";
|
||||
private static final String ALLOWED_EXPOSE = "*";
|
||||
private static final String MAX_AGE = "18000L";
|
||||
|
||||
/**
|
||||
* 跨域配置
|
||||
*/
|
||||
@Bean
|
||||
public WebFilter corsFilter() {
|
||||
return (ServerWebExchange ctx, WebFilterChain chain) -> {
|
||||
ServerHttpRequest request = ctx.getRequest();
|
||||
if (CorsUtils.isCorsRequest(request)) {
|
||||
ServerHttpResponse response = ctx.getResponse();
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
|
||||
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
|
||||
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
|
||||
headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
|
||||
headers.add("Access-Control-Max-Age", MAX_AGE);
|
||||
headers.add("Access-Control-Allow-Credentials", "true");
|
||||
if (request.getMethod() == HttpMethod.OPTIONS) {
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
return Mono.empty();
|
||||
}
|
||||
}
|
||||
return chain.filter(ctx);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.dynamic;
|
||||
|
||||
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 动态路由业务类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Service
|
||||
public class DynamicRouteService implements ApplicationEventPublisherAware {
|
||||
|
||||
private final RouteDefinitionWriter routeDefinitionWriter;
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
public DynamicRouteService(RouteDefinitionWriter routeDefinitionWriter) {
|
||||
this.routeDefinitionWriter = routeDefinitionWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
|
||||
this.publisher = applicationEventPublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加路由
|
||||
*/
|
||||
public String save(RouteDefinition definition) {
|
||||
try {
|
||||
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
|
||||
this.publisher.publishEvent(new RefreshRoutesEvent(this));
|
||||
return "save success";
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return "save failure";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新路由
|
||||
*/
|
||||
public String update(RouteDefinition definition) {
|
||||
try {
|
||||
this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
|
||||
this.routeDefinitionWriter.save(Mono.just(definition)).subscribe();
|
||||
this.publisher.publishEvent(new RefreshRoutesEvent(this));
|
||||
return "update success";
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return "update failure";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新路由
|
||||
*/
|
||||
public String updateList(List<RouteDefinition> routeDefinitions) {
|
||||
routeDefinitions.forEach(this::update);
|
||||
return "update done";
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除路由
|
||||
*/
|
||||
public String delete(String id) {
|
||||
try {
|
||||
this.routeDefinitionWriter.delete(Mono.just(id));
|
||||
return "delete success";
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return "delete failure";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.dynamic;
|
||||
|
||||
import com.alibaba.cloud.nacos.NacosConfigProperties;
|
||||
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.nacos.api.NacosFactory;
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
import com.alibaba.nacos.api.config.ConfigService;
|
||||
import com.alibaba.nacos.api.config.listener.Listener;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.launch.constant.NacosConstant;
|
||||
import org.springblade.core.launch.props.BladeProperties;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* 动态路由监听器
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Order
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DynamicRouteServiceListener {
|
||||
|
||||
private final DynamicRouteService dynamicRouteService;
|
||||
private final NacosDiscoveryProperties nacosDiscoveryProperties;
|
||||
private final NacosConfigProperties nacosConfigProperties;
|
||||
private final BladeProperties bladeProperties;
|
||||
|
||||
public DynamicRouteServiceListener(DynamicRouteService dynamicRouteService, NacosDiscoveryProperties nacosDiscoveryProperties, NacosConfigProperties nacosConfigProperties, BladeProperties bladeProperties) {
|
||||
this.dynamicRouteService = dynamicRouteService;
|
||||
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
|
||||
this.nacosConfigProperties = nacosConfigProperties;
|
||||
this.bladeProperties = bladeProperties;
|
||||
dynamicRouteServiceListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听Nacos下发的动态路由配置
|
||||
*/
|
||||
private void dynamicRouteServiceListener() {
|
||||
try {
|
||||
String dataId = NacosConstant.dataId(bladeProperties.getName(), bladeProperties.getEnv(), NacosConstant.NACOS_CONFIG_JSON_FORMAT);
|
||||
String group = nacosConfigProperties.getGroup();
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosDiscoveryProperties.getServerAddr());
|
||||
properties.setProperty(PropertyKeyConst.NAMESPACE, nacosDiscoveryProperties.getNamespace());
|
||||
ConfigService configService = NacosFactory.createConfigService(properties);
|
||||
configService.addListener(dataId, group, new Listener() {
|
||||
@Override
|
||||
public void receiveConfigInfo(String configInfo) {
|
||||
List<RouteDefinition> routeDefinitions = JSON.parseArray(configInfo, RouteDefinition.class);
|
||||
dynamicRouteService.updateList(routeDefinitions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Executor getExecutor() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
String configInfo = configService.getConfig(dataId, group, 5000);
|
||||
if (configInfo != null) {
|
||||
List<RouteDefinition> routeDefinitions = JSON.parseArray(configInfo, RouteDefinition.class);
|
||||
dynamicRouteService.updateList(routeDefinitions);
|
||||
}
|
||||
} catch (NacosException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.dynamic;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 过滤器定义模型
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
public class GatewayFilter {
|
||||
|
||||
/**
|
||||
* 过滤器对应的Name
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 对应的路由规则
|
||||
*/
|
||||
private Map<String, String> args = new LinkedHashMap<>();
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.dynamic;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 路由断言定义模型
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
public class GatewayPredicate {
|
||||
|
||||
/**
|
||||
* 断言对应的Name
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 配置的断言规则
|
||||
*/
|
||||
private Map<String, String> args = new LinkedHashMap<>();
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.dynamic;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Gateway的路由定义模型
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
public class GatewayRoute {
|
||||
|
||||
/**
|
||||
* 路由的id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 路由断言集合配置
|
||||
*/
|
||||
private List<GatewayPredicate> predicates = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 路由过滤器集合配置
|
||||
*/
|
||||
private List<GatewayFilter> filters = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 路由规则转发的目标uri
|
||||
*/
|
||||
private String uri;
|
||||
|
||||
/**
|
||||
* 路由执行的顺序
|
||||
*/
|
||||
private int order = 0;
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.filter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.security.gateway.props.AuthProperties;
|
||||
import org.springblade.core.jwt.JwtUtil;
|
||||
import org.springblade.core.jwt.props.JwtProperties;
|
||||
import org.springblade.core.launch.constant.TokenConstant;
|
||||
import org.security.gateway.provider.AuthProvider;
|
||||
import org.security.gateway.provider.RequestProvider;
|
||||
import org.security.gateway.provider.ResponseProvider;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 鉴权认证
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class AuthFilter implements GlobalFilter, Ordered {
|
||||
private final AuthProperties authProperties;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final JwtProperties jwtProperties;
|
||||
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
//校验 Token 放行
|
||||
String originalRequestUrl = RequestProvider.getOriginalRequestUrl(exchange);
|
||||
String path = exchange.getRequest().getURI().getPath();
|
||||
if (isSkip(path) || isSkip(originalRequestUrl)) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
//校验 Token 合法性
|
||||
ServerHttpResponse resp = exchange.getResponse();
|
||||
String headerToken = exchange.getRequest().getHeaders().getFirst(AuthProvider.AUTH_KEY);
|
||||
String paramToken = exchange.getRequest().getQueryParams().getFirst(AuthProvider.AUTH_KEY);
|
||||
if (StringUtils.isBlank(headerToken) && StringUtils.isBlank(paramToken)) {
|
||||
return unAuth(resp, "缺失令牌,鉴权失败");
|
||||
}
|
||||
String auth = StringUtils.isBlank(headerToken) ? paramToken : headerToken;
|
||||
String token = JwtUtil.getToken(auth);
|
||||
Claims claims = JwtUtil.parseJWT(token);
|
||||
if (token == null || claims == null) {
|
||||
return unAuth(resp, "请求未授权");
|
||||
}
|
||||
//判断 Token 状态
|
||||
if (jwtProperties.getState()) {
|
||||
String tenantId = String.valueOf(claims.get(TokenConstant.TENANT_ID));
|
||||
String userId = String.valueOf(claims.get(TokenConstant.USER_ID));
|
||||
String accessToken = JwtUtil.getAccessToken(tenantId, userId, token);
|
||||
if (!token.equalsIgnoreCase(accessToken)) {
|
||||
return unAuth(resp, "令牌已失效");
|
||||
}
|
||||
}
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
private boolean isSkip(String path) {
|
||||
return AuthProvider.getDefaultSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path))
|
||||
|| authProperties.getSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path));
|
||||
}
|
||||
|
||||
private Mono<Void> unAuth(ServerHttpResponse resp, String msg) {
|
||||
resp.setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||
resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
|
||||
String result = "";
|
||||
try {
|
||||
result = objectMapper.writeValueAsString(ResponseProvider.unAuth(msg));
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
DataBuffer buffer = resp.bufferFactory().wrap(result.getBytes(StandardCharsets.UTF_8));
|
||||
return resp.writeWith(Flux.just(buffer));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return -100;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, DreamLu 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 dreamlu.net 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: DreamLu 卢春梦 (596392912@qq.com)
|
||||
*/
|
||||
package org.security.gateway.filter;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springblade.core.jwt.JwtUtil;
|
||||
import org.security.gateway.provider.AuthProvider;
|
||||
import org.security.gateway.provider.RequestProvider;
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* webflux 日志请求记录,方便开发调试。请求日志过滤器排序尽量低。
|
||||
*
|
||||
* <p>
|
||||
* 注意:暂时不支持结构体打印,想实现,请看下面的链接。
|
||||
* https://stackoverflow.com/questions/45240005/how-to-log-request-and-response-bodies-in-spring-webflux
|
||||
* https://github.com/Silvmike/webflux-demo/blob/master/tests/src/test/java/ru/hardcoders/demo/webflux/web_handler/filters/logging
|
||||
* </p>
|
||||
*
|
||||
* @author dream.lu
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnProperty(value = "blade.log.request.enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class GlobalRequestLogFilter implements GlobalFilter, Ordered {
|
||||
private final WebEndpointProperties endpointProperties;
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
// 打印请求路径
|
||||
String path = request.getPath().pathWithinApplication().value();
|
||||
|
||||
// 忽略 endpoint 请求
|
||||
String endpointBasePath = endpointProperties.getBasePath();
|
||||
if (StringUtils.isNotBlank(endpointBasePath) && path.startsWith(endpointBasePath)) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
String requestUrl = RequestProvider.getOriginalRequestUrl(exchange);
|
||||
|
||||
// 构建成一条长 日志,避免并发下日志错乱
|
||||
StringBuilder beforeReqLog = new StringBuilder(300);
|
||||
// 日志参数
|
||||
List<Object> beforeReqArgs = new ArrayList<>();
|
||||
beforeReqLog.append("\n\n================ Gateway Request Start ================\n");
|
||||
// 打印路由
|
||||
beforeReqLog.append("===> {}: {}\n");
|
||||
// 参数
|
||||
String requestMethod = request.getMethodValue();
|
||||
beforeReqArgs.add(requestMethod);
|
||||
beforeReqArgs.add(requestUrl);
|
||||
|
||||
// 打印请求头
|
||||
HttpHeaders headers = request.getHeaders();
|
||||
Locale.setDefault(Locale.ENGLISH);
|
||||
headers.forEach((headerName, headerValue) -> {
|
||||
beforeReqLog.append("===Headers=== {}: {}\n");
|
||||
beforeReqArgs.add(headerName);
|
||||
if (AuthProvider.AUTH_KEY.toLowerCase().equals(headerName)) {
|
||||
String value = headerValue.get(0);
|
||||
String token = JwtUtil.getToken(value);
|
||||
Claims claims = JwtUtil.parseJWT(token);
|
||||
beforeReqArgs.add((claims == null) ? "" : claims.toString());
|
||||
beforeReqLog.append("===Headers=== {}: {}\n");
|
||||
beforeReqArgs.add(headerName.concat("-original"));
|
||||
beforeReqArgs.add(StringUtils.join(headerValue.toArray()));
|
||||
} else {
|
||||
beforeReqArgs.add(StringUtils.join(headerValue.toArray()));
|
||||
}
|
||||
});
|
||||
|
||||
beforeReqLog.append("================ Gateway Request End =================\n");
|
||||
// 打印执行时间
|
||||
log.info(beforeReqLog.toString(), beforeReqArgs.toArray());
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, DreamLu 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 dreamlu.net 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: DreamLu 卢春梦 (596392912@qq.com)
|
||||
*/
|
||||
package org.security.gateway.filter;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* webflux 相应日志,方便开发调试,注意排序要优先。
|
||||
*
|
||||
* @author dream.lu
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnProperty(value = "blade.log.request.enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class GlobalResponseLogFilter implements GlobalFilter, Ordered {
|
||||
private final WebEndpointProperties endpointProperties;
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
// 打印请求路径
|
||||
String path = request.getPath().pathWithinApplication().value();
|
||||
// 忽略 endpoint 请求
|
||||
String endpointBasePath = endpointProperties.getBasePath();
|
||||
if (StringUtils.isNotBlank(endpointBasePath) && path.startsWith(endpointBasePath)) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
return chain.filter(exchange).then(
|
||||
Mono.fromRunnable(() -> {
|
||||
MultiValueMap<String, String> queryParams = request.getQueryParams();
|
||||
String requestUrl = UriComponentsBuilder.fromPath(path).queryParams(queryParams).build().toUriString();
|
||||
|
||||
// 构建成一条长 日志,避免并发下日志错乱
|
||||
StringBuilder responseLog = new StringBuilder(300);
|
||||
// 日志参数
|
||||
List<Object> responseArgs = new ArrayList<>();
|
||||
responseLog.append("\n\n================ Gateway Response Start ================\n");
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
// 打印路由 200 get: /api/xxx/xxx
|
||||
responseLog.append("<=== {} {}: {}\n");
|
||||
// 参数
|
||||
String requestMethod = request.getMethodValue();
|
||||
responseArgs.add(response.getStatusCode().value());
|
||||
responseArgs.add(requestMethod);
|
||||
responseArgs.add(requestUrl);
|
||||
|
||||
// 打印请求头
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
headers.forEach((headerName, headerValue) -> {
|
||||
responseLog.append("===Headers=== {}: {}\n");
|
||||
responseArgs.add(headerName);
|
||||
responseArgs.add(StringUtils.join(headerValue.toArray()));
|
||||
});
|
||||
|
||||
responseLog.append("================ Gateway Response End =================\n");
|
||||
// 打印执行时间
|
||||
log.info(responseLog.toString(), responseArgs.toArray());
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.HIGHEST_PRECEDENCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package org.security.gateway.filter;
|
||||
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 全局拦截器,作用所有的微服务
|
||||
* <p>
|
||||
* 1. 对请求头中参数进行处理 from 参数进行清洗
|
||||
* 2. 重写StripPrefix = 1,支持全局
|
||||
*
|
||||
* @author lengleng
|
||||
*/
|
||||
@Component
|
||||
public class RequestFilter implements GlobalFilter, Ordered {
|
||||
|
||||
/**
|
||||
* Process the Web request and (optionally) delegate to the next
|
||||
* {@code WebFilter} through the given {@link GatewayFilterChain}.
|
||||
*
|
||||
* @param exchange the current server exchange
|
||||
* @param chain provides a way to delegate to the next filter
|
||||
* @return {@code Mono<Void>} to indicate when request processing is complete
|
||||
*/
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
// 1. 清洗请求头中from 参数
|
||||
ServerHttpRequest request = exchange.getRequest().mutate()
|
||||
.headers(httpHeaders -> httpHeaders.remove("X"))
|
||||
.build();
|
||||
|
||||
// 2. 重写StripPrefix
|
||||
addOriginalRequestUrl(exchange, request.getURI());
|
||||
String rawPath = request.getURI().getRawPath();
|
||||
String newPath = "/" + Arrays.stream(StringUtils.tokenizeToStringArray(rawPath, "/"))
|
||||
.skip(1L).collect(Collectors.joining("/"));
|
||||
ServerHttpRequest newRequest = request.mutate()
|
||||
.path(newPath)
|
||||
.build();
|
||||
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newRequest.getURI());
|
||||
|
||||
return chain.filter(exchange.mutate().request(newRequest.mutate().build()).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return -1000;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.handler;
|
||||
|
||||
import org.security.gateway.provider.ResponseProvider;
|
||||
import org.springframework.boot.autoconfigure.web.ErrorProperties;
|
||||
import org.springframework.boot.autoconfigure.web.ResourceProperties;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
|
||||
import org.springframework.boot.web.reactive.error.ErrorAttributes;
|
||||
import org.springframework.cloud.gateway.support.NotFoundException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.web.reactive.function.server.*;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 异常处理
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class ErrorExceptionHandler extends DefaultErrorWebExceptionHandler {
|
||||
|
||||
public ErrorExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
|
||||
ErrorProperties errorProperties, ApplicationContext applicationContext) {
|
||||
super(errorAttributes, resourceProperties, errorProperties, applicationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取异常属性
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
|
||||
int code = 500;
|
||||
Throwable error = super.getError(request);
|
||||
if (error instanceof NotFoundException) {
|
||||
code = 404;
|
||||
}
|
||||
if (error instanceof ResponseStatusException) {
|
||||
code = ((ResponseStatusException) error).getStatus().value();
|
||||
}
|
||||
return ResponseProvider.response(code, this.buildMessage(request, error));
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定响应处理方法为JSON处理的方法
|
||||
*
|
||||
* @param errorAttributes
|
||||
*/
|
||||
@Override
|
||||
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
|
||||
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据code获取对应的HttpStatus
|
||||
*
|
||||
* @param errorAttributes
|
||||
*/
|
||||
@Override
|
||||
protected int getHttpStatus(Map<String, Object> errorAttributes) {
|
||||
return (int) errorAttributes.get("code");
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建异常信息
|
||||
*
|
||||
* @param request
|
||||
* @param ex
|
||||
* @return
|
||||
*/
|
||||
private String buildMessage(ServerRequest request, Throwable ex) {
|
||||
String uri = request.uri().toString();
|
||||
if (uri.endsWith("doc.html")) {
|
||||
return "[Swagger聚合网关] 已迁移至 [blade-swagger] 服务,请开启 [blade-swagger] 服务并访问 [http://127.0.0.1:18000/doc.html]";
|
||||
}
|
||||
StringBuilder message = new StringBuilder("Failed to handle request [");
|
||||
message.append(request.methodName());
|
||||
message.append(" ");
|
||||
message.append(request.uri());
|
||||
message.append("]");
|
||||
if (ex != null) {
|
||||
message.append(": ");
|
||||
message.append(ex.getMessage());
|
||||
}
|
||||
return message.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.props;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 权限过滤
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@RefreshScope
|
||||
@ConfigurationProperties("blade.secure")
|
||||
public class AuthProperties {
|
||||
|
||||
/**
|
||||
* 放行API集合
|
||||
*/
|
||||
private final List<String> skipUrl = new ArrayList<>();
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.provider;
|
||||
|
||||
import org.springblade.core.launch.constant.TokenConstant;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 鉴权配置
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class AuthProvider {
|
||||
|
||||
public static final String AUTH_KEY = TokenConstant.HEADER;
|
||||
private static final List<String> DEFAULT_SKIP_URL = new ArrayList<>();
|
||||
|
||||
static {
|
||||
DEFAULT_SKIP_URL.add("/example");
|
||||
DEFAULT_SKIP_URL.add("/oauth/token/**");
|
||||
DEFAULT_SKIP_URL.add("/oauth/captcha/**");
|
||||
DEFAULT_SKIP_URL.add("/oauth/clear-cache/**");
|
||||
DEFAULT_SKIP_URL.add("/oauth/user-info");
|
||||
DEFAULT_SKIP_URL.add("/oauth/render/**");
|
||||
DEFAULT_SKIP_URL.add("/oauth/callback/**");
|
||||
DEFAULT_SKIP_URL.add("/oauth/revoke/**");
|
||||
DEFAULT_SKIP_URL.add("/oauth/refresh/**");
|
||||
DEFAULT_SKIP_URL.add("/token/**");
|
||||
DEFAULT_SKIP_URL.add("/actuator/**");
|
||||
DEFAULT_SKIP_URL.add("/v2/api-docs/**");
|
||||
DEFAULT_SKIP_URL.add("/auth/**");
|
||||
DEFAULT_SKIP_URL.add("/authorize/**");
|
||||
DEFAULT_SKIP_URL.add("/log/**");
|
||||
DEFAULT_SKIP_URL.add("/menu/routes");
|
||||
DEFAULT_SKIP_URL.add("/menu/auth-routes");
|
||||
DEFAULT_SKIP_URL.add("/menu/top-menu");
|
||||
DEFAULT_SKIP_URL.add("/tenant/info");
|
||||
DEFAULT_SKIP_URL.add("/process/resource-view");
|
||||
DEFAULT_SKIP_URL.add("/process/diagram-view");
|
||||
DEFAULT_SKIP_URL.add("/manager/check-upload");
|
||||
DEFAULT_SKIP_URL.add("/error/**");
|
||||
DEFAULT_SKIP_URL.add("/assets/**");
|
||||
//TODO:app接口暂时放行,后续接单点登录
|
||||
DEFAULT_SKIP_URL.add("/app/**");
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认无需鉴权的API
|
||||
*/
|
||||
public static List<String> getDefaultSkipUrl() {
|
||||
return DEFAULT_SKIP_URL;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.provider;
|
||||
|
||||
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
/**
|
||||
* RequestProvider
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class RequestProvider {
|
||||
|
||||
/**
|
||||
* 获取原始url
|
||||
*
|
||||
* @param exchange
|
||||
* @return
|
||||
*/
|
||||
public static String getOriginalRequestUrl(ServerWebExchange exchange) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
LinkedHashSet<URI> uris = exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
|
||||
URI requestUri = uris.stream().findFirst().orElse(request.getURI());
|
||||
MultiValueMap<String, String> queryParams = request.getQueryParams();
|
||||
return UriComponentsBuilder.fromPath(requestUri.getRawPath()).queryParams(queryParams).build().toUriString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.gateway.provider;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 请求响应返回
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class ResponseProvider {
|
||||
|
||||
/**
|
||||
* 成功
|
||||
*
|
||||
* @param message 信息
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Object> success(String message) {
|
||||
return response(200, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*
|
||||
* @param message 信息
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Object> fail(String message) {
|
||||
return response(400, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 未授权
|
||||
*
|
||||
* @param message 信息
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Object> unAuth(String message) {
|
||||
return response(401, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务器异常
|
||||
*
|
||||
* @param message 信息
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Object> error(String message) {
|
||||
return response(500, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建返回的JSON数据格式
|
||||
*
|
||||
* @param status 状态码
|
||||
* @param message 信息
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Object> response(int status, String message) {
|
||||
Map<String, Object> map = new HashMap<>(16);
|
||||
map.put("code", status);
|
||||
map.put("msg", message);
|
||||
map.put("data", null);
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
blade:
|
||||
#多团队协作服务配置
|
||||
ribbon:
|
||||
rule:
|
||||
#开启配置
|
||||
enabled: true
|
||||
#负载均衡优先调用的ip段
|
||||
prior-ip-pattern:
|
||||
- 192.168.0.*
|
||||
- 127.0.0.1
|
|
@ -0,0 +1,10 @@
|
|||
blade:
|
||||
#多团队协作服务配置
|
||||
ribbon:
|
||||
rule:
|
||||
#开启配置
|
||||
enabled: true
|
||||
#负载均衡优先调用的ip段
|
||||
prior-ip-pattern:
|
||||
- 192.168.0.*
|
||||
- 127.0.0.1
|
|
@ -0,0 +1,10 @@
|
|||
blade:
|
||||
#多团队协作服务配置
|
||||
ribbon:
|
||||
rule:
|
||||
#开启配置
|
||||
enabled: true
|
||||
#负载均衡优先调用的ip段
|
||||
prior-ip-pattern:
|
||||
- 192.168.0.*
|
||||
- 127.0.0.1
|
|
@ -0,0 +1,15 @@
|
|||
server:
|
||||
port: 8000
|
||||
|
||||
spring:
|
||||
cloud:
|
||||
discovery:
|
||||
reactive:
|
||||
enabled: false
|
||||
gateway:
|
||||
discovery:
|
||||
locator:
|
||||
enabled: true
|
||||
loadbalancer:
|
||||
retry:
|
||||
enabled: true
|
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<configuration>
|
||||
<property name="logdir" value="../logs/security-gateway"/>
|
||||
<!-- 控制台输出日志 -->
|
||||
<!-- 彩色日志依赖的渲染类 -->
|
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
|
||||
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
|
||||
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
|
||||
<!-- 彩色日志格式 -->
|
||||
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||
<charset>utf8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
<!-- 按用户输出日志 -->
|
||||
<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
|
||||
<discriminator>
|
||||
<Key>txcode</Key>
|
||||
<DefaultValue>security-gateway</DefaultValue>
|
||||
</discriminator>
|
||||
<sift>
|
||||
<appender name="FILE-${userid}" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<File>${logdir}/${txcode}.log</File>
|
||||
<Append>false</Append>
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} %msg%n</Pattern>
|
||||
</layout>
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<FileNamePattern>${logdir}/${txcode}.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
|
||||
<MaxHistory>20</MaxHistory>
|
||||
<maxFileSize>5MB</maxFileSize>
|
||||
<totalSizeCap>1024MB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
</sift>
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<includeCallerData>true</includeCallerData>
|
||||
<discardingThreshold>-1</discardingThreshold>
|
||||
<queueSize>1024</queueSize>
|
||||
<appender-ref ref="SIFT"/>
|
||||
</appender>
|
||||
|
||||
<!-- <logger name="dao" level="DEBUG"/>-->
|
||||
<!-- <logger name="net.sf.ehcache" level="INFO"/>-->
|
||||
<!-- <logger name="druid.sql" level="INFO"/>-->
|
||||
|
||||
|
||||
<!-- MyBatis log configure -->
|
||||
<logger name="com.apache.ibatis" level="INFO"/>
|
||||
<logger name="org.mybatis.spring" level="DEBUG"/>
|
||||
<logger name="java.sql.Connection" level="DEBUG"/>
|
||||
<logger name="java.sql.Statement" level="DEBUG"/>
|
||||
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
|
||||
|
||||
<!-- 减少部分debug日志 -->
|
||||
<logger name="druid.sql" level="INFO"/>
|
||||
<logger name="org.apache.shiro" level="INFO"/>
|
||||
<logger name="org.mybatis.spring" level="INFO"/>
|
||||
<logger name="org.springframework" level="INFO"/>
|
||||
<logger name="org.springframework.context" level="WARN"/>
|
||||
<logger name="org.springframework.beans" level="WARN"/>
|
||||
<logger name="com.baomidou.mybatisplus" level="INFO"/>
|
||||
<logger name="org.apache.ibatis.io" level="INFO"/>
|
||||
<logger name="org.apache.velocity" level="INFO"/>
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="io.undertow" level="INFO"/>
|
||||
<logger name="org.xnio.nio" level="INFO"/>
|
||||
<logger name="org.thymeleaf" level="INFO"/>
|
||||
<logger name="springfox.documentation" level="INFO"/>
|
||||
<logger name="org.hibernate.validator" level="INFO"/>
|
||||
<logger name="com.netflix.loadbalancer" level="INFO"/>
|
||||
<logger name="com.netflix.hystrix" level="INFO"/>
|
||||
<logger name="com.netflix.zuul" level="INFO"/>
|
||||
<logger name="de.codecentric" level="INFO"/>
|
||||
<!-- cache INFO -->
|
||||
<logger name="net.sf.ehcache" level="INFO"/>
|
||||
<logger name="org.springframework.cache" level="INFO"/>
|
||||
<!-- cloud -->
|
||||
<logger name="org.apache.http" level="INFO"/>
|
||||
<logger name="com.netflix.discovery" level="INFO"/>
|
||||
<logger name="com.netflix.eureka" level="INFO"/>
|
||||
<!-- 业务日志 -->
|
||||
<Logger name="org.security" level="DEBUG" />
|
||||
<Logger name="org.springblade.core.version" level="INFO"/>
|
||||
|
||||
<!-- 减少nacos日志 -->
|
||||
<logger name="com.alibaba.nacos" level="ERROR"/>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
<appender-ref ref="ASYNC"/>
|
||||
</root>
|
||||
</configuration>
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>security-manage</artifactId>
|
||||
<groupId>org.security</groupId>
|
||||
<version>2.8.1.RELEASE</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>security-ops-api</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>2.8.1.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>security-flow-api</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-auto</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.security</groupId>
|
||||
<artifactId>security-common</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
<finalName>${project.name}</finalName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>security-ops-api</artifactId>
|
||||
<groupId>org.security</groupId>
|
||||
<version>2.8.1.RELEASE</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>security-flow-api</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>${bladex.project.version}</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.flowable</groupId>
|
||||
<artifactId>flowable-engine</artifactId>
|
||||
<version>${flowable.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
</project>
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.flow.core.constant;
|
||||
|
||||
/**
|
||||
* 流程常量.
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public interface ProcessConstant {
|
||||
|
||||
/**
|
||||
* 请假流程标识
|
||||
*/
|
||||
String LEAVE_KEY = "Leave";
|
||||
|
||||
/**
|
||||
* 报销流程标识
|
||||
*/
|
||||
String EXPENSE_KEY = "Expense";
|
||||
|
||||
/**
|
||||
* 同意标识
|
||||
*/
|
||||
String PASS_KEY = "pass";
|
||||
|
||||
/**
|
||||
* 同意代号
|
||||
*/
|
||||
String PASS_ALIAS = "ok";
|
||||
|
||||
/**
|
||||
* 同意默认批复
|
||||
*/
|
||||
String PASS_COMMENT = "同意";
|
||||
|
||||
/**
|
||||
* 驳回默认批复
|
||||
*/
|
||||
String NOT_PASS_COMMENT = "驳回";
|
||||
|
||||
/**
|
||||
* 创建人变量名
|
||||
*/
|
||||
String TASK_VARIABLE_CREATE_USER = "createUser";
|
||||
|
||||
/**
|
||||
* 开启流程人id
|
||||
*/
|
||||
String START_PROC_USER_ID = "startProcUserId";
|
||||
|
||||
/**
|
||||
* 案件材料报送审批流程标识
|
||||
*/
|
||||
String PREVENT_MATERIAL_KEY = "prevent_material";
|
||||
|
||||
/**
|
||||
* 风险提示审批流程标识
|
||||
*/
|
||||
String PREVENT_RISK_KEY = "prevent_risk";
|
||||
|
||||
/**
|
||||
* 值班备勤审批流程标识
|
||||
*/
|
||||
String DUTY_RECORDS_KEY = "duty_records";
|
||||
|
||||
/**
|
||||
* 机构考核审批流程标识
|
||||
*/
|
||||
String BANK_ASSESSMENT_KEY = "bank_assessment";
|
||||
|
||||
/**
|
||||
* 相关方考评审批流程标识
|
||||
*/
|
||||
String OUTSOURCING_ASSESSMENT_KEY = "outsourcing_assessment";
|
||||
|
||||
/**
|
||||
* 项目考评审批流程标识
|
||||
*/
|
||||
String PROJECT_ASSESSMENT_KEY = "project_assessment";
|
||||
|
||||
/**
|
||||
* 教育培训审批流程标识
|
||||
*/
|
||||
String TASK_HANDIN_EDU_KEY = "task_handin_edu";
|
||||
|
||||
/**
|
||||
* 应急演练审批流程标识
|
||||
*/
|
||||
String TASK_HANDIN_DRILL_KEY = "task_handin_drill";
|
||||
|
||||
/**
|
||||
* 现场检查审批流程标识
|
||||
*/
|
||||
String INSPECTION_KEY = "inspection";
|
||||
|
||||
/**
|
||||
* 现场检查整改审批流程标识
|
||||
*/
|
||||
String INSPECTION_LINE_KEY = "inspection_line";
|
||||
|
||||
/**
|
||||
* 非现场检查审批流程标识
|
||||
*/
|
||||
String SCC_CHECK_KEY = "scc_check";
|
||||
|
||||
/**
|
||||
* 非现场检查整改审批流程标识
|
||||
*/
|
||||
String SCC_UNLOCAL_CHECK_KEY = "scc_unlocal_check";
|
||||
|
||||
/**
|
||||
* 非现场检查持续整改审批流程标识
|
||||
*/
|
||||
String SCC_UNLOCAL_CHECK_CONTINUE_KEY = "scc_unlocal_check_con";
|
||||
|
||||
/**
|
||||
* 设备检查流程标识
|
||||
*/
|
||||
String DEVICE_INSPECTION_KEY = "device_inspection";
|
||||
|
||||
/**
|
||||
* 设备检查整改流程标识
|
||||
*/
|
||||
String DEVICE_INSPECTION_REC_KEY = "device_inspection_rec";
|
||||
|
||||
/**
|
||||
* 设备检查持续整改流程标识
|
||||
*/
|
||||
String DEVICE_INS_REC_CON_KEY = "device_ins_rec_con";
|
||||
|
||||
/**
|
||||
* 下发整改通知书审批流程标识
|
||||
*/
|
||||
// String SCC_UNLOCAL_CHECK_KEY = "scc_unlocal_check";
|
||||
|
||||
/**
|
||||
* 联系接警记录审批流程标识
|
||||
*/
|
||||
String SCC_ANSWER_ALARM_KEY = "scc_answer_alarm";
|
||||
|
||||
/**
|
||||
* 警情处理审批流程标识
|
||||
*/
|
||||
String SCC_ALARM_PUSH_KEY = "scc_alarm_push";
|
||||
|
||||
/**
|
||||
* 业务id标识
|
||||
*/
|
||||
String BUSINESS_ID_KEY = "businessId";
|
||||
|
||||
String PASS_STATE = "2";
|
||||
|
||||
String REJECT_STATE = "3";
|
||||
|
||||
String CANCEL_STATE = "4";
|
||||
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.flow.core.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import org.security.flow.core.constant.ProcessConstant;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流通用实体类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
public class BladeFlow implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务编号
|
||||
*/
|
||||
private String taskId;
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String taskName;
|
||||
/**
|
||||
* 任务定义Key
|
||||
*/
|
||||
private String taskDefinitionKey;
|
||||
/**
|
||||
* 任务执行人编号
|
||||
*/
|
||||
private String assignee;
|
||||
/**
|
||||
* 任务执行人名称
|
||||
*/
|
||||
private String assigneeName;
|
||||
/**
|
||||
* 流程分类
|
||||
*/
|
||||
private String category;
|
||||
/**
|
||||
* 流程分类名
|
||||
*/
|
||||
private String categoryName;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private Date endTime;
|
||||
/**
|
||||
* 签收时间
|
||||
*/
|
||||
private Date claimTime;
|
||||
/**
|
||||
* 历史任务结束时间
|
||||
*/
|
||||
private Date historyTaskEndTime;
|
||||
/**
|
||||
* 执行ID
|
||||
*/
|
||||
private String executionId;
|
||||
/**
|
||||
* 流程实例ID
|
||||
*/
|
||||
private String processInstanceId;
|
||||
/**
|
||||
* 流程ID
|
||||
*/
|
||||
private String processDefinitionId;
|
||||
/**
|
||||
* 流程标识
|
||||
*/
|
||||
private String processDefinitionKey;
|
||||
/**
|
||||
* 流程名
|
||||
*/
|
||||
private String processDefinitionName;
|
||||
/**
|
||||
* 流程版本
|
||||
*/
|
||||
private int processDefinitionVersion;
|
||||
/**
|
||||
* 流程说明
|
||||
*/
|
||||
private String processDefinitionDesc;
|
||||
/**
|
||||
* 流程简图名
|
||||
*/
|
||||
private String processDefinitionDiagramResName;
|
||||
/**
|
||||
* 流程重命名
|
||||
*/
|
||||
private String processDefinitionResName;
|
||||
/**
|
||||
* 历史任务流程实例ID 查看流程图会用到
|
||||
*/
|
||||
private String historyProcessInstanceId;
|
||||
/**
|
||||
* 流程实例是否结束
|
||||
*/
|
||||
private String processIsFinished;
|
||||
/**
|
||||
* 历史活动ID
|
||||
*/
|
||||
private String historyActivityId;
|
||||
/**
|
||||
* 历史活动流程
|
||||
*/
|
||||
private String historyActivityName;
|
||||
/**
|
||||
* 历史活动耗时
|
||||
*/
|
||||
private String historyActivityDurationTime;
|
||||
/**
|
||||
* 业务绑定Table
|
||||
*/
|
||||
private String businessTable;
|
||||
/**
|
||||
* 业务绑定ID
|
||||
*/
|
||||
private String businessId;
|
||||
/**
|
||||
* 任务状态
|
||||
*/
|
||||
private String status;
|
||||
/**
|
||||
* 任务意见
|
||||
*/
|
||||
private String comment;
|
||||
/**
|
||||
* 是否通过
|
||||
*/
|
||||
private boolean isPass;
|
||||
/**
|
||||
* 是否通过代号
|
||||
*/
|
||||
private String flag;
|
||||
/**
|
||||
* 开始查询日期
|
||||
*/
|
||||
private Date beginDate;
|
||||
/**
|
||||
* 结束查询日期
|
||||
*/
|
||||
private Date endDate;
|
||||
/**
|
||||
* 流程参数
|
||||
*/
|
||||
private Map<String, Object> variables;
|
||||
|
||||
/**
|
||||
* 获取是否通过
|
||||
*/
|
||||
public boolean isPass() {
|
||||
return ProcessConstant.PASS_ALIAS.equals(flag) || ProcessConstant.PASS_COMMENT.equals(comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* 整个流程是否通过
|
||||
*/
|
||||
private boolean flowPass;
|
||||
|
||||
private boolean cancelFlow;
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package org.security.flow.core.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: qxqx
|
||||
* @Create: 2022/9/7
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class BladeFlowDef implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
|
||||
private String category;
|
||||
|
||||
private String name;
|
||||
|
||||
private String key;
|
||||
|
||||
private String description;
|
||||
|
||||
private int version;
|
||||
|
||||
private String resourceName;
|
||||
|
||||
private String deploymentId;
|
||||
|
||||
private String diagramResourceName;
|
||||
|
||||
private boolean hasStartFormKey;
|
||||
|
||||
private boolean hasGraphicalNotation;
|
||||
|
||||
private boolean isSuspended;
|
||||
|
||||
private String tenantId;
|
||||
|
||||
private String derivedForm;
|
||||
|
||||
private String derivedFromRoot;
|
||||
|
||||
private int derivedVersion;
|
||||
|
||||
private String engineVersion;
|
||||
|
||||
private List<BladeFlow> historyFlowList;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.flow.core.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springblade.core.mp.base.BaseEntity;
|
||||
|
||||
/**
|
||||
* FlowEntity
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class FlowEntity extends BaseEntity {
|
||||
|
||||
@TableField(exist = false)
|
||||
private BladeFlow flow;
|
||||
|
||||
public BladeFlow getFlow() {
|
||||
if (flow == null) {
|
||||
flow = new BladeFlow();
|
||||
}
|
||||
return flow;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.flow.core.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 审批候选人类型
|
||||
*
|
||||
* @author Arlex
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum CandidateTypeEnum {
|
||||
|
||||
/**
|
||||
* 总行领导
|
||||
*/
|
||||
HEAD_LEADER("headLeader", "总行领导"),
|
||||
|
||||
/**
|
||||
* 总行安全部部门领导
|
||||
*/
|
||||
HEAD_SEC_LEADER("headSecLeader", "总行安全部部门领导"),
|
||||
|
||||
/**
|
||||
* 总行安全员
|
||||
*/
|
||||
HEAD_SAFER("headSafer", "总行安全员"),
|
||||
|
||||
/**
|
||||
* 分行领导
|
||||
*/
|
||||
BRANCH_LEADER("branchLeader", "分行领导"),
|
||||
|
||||
/**
|
||||
* 分行安全员
|
||||
*/
|
||||
BRANCH_SAFER("branchSafer", "分行安全员"),
|
||||
|
||||
/**
|
||||
* 支行领导
|
||||
*/
|
||||
SUB_LEADER("subLeader", "支行领导"),
|
||||
|
||||
/**
|
||||
* 支行安全员
|
||||
*/
|
||||
SUB_SAFER("subSafer", "支行安全员"),
|
||||
|
||||
/**
|
||||
* 部门领导
|
||||
*/
|
||||
DEPT_LEADER("deptLeader", "部门领导"),
|
||||
|
||||
/**
|
||||
* 总行安保指挥中心全员
|
||||
*/
|
||||
HEAD_SEC_CENTER_ALL("securityUser", "总行安保指挥中心全员"),
|
||||
|
||||
/**
|
||||
* 分行安保指挥中心全员
|
||||
*/
|
||||
BRANCH_SEC_CENTER_ALL("branchSecurityUser", "分行安保指挥中心全员"),
|
||||
;
|
||||
|
||||
final String value;
|
||||
|
||||
final String name;
|
||||
|
||||
public static CandidateTypeEnum fromValue(String value) {
|
||||
if (null == value) {
|
||||
throw new IllegalArgumentException("Invalid value: " + value);
|
||||
}
|
||||
return EnumSet.allOf(CandidateTypeEnum.class).stream()
|
||||
.filter(s -> s.getValue().equals(value))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new IllegalArgumentException("Invalid value: " + value));
|
||||
}
|
||||
|
||||
public static List<String> getValues() {
|
||||
List<String> list = Stream.of(CandidateTypeEnum.values()).map(CandidateTypeEnum::getValue).collect(Collectors.toList());
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.flow.core.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 流程类型枚举
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum FlowModeEnum {
|
||||
|
||||
/**
|
||||
* 通用流程
|
||||
*/
|
||||
COMMON("common", 1),
|
||||
|
||||
/**
|
||||
* 定制流程
|
||||
*/
|
||||
CUSTOM("custom", 2),
|
||||
;
|
||||
|
||||
final String name;
|
||||
final int mode;
|
||||
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.flow.core.feign;
|
||||
|
||||
import org.security.common.constant.CommonConstant;
|
||||
import org.security.flow.core.entity.BladeFlow;
|
||||
import org.security.flow.core.entity.BladeFlowDef;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流远程调用接口.
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@FeignClient(
|
||||
value = CommonConstant.APPLICATION_FLOW_NAME,
|
||||
fallback = IFlowClientFallback.class
|
||||
)
|
||||
public interface IFlowClient {
|
||||
|
||||
String API_PREFIX = "/client";
|
||||
String START_PROCESS_INSTANCE_BY_ID = API_PREFIX + "/start-process-instance-by-id";
|
||||
String START_PROCESS_INSTANCE_BY_KEY = API_PREFIX + "/start-process-instance-by-key";
|
||||
String COMPLETE_TASK = API_PREFIX + "/complete-task";
|
||||
String TASK_VARIABLE = API_PREFIX + "/task-variable";
|
||||
String TASK_VARIABLES = API_PREFIX + "/task-variables";
|
||||
String PROCESS_DEFINITION = API_PREFIX + "/get-latest-process-definition-by-key";
|
||||
String DELETE_RPOC_INS = API_PREFIX + "/delete-process-instance";
|
||||
|
||||
/**
|
||||
* 开启流程
|
||||
*
|
||||
* @param processDefinitionId 流程id
|
||||
* @param businessKey 业务key
|
||||
* @param variables 参数
|
||||
* @return BladeFlow
|
||||
*/
|
||||
@PostMapping(START_PROCESS_INSTANCE_BY_ID)
|
||||
R<BladeFlow> startProcessInstanceById(@RequestParam("processDefinitionId") String processDefinitionId, @RequestParam("businessKey") String businessKey, @RequestBody Map<String, Object> variables);
|
||||
|
||||
/**
|
||||
* 开启流程
|
||||
*
|
||||
* @param processDefinitionKey 流程标识
|
||||
* @param businessKey 业务key
|
||||
* @param variables 参数
|
||||
* @return BladeFlow
|
||||
*/
|
||||
@PostMapping(START_PROCESS_INSTANCE_BY_KEY)
|
||||
R<BladeFlow> startProcessInstanceByKey(@RequestParam("processDefinitionKey") String processDefinitionKey, @RequestParam("businessKey") String businessKey, @RequestBody Map<String, Object> variables);
|
||||
|
||||
/**
|
||||
* 完成任务
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @param processInstanceId 流程实例id
|
||||
* @param comment 评论
|
||||
* @param variables 参数
|
||||
* @return R
|
||||
*/
|
||||
@PostMapping(COMPLETE_TASK)
|
||||
R completeTask(@RequestParam("taskId") String taskId, @RequestParam("processInstanceId") String processInstanceId, @RequestParam("comment") String comment, @RequestBody Map<String, Object> variables);
|
||||
|
||||
/**
|
||||
* 获取流程变量
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @param variableName 变量名
|
||||
* @return R
|
||||
*/
|
||||
@GetMapping(TASK_VARIABLE)
|
||||
R<Object> taskVariable(@RequestParam("taskId") String taskId, @RequestParam("variableName") String variableName);
|
||||
|
||||
/**
|
||||
* 获取流程变量集合
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @return R
|
||||
*/
|
||||
@GetMapping(TASK_VARIABLES)
|
||||
R<Map<String, Object>> taskVariables(@RequestParam("taskId") String taskId);
|
||||
|
||||
/**
|
||||
* 根据流程标识获取最新的流程定义
|
||||
*
|
||||
* @param processDefinitionKey 流程标识
|
||||
* @return ProcessDefinition
|
||||
*/
|
||||
@GetMapping(PROCESS_DEFINITION)
|
||||
R<BladeFlowDef> getLatestProcessDefinitionByKey(@RequestParam("processDefinitionKey") String processDefinitionKey);
|
||||
|
||||
/**
|
||||
* 根据流程实例id删除流程及其历史信息
|
||||
*
|
||||
* @param processInstanceIds 流程标识
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(DELETE_RPOC_INS)
|
||||
R deleteProcessInstanceByInstanceId(@RequestParam("processInstanceIds") String processInstanceIds);
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.flow.core.feign;
|
||||
|
||||
import org.security.flow.core.entity.BladeFlowDef;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.security.flow.core.entity.BladeFlow;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程远程调用失败处理类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Component
|
||||
public class IFlowClientFallback implements IFlowClient {
|
||||
|
||||
@Override
|
||||
public R<BladeFlow> startProcessInstanceById(String processDefinitionId, String businessKey, Map<String, Object> variables) {
|
||||
return R.fail("远程调用失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<BladeFlow> startProcessInstanceByKey(String processDefinitionKey, String businessKey, Map<String, Object> variables) {
|
||||
return R.fail("远程调用失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public R completeTask(String taskId, String processInstanceId, String comment, Map<String, Object> variables) {
|
||||
return R.fail("远程调用失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<Object> taskVariable(String taskId, String variableName) {
|
||||
return R.fail("远程调用失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<Map<String, Object>> taskVariables(String taskId) {
|
||||
return R.fail("远程调用失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<BladeFlowDef> getLatestProcessDefinitionByKey(String processDefinitionKey) {
|
||||
return R.fail("远程调用失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public R deleteProcessInstanceByInstanceId(String processInstanceIds) {
|
||||
return R.fail("远程调用失败");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.flow.core.utils;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
||||
import org.security.flow.core.constant.ProcessConstant;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流工具类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class FlowUtil {
|
||||
|
||||
/**
|
||||
* 定义流程key对应的表名
|
||||
*/
|
||||
private final static Map<String, String> BUSINESS_TABLE = new HashMap<>();
|
||||
|
||||
static {
|
||||
BUSINESS_TABLE.put(ProcessConstant.LEAVE_KEY, "blade_process_leave");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过流程key获取业务表名
|
||||
*
|
||||
* @param key 流程key
|
||||
*/
|
||||
public static String getBusinessTable(String key) {
|
||||
String businessTable = BUSINESS_TABLE.get(key);
|
||||
if (Func.isEmpty(businessTable)) {
|
||||
throw new RuntimeException("流程启动失败,未找到相关业务表");
|
||||
}
|
||||
return businessTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取业务标识
|
||||
*
|
||||
* @param businessTable 业务表
|
||||
* @param businessId 业务表主键
|
||||
* @return businessKey
|
||||
*/
|
||||
public static String getBusinessKey(String businessTable, String businessId) {
|
||||
return StringUtil.format("{}:{}", businessTable, businessId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过流程对象获取业务表名
|
||||
*
|
||||
* @param clazz 流程对象类
|
||||
*/
|
||||
public static String getBusinessTable(Class clazz) {
|
||||
String tableName = SqlHelper.table(clazz).getTableName();
|
||||
return tableName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
|
||||
*/
|
||||
package org.security.flow.core.utils;
|
||||
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
||||
import static org.springblade.core.launch.constant.FlowConstant.TASK_USR_PREFIX;
|
||||
|
||||
/**
|
||||
* 工作流任务工具类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class TaskUtil {
|
||||
|
||||
/**
|
||||
* 获取任务用户格式
|
||||
*
|
||||
* @return taskUser
|
||||
*/
|
||||
public static String getTaskUser() {
|
||||
return StringUtil.format("{}{}", TASK_USR_PREFIX, AuthUtil.getUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务用户格式
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return taskUser
|
||||
*/
|
||||
public static String getTaskUser(String userId) {
|
||||
return StringUtil.format("{}{}", TASK_USR_PREFIX, userId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户主键
|
||||
*
|
||||
* @param taskUser 任务用户
|
||||
* @return userId
|
||||
*/
|
||||
public static Long getUserId(String taskUser) {
|
||||
return Func.toLong(StringUtil.removePrefix(taskUser, TASK_USR_PREFIX));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户组格式
|
||||
*
|
||||
* @return candidateGroup
|
||||
*/
|
||||
public static String getCandidateGroup() {
|
||||
return AuthUtil.getUserRole();
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue