From adc037d213bacf9fed4b4871fab8906a3da68ff2 Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Tue, 1 Aug 2023 09:55:28 +0800 Subject: [PATCH 01/23] =?UTF-8?q?feat:=20=E5=88=A0=E9=99=A4txlcn-demo?= =?UTF-8?q?=E5=B7=A5=E7=A8=8B(=E7=94=B1=E4=BA=8Etxlcn=E4=B8=8D=E6=8E=A8?= =?UTF-8?q?=E8=8D=90=E4=BD=BF=E7=94=A8=E4=BA=86)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zlt-demo/pom.xml | 2 - zlt-demo/txlcn-demo/README.md | 48 ------------- zlt-demo/txlcn-demo/pom.xml | 22 ------ zlt-demo/txlcn-demo/txlcn-demo-common/pom.xml | 69 ------------------- .../org/txlcn/demo/common/db/domain/Demo.java | 27 -------- .../demo/common/db/mapper/BaseDemoMapper.java | 22 ------ .../common/spring/FeignConfiguration.java | 17 ----- .../demo/common/spring/ServiceBClient.java | 18 ----- .../demo/common/spring/ServiceCClient.java | 18 ----- .../main/resources/META-INF/spring.factories | 1 - .../txlcn-demo-spring-service-a/pom.xml | 29 -------- .../org/txlcn/demo/ServiceAApplication.java | 23 ------- .../txlcn/demo/servicea/DemoController.java | 29 -------- .../org/txlcn/demo/servicea/DemoMapper.java | 14 ---- .../org/txlcn/demo/servicea/DemoService.java | 12 ---- .../txlcn/demo/servicea/DemoServiceImpl.java | 55 --------------- .../src/main/resources/application.yml | 25 ------- .../src/main/resources/bootstrap.yml | 6 -- .../txlcn-demo-spring-service-b/pom.xml | 28 -------- .../org/txlcn/demo/ServiceBApplication.java | 21 ------ .../txlcn/demo/serviceb/DemoController.java | 26 ------- .../org/txlcn/demo/serviceb/DemoMapper.java | 14 ---- .../org/txlcn/demo/serviceb/DemoService.java | 12 ---- .../txlcn/demo/serviceb/DemoServiceImpl.java | 41 ----------- .../src/main/resources/application.yml | 24 ------- .../src/main/resources/bootstrap.yml | 6 -- .../txlcn-demo-spring-service-c/pom.xml | 28 -------- .../org/txlcn/demo/ServiceCApplication.java | 21 ------ .../txlcn/demo/servicec/DemoController.java | 24 ------- .../org/txlcn/demo/servicec/DemoMapper.java | 14 ---- .../org/txlcn/demo/servicec/DemoService.java | 12 ---- .../txlcn/demo/servicec/DemoServiceImpl.java | 48 ------------- .../src/main/resources/application.yml | 19 ----- .../src/main/resources/bootstrap.yml | 6 -- zlt-demo/txlcn-demo/txlcn-demo.sql | 23 ------- 35 files changed, 804 deletions(-) delete mode 100644 zlt-demo/txlcn-demo/README.md delete mode 100644 zlt-demo/txlcn-demo/pom.xml delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-common/pom.xml delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/db/domain/Demo.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/db/mapper/BaseDemoMapper.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/FeignConfiguration.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/ServiceBClient.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/ServiceCClient.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-common/src/main/resources/META-INF/spring.factories delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/pom.xml delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/ServiceAApplication.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoController.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoMapper.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoService.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoServiceImpl.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/resources/application.yml delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/resources/bootstrap.yml delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/pom.xml delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/ServiceBApplication.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoController.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoMapper.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoService.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoServiceImpl.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/resources/application.yml delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/resources/bootstrap.yml delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/pom.xml delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/ServiceCApplication.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoController.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoMapper.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoService.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoServiceImpl.java delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/resources/application.yml delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/resources/bootstrap.yml delete mode 100644 zlt-demo/txlcn-demo/txlcn-demo.sql diff --git a/zlt-demo/pom.xml b/zlt-demo/pom.xml index fc979432f..052643246 100644 --- a/zlt-demo/pom.xml +++ b/zlt-demo/pom.xml @@ -10,8 +10,6 @@ pom - - txlcn-demo sharding-jdbc-demo diff --git a/zlt-demo/txlcn-demo/README.md b/zlt-demo/txlcn-demo/README.md deleted file mode 100644 index 73cbd85d6..000000000 --- a/zlt-demo/txlcn-demo/README.md +++ /dev/null @@ -1,48 +0,0 @@ -[TOC] - -## 一、说明 - -本demo是通过tx-lcn测试lcn模式的分布式事务,主要是模拟以下两个场景 - -1. `service-a` 调用`service-b`调用`service-c` 都成功 -2. `service-a` 调用`service-b`调用`service-c` 最后`service-a`抛出异常全部回滚 - - - -  - -## 二、运行步骤 - -### 1. 初始化TxManager的数据 - -执行`zlt-doc\sql\tx-manager.sql`和`zlt-doc\sql\tx_logger.sql`脚本 - -### 2. 修改TxManager的配置 - -工程目录:`zlt-transaction\txlcn-tm`,修改nacos、数据库和redis - -### 2. 启动TxManager - -工程目录:`zlt-transaction\txlcn-tm` - -### 3. 初始化demo的数据 - -执行`zlt-demo\txlcn-demo\txlcn-demo.sql`脚本 - -### 4. 修改3个服务的配置 - -`nacos`地址和数据库地址 - - - -  - -## 三、启动模块与测试 - -### 1. 正常提交事务 -访问 发起方提供的Rest接口 `/txlcn?value=the-value`。发现事务全部提交 -![result](https://www.txlcn.org/img/docs/result.png) - -### 2. 回滚事务 -访问 发起方提供的Rest接口 `/txlcn?value=the-value&ex=throw`。发现发起方由本地事务回滚,而参与方ServiceB、ServiceC,由于TX-LCN的协调,数据也回滚了。 -![error_result](https://www.txlcn.org/img/docs/error_result.png) \ No newline at end of file diff --git a/zlt-demo/txlcn-demo/pom.xml b/zlt-demo/txlcn-demo/pom.xml deleted file mode 100644 index 494d258ca..000000000 --- a/zlt-demo/txlcn-demo/pom.xml +++ /dev/null @@ -1,22 +0,0 @@ - - 4.0.0 - - com.zlt - zlt-demo - 5.6.0 - - txlcn-demo - txlcn分布式事务demo - pom - - - txlcn-demo-common - - txlcn-demo-spring-service-a - - txlcn-demo-spring-service-b - - txlcn-demo-spring-service-c - - \ No newline at end of file diff --git a/zlt-demo/txlcn-demo/txlcn-demo-common/pom.xml b/zlt-demo/txlcn-demo/txlcn-demo-common/pom.xml deleted file mode 100644 index c3f6c452e..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-common/pom.xml +++ /dev/null @@ -1,69 +0,0 @@ - - 4.0.0 - - com.zlt - txlcn-demo - 5.6.0 - - txlcn-demo-common - demo-common - demo-common project for Spring Boot - - - - com.codingapi.txlcn - txlcn-tc - - - com.codingapi.txlcn - txlcn-txmsg-netty - - - - com.zlt - zlt-config - - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-config - - - - - com.zlt - zlt-log-spring-boot-starter - - - com.zlt - zlt-db-spring-boot-starter - - - com.zlt - zlt-loadbalancer-spring-boot-starter - - - com.zlt - zlt-sentinel-spring-boot-starter - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-discovery - - - mysql - mysql-connector-java - - - - org.springframework.boot - spring-boot-starter-actuator - - - - org.springframework.boot - spring-boot-starter-web - - - diff --git a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/db/domain/Demo.java b/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/db/domain/Demo.java deleted file mode 100644 index 6178c9767..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/db/domain/Demo.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.txlcn.demo.common.db.domain; - -import com.codingapi.txlcn.common.util.id.RandomUtils; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@AllArgsConstructor -@NoArgsConstructor -@Data -public class Demo { - private Long id; - private String kid = RandomUtils.randomKey(); - private String demoField; - private String groupId; - private Date createTime; - private String appName; - -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/db/mapper/BaseDemoMapper.java b/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/db/mapper/BaseDemoMapper.java deleted file mode 100644 index 9f925a0b5..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/db/mapper/BaseDemoMapper.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.txlcn.demo.common.db.mapper; - -import org.txlcn.demo.common.db.domain.Demo; -import org.apache.ibatis.annotations.Delete; -import org.apache.ibatis.annotations.Insert; -import org.apache.ibatis.annotations.Mapper; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@Mapper -public interface BaseDemoMapper { - - @Insert("insert into t_demo(kid, demo_field, group_id, create_time,app_name) values(#{kid}, #{demoField}, #{groupId}, #{createTime},#{appName})") - void save(Demo demo); - - @Delete("delete from t_demo where id=#{id}") - void deleteById(Long id); -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/FeignConfiguration.java b/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/FeignConfiguration.java deleted file mode 100644 index df3148df4..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/FeignConfiguration.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.txlcn.demo.common.spring; - -import org.springframework.cloud.openfeign.EnableFeignClients; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@ComponentScan -@Configuration -@EnableFeignClients -public class FeignConfiguration { -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/ServiceBClient.java b/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/ServiceBClient.java deleted file mode 100644 index bee926370..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/ServiceBClient.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.txlcn.demo.common.spring; - -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@FeignClient(value = "txlcn-demo-spring-service-b") -public interface ServiceBClient { - - @GetMapping("/rpc") - String rpc(@RequestParam("value") String name); -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/ServiceCClient.java b/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/ServiceCClient.java deleted file mode 100644 index 7c9cb0238..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/java/org/txlcn/demo/common/spring/ServiceCClient.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.txlcn.demo.common.spring; - -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@FeignClient(value = "txlcn-demo-spring-service-c") -public interface ServiceCClient { - - @GetMapping("/rpc") - String rpc(@RequestParam("value") String name); -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/resources/META-INF/spring.factories b/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 086747a22..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-common/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.txlcn.demo.common.spring.FeignConfiguration \ No newline at end of file diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/pom.xml b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/pom.xml deleted file mode 100644 index da9b422d6..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - com.zlt - txlcn-demo - 5.6.0 - - 4.0.0 - - txlcn-demo-spring-service-a - txlcn-demo-spring-service-a - - - - com.zlt - txlcn-demo-common - ${project.version} - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/ServiceAApplication.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/ServiceAApplication.java deleted file mode 100644 index cdbd24a5e..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/ServiceAApplication.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.txlcn.demo; - -import com.central.common.lb.annotation.EnableFeignInterceptor; -import com.codingapi.txlcn.tc.config.EnableDistributedTransaction; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@SpringBootApplication -@EnableDiscoveryClient -@EnableDistributedTransaction -@EnableFeignInterceptor -public class ServiceAApplication { - public static void main(String[] args) { - SpringApplication.run(ServiceAApplication.class, args); - } -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoController.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoController.java deleted file mode 100644 index 3d75f2bca..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoController.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.txlcn.demo.servicea; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@RestController -public class DemoController { - - private final DemoService demoService; - - @Autowired - public DemoController(DemoService demoService) { - this.demoService = demoService; - } - - @RequestMapping("/txlcn") - public String execute(@RequestParam("value") String value, @RequestParam(value = "ex", required = false) String exFlag - , @RequestParam(value = "f", required = false) String flag) { - return demoService.execute(value, exFlag, flag); - } -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoMapper.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoMapper.java deleted file mode 100644 index caeed6f44..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.txlcn.demo.servicea; - -import org.apache.ibatis.annotations.Mapper; -import org.txlcn.demo.common.db.mapper.BaseDemoMapper; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@Mapper -public interface DemoMapper extends BaseDemoMapper { -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoService.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoService.java deleted file mode 100644 index a3d20e8e9..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoService.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.txlcn.demo.servicea; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -public interface DemoService { - - String execute(String value, String ex, String flag); -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoServiceImpl.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoServiceImpl.java deleted file mode 100644 index 366fde3b7..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/java/org/txlcn/demo/servicea/DemoServiceImpl.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.txlcn.demo.servicea; - -import com.codingapi.txlcn.common.util.Transactions; -import com.codingapi.txlcn.tc.annotation.LcnTransaction; -import com.codingapi.txlcn.tracing.TracingContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.txlcn.demo.common.db.domain.Demo; -import org.txlcn.demo.common.spring.ServiceBClient; -import org.txlcn.demo.common.spring.ServiceCClient; - -import javax.annotation.Resource; -import java.util.Date; -import java.util.Objects; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@Service -@Slf4j -public class DemoServiceImpl implements DemoService { - @Resource - private DemoMapper demoMapper; - @Resource - private ServiceBClient serviceBClient; - @Resource - private ServiceCClient serviceCClient; - - @LcnTransaction - @Transactional(rollbackFor = Exception.class) - @Override - public String execute(String value, String exFlag, String flag) { - String dResp = serviceBClient.rpc(value); - // step2. call remote ServiceB - String eResp = serviceCClient.rpc(value); - // step3. execute local transaction - Demo demo = new Demo(); - demo.setGroupId(TracingContext.tracing().groupId()); - demo.setDemoField(value); - demo.setCreateTime(new Date()); - demo.setAppName(Transactions.getApplicationId()); - demoMapper.save(demo); - - // 置异常标志,DTX 回滚 - if (Objects.nonNull(exFlag)) { - throw new IllegalStateException("by exFlag"); - } - - return dResp + " > " + eResp + " > " + "ok-service-a"; - } -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/resources/application.yml b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/resources/application.yml deleted file mode 100644 index 7133edbda..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/resources/application.yml +++ /dev/null @@ -1,25 +0,0 @@ -spring: - datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://${zlt.datasource.ip}:3306/txlcn-demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull - username: ${zlt.datasource.username} - password: ${zlt.datasource.password} - -## tx-manager 配置 -tx-lcn: - ribbon: - loadbalancer: - dtx: - enabled: true - logger: - enabled: true - driver-class-name: com.mysql.cj.jdbc.Driver - jdbc-url: jdbc:mysql://${zlt.datasource.ip}:3306/tx_logger?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull - username: ${zlt.datasource.username} - password: ${zlt.datasource.password} -zlt: - loadbalance: - version: test - isolation: - enabled: true - chooser: com.central.common.lb.chooser.RandomRuleChooser diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/resources/bootstrap.yml b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/resources/bootstrap.yml deleted file mode 100644 index 288bff668..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-a/src/main/resources/bootstrap.yml +++ /dev/null @@ -1,6 +0,0 @@ -server: - port: 12011 - -spring: - application: - name: txlcn-demo-spring-service-a \ No newline at end of file diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/pom.xml b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/pom.xml deleted file mode 100644 index 3b3ddbf45..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - com.zlt - txlcn-demo - 5.6.0 - - 4.0.0 - txlcn-demo-spring-service-b - txlcn-demo-spring-service-b - - - - com.zlt - txlcn-demo-common - ${project.version} - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/ServiceBApplication.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/ServiceBApplication.java deleted file mode 100644 index a2ba3e6d1..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/ServiceBApplication.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.txlcn.demo; - -import com.codingapi.txlcn.tc.config.EnableDistributedTransaction; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@SpringBootApplication -@EnableDiscoveryClient -@EnableDistributedTransaction -public class ServiceBApplication { - public static void main(String[] args) { - SpringApplication.run(ServiceBApplication.class, args); - } -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoController.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoController.java deleted file mode 100644 index a6ede52a2..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoController.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.txlcn.demo.serviceb; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import javax.servlet.http.HttpServletRequest; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@RestController -public class DemoController { - - @Autowired - private DemoService demoService; - - @GetMapping("/rpc") - public String rpc(@RequestParam("value") String value, HttpServletRequest servletRequest) { - return demoService.rpc(value); - } -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoMapper.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoMapper.java deleted file mode 100644 index a0453e257..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.txlcn.demo.serviceb; - -import org.apache.ibatis.annotations.Mapper; -import org.txlcn.demo.common.db.mapper.BaseDemoMapper; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@Mapper -public interface DemoMapper extends BaseDemoMapper { -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoService.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoService.java deleted file mode 100644 index 586e56d9b..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoService.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.txlcn.demo.serviceb; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -public interface DemoService { - - String rpc(String value); -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoServiceImpl.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoServiceImpl.java deleted file mode 100644 index c26e3ddc5..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/java/org/txlcn/demo/serviceb/DemoServiceImpl.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.txlcn.demo.serviceb; - -import com.codingapi.txlcn.common.util.Transactions; -import com.codingapi.txlcn.tc.annotation.DTXPropagation; -import com.codingapi.txlcn.tc.annotation.LcnTransaction; -import com.codingapi.txlcn.tc.annotation.TxcTransaction; -import com.codingapi.txlcn.tracing.TracingContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.txlcn.demo.common.db.domain.Demo; - -import javax.annotation.Resource; -import java.util.Date; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@Service -@Slf4j -public class DemoServiceImpl implements DemoService { - @Resource - private DemoMapper demoMapper; - - @Override - @LcnTransaction - @Transactional(rollbackFor = Exception.class) - public String rpc(String value) { - Demo demo = new Demo(); - demo.setGroupId(TracingContext.tracing().groupId()); - demo.setDemoField(value); - demo.setAppName(Transactions.getApplicationId()); - demo.setCreateTime(new Date()); - demoMapper.save(demo); - return "ok-service-b"; - } -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/resources/application.yml b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/resources/application.yml deleted file mode 100644 index 68d7e81d1..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/resources/application.yml +++ /dev/null @@ -1,24 +0,0 @@ -spring: - datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://${zlt.datasource.ip}:3306/txlcn-demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull - username: ${zlt.datasource.username} - password: ${zlt.datasource.password} - -## tx-manager 配置 -tx-lcn: - ribbon: - loadbalancer: - dtx: - enabled: true - logger: - enabled: true - driver-class-name: com.mysql.cj.jdbc.Driver - jdbc-url: jdbc:mysql://${zlt.datasource.ip}:3306/tx_logger?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull - username: ${zlt.datasource.username} - password: ${zlt.datasource.password} -zlt: - loadbalance: - version: test - isolation: - enabled: true \ No newline at end of file diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/resources/bootstrap.yml b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/resources/bootstrap.yml deleted file mode 100644 index c3d532dcf..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-b/src/main/resources/bootstrap.yml +++ /dev/null @@ -1,6 +0,0 @@ -server: - port: 12002 - -spring: - application: - name: txlcn-demo-spring-service-b \ No newline at end of file diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/pom.xml b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/pom.xml deleted file mode 100644 index 38ba0aaa1..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - com.zlt - txlcn-demo - 5.6.0 - - 4.0.0 - txlcn-demo-spring-service-c - txlcn-demo-spring-service-c - - - - com.zlt - txlcn-demo-common - ${project.version} - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/ServiceCApplication.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/ServiceCApplication.java deleted file mode 100644 index fb0c4058a..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/ServiceCApplication.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.txlcn.demo; - -import com.codingapi.txlcn.tc.config.EnableDistributedTransaction; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@SpringBootApplication -@EnableDiscoveryClient -@EnableDistributedTransaction -public class ServiceCApplication { - public static void main(String[] args) { - SpringApplication.run(ServiceCApplication.class, args); - } -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoController.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoController.java deleted file mode 100644 index dc2ae6531..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoController.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.txlcn.demo.servicec; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@RestController -public class DemoController { - - @Autowired - private DemoService demoService; - - @GetMapping("/rpc") - public String rpc(@RequestParam("value") String value) { - return demoService.rpc(value); - } -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoMapper.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoMapper.java deleted file mode 100644 index 4b7747e7f..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.txlcn.demo.servicec; - -import org.apache.ibatis.annotations.Mapper; -import org.txlcn.demo.common.db.mapper.BaseDemoMapper; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@Mapper -public interface DemoMapper extends BaseDemoMapper { -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoService.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoService.java deleted file mode 100644 index 3be9ce681..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoService.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.txlcn.demo.servicec; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -public interface DemoService { - - String rpc(String value); -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoServiceImpl.java b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoServiceImpl.java deleted file mode 100644 index c137f3021..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/java/org/txlcn/demo/servicec/DemoServiceImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.txlcn.demo.servicec; - -import com.codingapi.txlcn.common.util.Transactions; -import com.codingapi.txlcn.tc.annotation.DTXPropagation; -import com.codingapi.txlcn.tc.annotation.LcnTransaction; -import com.codingapi.txlcn.tc.annotation.TccTransaction; -import com.codingapi.txlcn.tc.support.DTXUserControls; -import com.codingapi.txlcn.tracing.TracingContext; -import com.google.common.collect.Sets; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.txlcn.demo.common.db.domain.Demo; - -import javax.annotation.Resource; -import java.util.Date; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Description: - * Date: 2018/12/25 - * - * @author ujued - */ -@Service -@Slf4j -public class DemoServiceImpl implements DemoService { - @Resource - private DemoMapper demoMapper; - - @Override - @LcnTransaction - @Transactional(rollbackFor = Exception.class) - public String rpc(String value) { - Demo demo = new Demo(); - demo.setDemoField(value); - demo.setCreateTime(new Date()); - demo.setAppName(Transactions.getApplicationId()); - demo.setGroupId(TracingContext.tracing().groupId()); - demoMapper.save(demo); - if ("456".equals(value)) { - throw new IllegalStateException("by test"); - } - return "ok-service-c"; - } -} diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/resources/application.yml b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/resources/application.yml deleted file mode 100644 index cd402049e..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/resources/application.yml +++ /dev/null @@ -1,19 +0,0 @@ -spring: - datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://${zlt.datasource.ip}:3306/txlcn-demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull - username: ${zlt.datasource.username} - password: ${zlt.datasource.password} - -## tx-manager 配置 -tx-lcn: - ribbon: - loadbalancer: - dtx: - enabled: true - logger: - enabled: true - driver-class-name: com.mysql.cj.jdbc.Driver - jdbc-url: jdbc:mysql://${zlt.datasource.ip}:3306/tx_logger?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull - username: ${zlt.datasource.username} - password: ${zlt.datasource.password} \ No newline at end of file diff --git a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/resources/bootstrap.yml b/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/resources/bootstrap.yml deleted file mode 100644 index e3bb0cb0e..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo-spring-service-c/src/main/resources/bootstrap.yml +++ /dev/null @@ -1,6 +0,0 @@ -server: - port: 12003 - -spring: - application: - name: txlcn-demo-spring-service-c \ No newline at end of file diff --git a/zlt-demo/txlcn-demo/txlcn-demo.sql b/zlt-demo/txlcn-demo/txlcn-demo.sql deleted file mode 100644 index a74c95643..000000000 --- a/zlt-demo/txlcn-demo/txlcn-demo.sql +++ /dev/null @@ -1,23 +0,0 @@ --- --- Current Database: `txlcn-demo` --- - -CREATE DATABASE `txlcn-demo` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - -USE `txlcn-demo`; - --- --- Table structure for table `t_demo` --- - -DROP TABLE IF EXISTS `t_demo`; -CREATE TABLE `t_demo` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `kid` varchar(45) DEFAULT NULL, - `demo_field` varchar(255) DEFAULT NULL, - `group_id` varchar(64) DEFAULT NULL, - `unit_id` varchar(32) DEFAULT NULL, - `app_name` varchar(128) DEFAULT NULL, - `create_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; From c7dfbc9e39bca231de5201054ace3af9dc62f861 Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Tue, 1 Aug 2023 17:08:46 +0800 Subject: [PATCH 02/23] =?UTF-8?q?feat:=20=E5=8D=87=E7=BA=A7jdk17?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 28 +++++++++++++++++-- .../com/central/common/utils/RsaUtils.java | 13 ++++----- .../sso/demo/controller/ApiController.java | 5 ++-- zlt-demo/sso-demo/web-sso/pom.xml | 4 +++ .../sso/demo/controller/ApiController.java | 5 ++-- 5 files changed, 38 insertions(+), 17 deletions(-) diff --git a/pom.xml b/pom.xml index 05b23914c..e5c3e8f02 100644 --- a/pom.xml +++ b/pom.xml @@ -9,10 +9,10 @@ pom - 1.8 - 1.8 + 17 + 17 UTF-8 - 8 + 17 2021.1 2.5.14 2020.0.6 @@ -63,6 +63,8 @@ -Djava.security.egd=file:/dev/./urandom -Xms128m -Xmx128m 20.0 + 3.11.0 + 3.1.2 @@ -452,6 +454,26 @@ spring-boot-maven-plugin ${spring-boot-dependencies.version} + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + UTF-8 + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + true + + com.spotify docker-maven-plugin diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/RsaUtils.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/RsaUtils.java index 2e93f5845..3d9b26a24 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/RsaUtils.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/RsaUtils.java @@ -1,7 +1,6 @@ package com.central.common.utils; -import sun.misc.BASE64Decoder; -import sun.misc.BASE64Encoder; +import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import java.security.KeyFactory; @@ -33,8 +32,7 @@ public static String encrypt(String content, PublicKey publicKey) { Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] output = cipher.doFinal(content.getBytes()); - BASE64Encoder encoder = new BASE64Encoder(); - return encoder.encode(output); + return Base64.encodeBase64String(output); }catch (Exception e){ e.printStackTrace(); } @@ -83,8 +81,7 @@ public static String decrypt(String content, PrivateKey privateKey) { Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte [] b = cipher.doFinal(content.getBytes()); - BASE64Encoder encoder = new BASE64Encoder(); - return encoder.encode(b); + return Base64.encodeBase64String(b); } catch (Exception e){ e.printStackTrace(); } @@ -97,7 +94,7 @@ public static String decrypt(String content, PrivateKey privateKey) { */ public static RSAPublicKey getPublicKey(String key) throws Exception { byte[] keyBytes; - keyBytes = (new BASE64Decoder()).decodeBuffer(key); + keyBytes = Base64.decodeBase64(key); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return (RSAPublicKey)keyFactory.generatePublic(keySpec); @@ -109,7 +106,7 @@ public static RSAPublicKey getPublicKey(String key) throws Exception { */ public static PrivateKey getPrivateKey(String key) throws Exception { byte[] keyBytes; - keyBytes = (new BASE64Decoder()).decodeBuffer(key); + keyBytes = Base64.decodeBase64(key); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(keySpec); diff --git a/zlt-demo/sso-demo/oidc-sso/src/main/java/com/sso/demo/controller/ApiController.java b/zlt-demo/sso-demo/oidc-sso/src/main/java/com/sso/demo/controller/ApiController.java index 74103b053..04b2b1c5d 100644 --- a/zlt-demo/sso-demo/oidc-sso/src/main/java/com/sso/demo/controller/ApiController.java +++ b/zlt-demo/sso-demo/oidc-sso/src/main/java/com/sso/demo/controller/ApiController.java @@ -21,7 +21,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; -import sun.misc.BASE64Encoder; +import org.apache.commons.codec.binary.Base64; import javax.servlet.http.HttpServletRequest; import java.nio.charset.StandardCharsets; @@ -217,8 +217,7 @@ private RSAPublicKey getPubKeyByRemote() throws Exception { */ private String getBase64ClientParam() { byte[] authorization = (clientId + ":" + clientSecret).getBytes(StandardCharsets.UTF_8); - BASE64Encoder encoder = new BASE64Encoder(); - return encoder.encode(authorization); + return Base64.encodeBase64String(authorization); } @Data diff --git a/zlt-demo/sso-demo/web-sso/pom.xml b/zlt-demo/sso-demo/web-sso/pom.xml index 190fdbf8f..78ad2b096 100644 --- a/zlt-demo/sso-demo/web-sso/pom.xml +++ b/zlt-demo/sso-demo/web-sso/pom.xml @@ -22,6 +22,10 @@ org.springframework.cloud spring-cloud-context + + commons-codec + commons-codec + diff --git a/zlt-demo/sso-demo/web-sso/src/main/java/com/sso/demo/controller/ApiController.java b/zlt-demo/sso-demo/web-sso/src/main/java/com/sso/demo/controller/ApiController.java index b5b050667..f15bbdc98 100644 --- a/zlt-demo/sso-demo/web-sso/src/main/java/com/sso/demo/controller/ApiController.java +++ b/zlt-demo/sso-demo/web-sso/src/main/java/com/sso/demo/controller/ApiController.java @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; -import sun.misc.BASE64Encoder; +import org.apache.commons.codec.binary.Base64; import javax.servlet.http.HttpServletRequest; import java.io.UnsupportedEncodingException; @@ -73,8 +73,7 @@ public Map getAccessToken(String code) throws UnsupportedEncodingException { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); byte[] authorization = (clientId + ":" + clientSecret).getBytes("UTF-8"); - BASE64Encoder encoder = new BASE64Encoder(); - String base64Auth = encoder.encode(authorization); + String base64Auth = Base64.encodeBase64String(authorization); headers.add("Authorization", "Basic " + base64Auth); MultiValueMap param = new LinkedMultiValueMap<>(); From ec616bc1b5ffc125e47dfd29c6cf3964fad5c78a Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Fri, 10 Nov 2023 14:59:27 +0800 Subject: [PATCH 03/23] =?UTF-8?q?feat:=20=E5=8D=87=E7=BA=A7SpringBoot?= =?UTF-8?q?=E5=92=8CSpringCloud=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 49 +++- .../controller/SysGeneratorController.java | 2 +- .../client/feign/AggregationService.java | 2 +- .../search/client/feign/SearchService.java | 2 +- .../SearchServiceFallbackFactory.java | 2 + .../admin/properties/IndexProperties.java | 2 + .../src/main/resources/application.yml | 7 +- .../user/controller/SysUserController.java | 2 +- .../pom.xml | 9 +- .../config/DefaultResourceServerConf.java | 12 +- .../config/DefaultSecurityHandlerConfig.java | 7 +- .../common/config/WcAuthConfigurator.java | 3 +- .../common/properties/SecurityProperties.java | 2 + .../properties/TokenStoreProperties.java | 2 + .../central/oauth2/common/util/AuthUtils.java | 2 +- .../com/central/common/feign/UserService.java | 2 +- .../fallback/UserServiceFallbackFactory.java | 2 + .../properties/DataScopeProperties.java | 2 + .../common/properties/TenantProperties.java | 2 + .../resolver/ClientArgumentResolver.java | 2 +- .../resolver/TokenArgumentResolver.java | 11 +- .../com/central/common/utils/AddrUtil.java | 2 +- .../com/central/common/utils/ExcelUtil.java | 2 +- .../central/common/utils/LoginUserUtils.java | 2 +- .../central/common/utils/PwdEncoderUtil.java | 24 +- .../central/common/utils/ResponseUtil.java | 2 +- .../zlt-common-spring-boot-starter/pom.xml | 6 - .../common/filter/LoginUserFilter.java | 10 +- .../central/common/filter/TenantFilter.java | 10 +- .../MybatisPlusAutoFillProperties.java | 2 + .../central/es/config/RestAutoConfigure.java | 93 +++---- .../properties/RestClientPoolProperties.java | 2 + .../pom.xml | 4 +- .../common/lb/RestTemplateAutoConfigure.java | 37 +-- .../lb/config/FeignHttpInterceptorConfig.java | 2 +- .../lb/config/RestTemplateProperties.java | 2 + .../zlt-log-spring-boot-starter/pom.xml | 18 +- .../central/log/aspect/AuditLogAspect.java | 2 +- .../log/properties/AuditLogProperties.java | 2 + .../log/properties/LogDbProperties.java | 4 + .../log/properties/TraceProperties.java | 2 + .../com/central/log/trace/WebTraceFilter.java | 10 +- .../main/java/org/slf4j/TtlMDCAdapter.java | 179 ++++++------ .../src/main/resources/logback-spring.xml | 1 - .../oss/properties/FileServerProperties.java | 2 + .../common/redis/RedisAutoConfigure.java | 8 +- .../redis/lock/RedissonDistributedLock.java | 2 + .../properties/CacheManagerProperties.java | 2 + .../redis/template/RedisRepository.java | 2 + .../main/resources/META-INF/spring.factories | 4 +- .../config/SentinelAutoConfigure.java | 2 +- .../swagger2/SwaggerAutoConfiguration.java | 8 +- .../common/swagger2/SwaggerProperties.java | 2 + .../properties/ZookeeperProperty.java | 2 + .../main/resources/application-dev.properties | 6 +- .../resources/application-prod.properties | 8 +- .../resources/application-test.properties | 8 +- .../src/main/resources/application.properties | 10 +- zlt-demo/dubbo-demo/pom.xml | 1 + .../rocketmq/demo/config/RocketMqConfig.java | 24 -- .../rocketmq/demo/service/ReceiveService.java | 30 +- .../src/main/resources/application.yml | 27 +- .../rocketmq/demo/config/RocketMqConfig.java | 20 -- .../rocketmq/demo/service/SenderService.java | 17 +- .../src/main/resources/application.yml | 23 +- .../rocketmq/demo/config/RocketMqConfig.java | 23 -- .../demo/controller/OrderController.java | 23 +- .../OrderTransactionListenerImpl.java | 31 ++- .../service/impl/IntegralReceiveService.java | 42 +-- .../src/main/resources/application.yml | 46 ++-- .../sso/demo/controller/ApiController.java | 2 +- .../com/sso/demo/config/SecurityConfig.java | 12 +- .../demo/config/SsoLogoutSuccessHandler.java | 4 +- .../sso/demo/controller/ApiController.java | 2 +- .../controller/TestWebSocketController.java | 6 +- zlt-gateway/sc-gateway/pom.xml | 36 +-- .../config/ResourceServerConfiguration.java | 17 +- .../CustomErrorWebFluxAutoConfiguration.java | 50 +--- .../error/JsonErrorWebExceptionHandler.java | 2 +- .../gateway/feign/AsynMenuService.java | 3 +- .../central/gateway/feign/MenuService.java | 2 +- .../gateway/swagger/SwaggerAggProperties.java | 62 ----- .../gateway/swagger/SwaggerHandler.java | 57 ---- .../gateway/swagger/SwaggerProvider.java | 73 ----- .../src/main/resources/bootstrap.yml | 4 +- .../monitor/config/SecuritySecureConfig.java | 16 +- zlt-uaa/pom.xml | 19 +- .../main/java/com/central/UaaServerApp.java | 2 + .../config/AuthorizationServerConfig.java | 178 ------------ .../central/oauth/config/SecurityConfig.java | 167 ------------ .../oauth/config/SecurityHandlerConfig.java | 86 ------ .../oauth/config/TokenGranterConfig.java | 179 ------------ .../central/oauth/config/WebMvcConfig.java | 6 +- .../oauth/controller/ClientController.java | 16 +- .../oauth/controller/TokensController.java | 73 ----- .../controller/ValidateCodeController.java | 5 +- .../filter/LoginProcessSetTenantFilter.java | 66 ----- .../oauth/filter/OauthTokenAspect.java | 93 ------- .../oauth/granter/MobilePwdGranter.java | 53 ---- .../central/oauth/granter/OpenIdGranter.java | 49 ---- .../oauth/granter/PwdImgCodeGranter.java | 42 --- .../oauth/handler/OauthLogoutHandler.java | 62 ----- .../handler/OauthLogoutSuccessHandler.java | 59 ---- .../IDecryptParamHandler.java | 48 ---- .../RsaDecryptParamHandler.java | 54 ---- .../listener/RedisKeyExpirationListener.java | 112 -------- .../mobile/MobileAuthenticationProvider.java | 46 ---- .../MobileAuthenticationSecurityConfig.java | 37 --- .../CustomAuthenticationDetailsSource.java | 31 --- .../openid/OpenIdAuthenticationProvider.java | 40 --- .../OpenIdAuthenticationSecurityConfig.java | 30 -- .../PasswordAuthenticationProvider.java | 148 ---------- .../central/oauth/service/IClientService.java | 58 ++-- .../oauth/service/IValidateCodeService.java | 78 +++--- .../service/impl/CustomTokenServices.java | 258 ------------------ .../impl/RedisAuthorizationCodeServices.java | 56 ---- .../impl/RedisClientDetailsService.java | 110 -------- .../service/impl/RedisTokensServiceImpl.java | 91 ------ .../service/impl/UnifiedLogoutService.java | 112 -------- .../impl/UserDetailServiceFactory.java | 53 ---- ...serDetailsByNameServiceFactoryWrapper.java | 59 ---- .../oauth/tenant/OauthAuthorizeAspect.java | 64 ----- .../tenant/TenantAuthenticationProvider.java | 32 --- .../TenantAuthenticationSecurityConfig.java | 35 --- ...tUsernamePasswordAuthenticationFilter.java | 59 ---- .../oauth/utils/OidcIdTokenBuilder.java | 132 --------- .../central/oauth/utils/UsernameHolder.java | 25 -- zlt-uaa/src/main/resources/application.yml | 19 +- .../oauth2/common/util/JwtUtilsTest.java | 6 +- zlt-web/react-web/pom.xml | 4 +- .../main/java/ui/ReactUiBootApplication.java | 13 - .../config/StaticResourceConfiguration.java | 32 --- .../main/java/ui/properties/UiProperties.java | 21 -- 133 files changed, 628 insertions(+), 3655 deletions(-) delete mode 100644 zlt-demo/rocketmq-demo/rocketmq-consume/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java delete mode 100644 zlt-demo/rocketmq-demo/rocketmq-produce/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java delete mode 100644 zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java delete mode 100644 zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerAggProperties.java delete mode 100644 zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerHandler.java delete mode 100644 zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerProvider.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/config/SecurityHandlerConfig.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/config/TokenGranterConfig.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/controller/TokensController.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/filter/LoginProcessSetTenantFilter.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/filter/OauthTokenAspect.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/granter/MobilePwdGranter.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/granter/OpenIdGranter.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/granter/PwdImgCodeGranter.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutHandler.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutSuccessHandler.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/handler/decryptParamHandler/IDecryptParamHandler.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/handler/decryptParamHandler/RsaDecryptParamHandler.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/listener/RedisKeyExpirationListener.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/mobile/MobileAuthenticationProvider.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/mobile/MobileAuthenticationSecurityConfig.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/model/CustomAuthenticationDetailsSource.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/openid/OpenIdAuthenticationProvider.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/openid/OpenIdAuthenticationSecurityConfig.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/password/PasswordAuthenticationProvider.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/CustomTokenServices.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisAuthorizationCodeServices.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisClientDetailsService.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/UnifiedLogoutService.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceFactory.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailsByNameServiceFactoryWrapper.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/tenant/OauthAuthorizeAspect.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/tenant/TenantAuthenticationProvider.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/tenant/TenantAuthenticationSecurityConfig.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/tenant/TenantUsernamePasswordAuthenticationFilter.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/utils/OidcIdTokenBuilder.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/utils/UsernameHolder.java delete mode 100644 zlt-web/react-web/src/main/java/ui/ReactUiBootApplication.java delete mode 100644 zlt-web/react-web/src/main/java/ui/config/StaticResourceConfiguration.java delete mode 100644 zlt-web/react-web/src/main/java/ui/properties/UiProperties.java diff --git a/pom.xml b/pom.xml index e5c3e8f02..f2c8f4532 100644 --- a/pom.xml +++ b/pom.xml @@ -13,21 +13,21 @@ 17 UTF-8 17 - 2021.1 - 2.5.14 - 2020.0.6 + 2022.0.0.0 + 3.0.9 + 2022.0.3 4.4 2.0.1 0.9.1 - 1.2.6 + 1.2.18 1.14 3.1.0 2.3.8.RELEASE 1.1.0.RELEASE - 3.16.1 + 3.23.2 1.6.2 5.7.20 - 3.5.1 + 3.5.3.1 3.8.1 7.2.28 4.1.3 @@ -38,7 +38,7 @@ 5.0.2.RELEASE 1.27.2 1.21 - 2.12.1 + 2.14.3 1.0.2 1.9.4 1.1.6.RELEASE @@ -46,8 +46,8 @@ 4.0.1 4.2.3 7.13.4 - 2.0.5 - 6.2.0.Final + 3.0.3 + 8.0.1.Final 2.7.8 5.1.0 2.13.4 @@ -65,6 +65,10 @@ 20.0 3.11.0 3.1.2 + 8.0.33 + 1.3.2 + 10.1.11 + 5.2.1 @@ -97,6 +101,16 @@ org.springframework.cloud spring-cloud-starter-bootstrap + + javax.annotation + javax.annotation-api + ${javax.annotation-api.version} + + + org.apache.tomcat.embed + tomcat-embed-core + ${tomcat-embed-core.version} + @@ -411,6 +425,11 @@ commons-configuration ${commons-configuration.version} + + mysql + mysql-connector-java + ${mysql-connector-java.version} + org.springframework.boot @@ -443,6 +462,18 @@ jackson-core ${jackson-databind.version} + + org.apache.httpcomponents.client5 + httpclient5 + ${httpclient.version} + + diff --git a/zlt-business/code-generator/src/main/java/com/central/generator/controller/SysGeneratorController.java b/zlt-business/code-generator/src/main/java/com/central/generator/controller/SysGeneratorController.java index 4f53ce017..f4c1641e0 100644 --- a/zlt-business/code-generator/src/main/java/com/central/generator/controller/SysGeneratorController.java +++ b/zlt-business/code-generator/src/main/java/com/central/generator/controller/SysGeneratorController.java @@ -3,7 +3,7 @@ import java.io.IOException; import java.util.Map; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; import com.central.common.model.PageResult; import com.central.generator.service.SysGeneratorService; diff --git a/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/AggregationService.java b/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/AggregationService.java index 117de292c..ee4d6bd60 100644 --- a/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/AggregationService.java +++ b/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/AggregationService.java @@ -11,7 +11,7 @@ /** * @author zlt */ -@FeignClient(name = ServiceNameConstants.SEARCH_SERVICE, fallbackFactory = SearchServiceFallbackFactory.class, decode404 = true) +@FeignClient(name = ServiceNameConstants.SEARCH_SERVICE, fallbackFactory = SearchServiceFallbackFactory.class, dismiss404 = true) public interface AggregationService { /** * 查询文档列表 diff --git a/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/SearchService.java b/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/SearchService.java index b094f5c25..9ea09f85a 100644 --- a/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/SearchService.java +++ b/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/SearchService.java @@ -11,7 +11,7 @@ /** * @author zlt */ -@FeignClient(name = ServiceNameConstants.SEARCH_SERVICE, fallbackFactory = SearchServiceFallbackFactory.class, decode404 = true) +@FeignClient(name = ServiceNameConstants.SEARCH_SERVICE, fallbackFactory = SearchServiceFallbackFactory.class, dismiss404 = true) public interface SearchService { /** * 查询文档列表 diff --git a/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/fallback/SearchServiceFallbackFactory.java b/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/fallback/SearchServiceFallbackFactory.java index ad2cb5b3a..bea16ce3a 100644 --- a/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/fallback/SearchServiceFallbackFactory.java +++ b/zlt-business/search-center/search-client/src/main/java/com/central/search/client/feign/fallback/SearchServiceFallbackFactory.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.JsonNode; import org.springframework.cloud.openfeign.FallbackFactory; import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; /** * searchService降级工场 @@ -12,6 +13,7 @@ * @author zlt */ @Slf4j +@Component public class SearchServiceFallbackFactory implements FallbackFactory { @Override public SearchService create(Throwable throwable) { diff --git a/zlt-business/search-center/search-server/src/main/java/com/central/admin/properties/IndexProperties.java b/zlt-business/search-center/search-server/src/main/java/com/central/admin/properties/IndexProperties.java index 61d5d1291..0a0edbe12 100644 --- a/zlt-business/search-center/search-server/src/main/java/com/central/admin/properties/IndexProperties.java +++ b/zlt-business/search-center/search-server/src/main/java/com/central/admin/properties/IndexProperties.java @@ -4,6 +4,7 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; /** * 索引配置 @@ -14,6 +15,7 @@ @Getter @ConfigurationProperties(prefix = "zlt.indices") @RefreshScope +@Component public class IndexProperties { /** * 配置过滤的索引名:默认只显示这些索引 diff --git a/zlt-business/search-center/search-server/src/main/resources/application.yml b/zlt-business/search-center/search-server/src/main/resources/application.yml index ef580d744..e7502fd30 100644 --- a/zlt-business/search-center/search-server/src/main/resources/application.yml +++ b/zlt-business/search-center/search-server/src/main/resources/application.yml @@ -1,9 +1,8 @@ spring: elasticsearch: - rest: - uris: ${zlt.elasticsearch.uris} - username: ${zlt.elasticsearch.username} - password: ${zlt.elasticsearch.password} + uris: ${zlt.elasticsearch.uris} + username: ${zlt.elasticsearch.username} + password: ${zlt.elasticsearch.password} zlt: indices: diff --git a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java index eb8ffede7..12eeace98 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java +++ b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java @@ -34,7 +34,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; /** * @author 作者 owen E-mail: 624191343@qq.com diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml b/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml index cfc7753a3..a303d2e9f 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml @@ -37,15 +37,14 @@ spring-boot-configuration-processor true - - javax.servlet - javax.servlet-api - provided - org.apache.tomcat.embed tomcat-embed-websocket true + + javax.servlet + javax.servlet-api + diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java index 71e6d114f..f84bbe858 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java @@ -5,7 +5,7 @@ import org.springframework.context.annotation.Import; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; +import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; @@ -52,10 +52,10 @@ public void configure(ResourceServerSecurityConfigurer resources) { @Override public void configure(HttpSecurity http) throws Exception { - ExpressionUrlAuthorizationConfigurer.AuthorizedUrl authorizedUrl = setHttp(http) - .authorizeRequests() - .antMatchers(securityProperties.getIgnore().getUrls()).permitAll() - .antMatchers(HttpMethod.OPTIONS).permitAll() + AuthorizeHttpRequestsConfigurer.AuthorizedUrl authorizedUrl = setHttp(http) + .authorizeHttpRequests() + .requestMatchers(securityProperties.getIgnore().getUrls()).permitAll() + .requestMatchers(HttpMethod.OPTIONS).permitAll() .anyRequest(); setAuthenticate(authorizedUrl); @@ -72,7 +72,7 @@ public void configure(HttpSecurity http) throws Exception { * url权限控制,默认是认证就通过,可以重写实现个性化 * @param authorizedUrl */ - public HttpSecurity setAuthenticate(ExpressionUrlAuthorizationConfigurer.AuthorizedUrl authorizedUrl) { + public HttpSecurity setAuthenticate(AuthorizeHttpRequestsConfigurer.AuthorizedUrl authorizedUrl) { return authorizedUrl.authenticated().and(); } diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultSecurityHandlerConfig.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultSecurityHandlerConfig.java index bd9904342..d12d9cadb 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultSecurityHandlerConfig.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultSecurityHandlerConfig.java @@ -10,9 +10,8 @@ import org.springframework.security.web.AuthenticationEntryPoint; import javax.annotation.Resource; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; /** @@ -47,7 +46,7 @@ public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler() { return new OAuth2AccessDeniedHandler() { @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException) throws IOException, ServletException { + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException) throws IOException { ResponseUtil.responseFailed(objectMapper, response, authException.getMessage()); } }; diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/WcAuthConfigurator.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/WcAuthConfigurator.java index 26caf368d..c1f979e1d 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/WcAuthConfigurator.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/WcAuthConfigurator.java @@ -1,12 +1,11 @@ package com.central.oauth2.common.config; import com.central.oauth2.common.util.AuthUtils; +import jakarta.websocket.server.ServerEndpointConfig; import lombok.extern.slf4j.Slf4j; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import javax.websocket.server.ServerEndpointConfig; - /** * webSocket鉴权配置 * diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java index 4e17c3c11..14391e651 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java @@ -4,6 +4,7 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; /** * @author zlt @@ -17,6 +18,7 @@ @Getter @ConfigurationProperties(prefix = "zlt.security") @RefreshScope +@Component public class SecurityProperties { private AuthProperties auth = new AuthProperties(); diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java index 0f2687fbb..3534835f5 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java @@ -4,6 +4,7 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; /** * Token配置 @@ -19,6 +20,7 @@ @Getter @ConfigurationProperties(prefix = "zlt.oauth2.token.store") @RefreshScope +@Component public class TokenStoreProperties { /** * token存储类型(redis/db/authJwt/resJwt) diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java index 2ed47e131..695abdfb3 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java @@ -16,7 +16,7 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.TokenStore; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.nio.charset.StandardCharsets; import java.util.*; diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/UserService.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/UserService.java index 0d0ed3c61..c5d9b8971 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/UserService.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/UserService.java @@ -15,7 +15,7 @@ /** * @author zlt */ -@FeignClient(name = ServiceNameConstants.USER_SERVICE, fallbackFactory = UserServiceFallbackFactory.class, decode404 = true) +@FeignClient(name = ServiceNameConstants.USER_SERVICE, fallbackFactory = UserServiceFallbackFactory.class, dismiss404 = true) public interface UserService { /** * feign rpc访问远程/users/{username}接口 diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java index 4a249494f..12d5f7cea 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java @@ -6,6 +6,7 @@ import com.central.common.model.SysUser; import org.springframework.cloud.openfeign.FallbackFactory; import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; import java.util.Collections; import java.util.List; @@ -17,6 +18,7 @@ * @date 2019/1/18 */ @Slf4j +@Component public class UserServiceFallbackFactory implements FallbackFactory { @Override public UserService create(Throwable throwable) { diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/DataScopeProperties.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/DataScopeProperties.java index 2d3720a33..d2170e81a 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/DataScopeProperties.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/DataScopeProperties.java @@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableSet; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; import java.util.Collections; import java.util.HashSet; @@ -16,6 +17,7 @@ */ @ConfigurationProperties(prefix = "zlt.datascope") @Data +@Component public class DataScopeProperties { private static final Set INGORE_SQL_ID = ImmutableSet .of("com.central.user.mapper.findRolesByUserId" diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/TenantProperties.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/TenantProperties.java index e749a1f33..51bdedaa3 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/TenantProperties.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/TenantProperties.java @@ -4,6 +4,7 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; @@ -17,6 +18,7 @@ @Getter @ConfigurationProperties(prefix = "zlt.tenant") @RefreshScope +@Component public class TenantProperties { /** * 是否开启多租户 diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/ClientArgumentResolver.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/ClientArgumentResolver.java index 4278a0580..63aa0adfe 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/ClientArgumentResolver.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/ClientArgumentResolver.java @@ -10,7 +10,7 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; /** * head中的应用参数注入clientId中 diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/TokenArgumentResolver.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/TokenArgumentResolver.java index d035c7087..97d85ef83 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/TokenArgumentResolver.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/TokenArgumentResolver.java @@ -1,27 +1,18 @@ package com.central.common.resolver; -import cn.hutool.core.util.StrUtil; import com.central.common.annotation.LoginUser; import com.central.common.constant.SecurityConstants; import com.central.common.feign.UserService; -import com.central.common.model.SysRole; import com.central.common.model.SysUser; import com.central.common.utils.LoginUserUtils; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.core.MethodParameter; -import org.springframework.security.authentication.AnonymousAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; -import javax.servlet.http.HttpServletRequest; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - /** * Token转化SysUser * diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/AddrUtil.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/AddrUtil.java index 891c89e43..fadf1c294 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/AddrUtil.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/AddrUtil.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.net.InetAddress; import java.net.UnknownHostException; diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/ExcelUtil.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/ExcelUtil.java index fa4d2741f..a9ac4a20c 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/ExcelUtil.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/ExcelUtil.java @@ -9,7 +9,7 @@ import org.apache.poi.ss.usermodel.Workbook; import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.net.URLEncoder; diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java index b05ecdfd5..4d6c8a7dd 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java @@ -5,13 +5,13 @@ import com.central.common.feign.UserService; import com.central.common.model.SysRole; import com.central.common.model.SysUser; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/PwdEncoderUtil.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/PwdEncoderUtil.java index 343a80705..cd7732719 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/PwdEncoderUtil.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/PwdEncoderUtil.java @@ -3,9 +3,7 @@ import com.central.common.passwordEncoder.SM3PasswordEncoder; import org.springframework.security.crypto.argon2.Argon2PasswordEncoder; 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.password.*; import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder; import org.springframework.util.Assert; @@ -26,16 +24,16 @@ public class PwdEncoderUtil { public static PasswordEncoder getDelegatingPasswordEncoder(String encodingId) { Map encoders = new HashMap<>(); encoders.put("bcrypt", new BCryptPasswordEncoder()); - encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder()); - encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder()); - encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5")); - encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance()); - encoders.put("pbkdf2", new Pbkdf2PasswordEncoder()); - encoders.put("scrypt", new SCryptPasswordEncoder()); - encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1")); - encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256")); - encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder()); - encoders.put("argon2", new Argon2PasswordEncoder()); + encoders.put("ldap", new LdapShaPasswordEncoder()); + encoders.put("MD4", new Md4PasswordEncoder()); + encoders.put("MD5", new MessageDigestPasswordEncoder("MD5")); + encoders.put("noop", NoOpPasswordEncoder.getInstance()); + encoders.put("pbkdf2",Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8()); + encoders.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8()); + encoders.put("SHA-1", new MessageDigestPasswordEncoder("SHA-1")); + encoders.put("SHA-256", new MessageDigestPasswordEncoder("SHA-256")); + encoders.put("sha256", new StandardPasswordEncoder()); + encoders.put("argon2", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8()); encoders.put("SM3", new SM3PasswordEncoder()); Assert.isTrue(encoders.containsKey(encodingId), encodingId + " is not found in idToPasswordEncoder"); diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/ResponseUtil.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/ResponseUtil.java index 2da8db68e..9a4ab54d9 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/ResponseUtil.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/ResponseUtil.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.http.MediaType; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.Writer; diff --git a/zlt-commons/zlt-common-spring-boot-starter/pom.xml b/zlt-commons/zlt-common-spring-boot-starter/pom.xml index f86bee97e..e8f5bbfc8 100644 --- a/zlt-commons/zlt-common-spring-boot-starter/pom.xml +++ b/zlt-commons/zlt-common-spring-boot-starter/pom.xml @@ -14,11 +14,5 @@ com.zlt zlt-common-core - - - javax.servlet - javax.servlet-api - true - \ No newline at end of file diff --git a/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/LoginUserFilter.java b/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/LoginUserFilter.java index 21c9a3ebd..920793cee 100644 --- a/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/LoginUserFilter.java +++ b/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/LoginUserFilter.java @@ -3,15 +3,15 @@ import com.central.common.context.LoginUserContextHolder; import com.central.common.model.SysUser; import com.central.common.utils.LoginUserUtils; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.core.annotation.Order; import org.springframework.web.filter.OncePerRequestFilter; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** diff --git a/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/TenantFilter.java b/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/TenantFilter.java index 506faa244..939c9ced1 100644 --- a/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/TenantFilter.java +++ b/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/TenantFilter.java @@ -4,14 +4,14 @@ import com.central.common.constant.CommonConstant; import com.central.common.constant.SecurityConstants; import com.central.common.context.TenantContextHolder; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.web.filter.OncePerRequestFilter; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** diff --git a/zlt-commons/zlt-db-spring-boot-starter/src/main/java/com/central/db/properties/MybatisPlusAutoFillProperties.java b/zlt-commons/zlt-db-spring-boot-starter/src/main/java/com/central/db/properties/MybatisPlusAutoFillProperties.java index 44b88f0f4..e2b9432a5 100644 --- a/zlt-commons/zlt-db-spring-boot-starter/src/main/java/com/central/db/properties/MybatisPlusAutoFillProperties.java +++ b/zlt-commons/zlt-db-spring-boot-starter/src/main/java/com/central/db/properties/MybatisPlusAutoFillProperties.java @@ -4,6 +4,7 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; /** * mybatis-plus 配置 @@ -18,6 +19,7 @@ @Getter @ConfigurationProperties(prefix = "zlt.mybatis-plus.auto-fill") @RefreshScope +@Component public class MybatisPlusAutoFillProperties { /** * 是否开启自动填充字段 diff --git a/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/config/RestAutoConfigure.java b/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/config/RestAutoConfigure.java index 407118359..547ca828f 100644 --- a/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/config/RestAutoConfigure.java +++ b/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/config/RestAutoConfigure.java @@ -1,19 +1,20 @@ package com.central.es.config; import com.central.es.properties.RestClientPoolProperties; +import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.impl.client.BasicCredentialsProvider; +import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestHighLevelClient; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientProperties; -import org.springframework.boot.autoconfigure.elasticsearch.RestClientBuilderCustomizer; +import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.context.properties.PropertyMapper; -import org.springframework.context.annotation.Bean; -import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; + +import javax.annotation.Resource; +import java.util.List; /** * es自动配置 @@ -25,51 +26,45 @@ * Github: https://github.com/zlt2000 */ @EnableConfigurationProperties(RestClientPoolProperties.class) -public class RestAutoConfigure { - @Bean - public RestClientBuilderCustomizer restClientBuilderCustomizer(RestClientPoolProperties poolProperties - , ElasticsearchRestClientProperties restProperties) { - return (builder) -> { - setRequestConfig(builder, poolProperties); - - setHttpClientConfig(builder, poolProperties, restProperties); - }; - } +public class RestAutoConfigure extends AbstractElasticsearchConfiguration { + private final static String SCHEME = "http"; + private final static String URI_SPLIT = ":"; - /** - * 异步httpclient连接延时配置 - */ - private void setRequestConfig(RestClientBuilder builder, RestClientPoolProperties poolProperties){ - builder.setRequestConfigCallback(requestConfigBuilder -> { - requestConfigBuilder.setConnectTimeout(poolProperties.getConnectTimeOut()) - .setSocketTimeout(poolProperties.getSocketTimeOut()) - .setConnectionRequestTimeout(poolProperties.getConnectionRequestTimeOut()); - return requestConfigBuilder; - }); - } - - /** - * 异步httpclient连接数配置 - */ - private void setHttpClientConfig(RestClientBuilder builder, RestClientPoolProperties poolProperties, ElasticsearchRestClientProperties restProperties){ - builder.setHttpClientConfigCallback(httpClientBuilder -> { - httpClientBuilder.setMaxConnTotal(poolProperties.getMaxConnectNum()) - .setMaxConnPerRoute(poolProperties.getMaxConnectPerRoute()); + @Resource + private ElasticsearchProperties restProperties; - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - map.from(restProperties::getUsername).to(username -> { - CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, - new UsernamePasswordCredentials(username, restProperties.getPassword())); - httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); - }); - return httpClientBuilder; - }); - } + @Resource + private RestClientPoolProperties poolProperties; - @Bean - @ConditionalOnMissingBean - public ElasticsearchRestTemplate elasticsearchRestTemplate(RestHighLevelClient restHighLevelClient) { - return new ElasticsearchRestTemplate(restHighLevelClient); + @Override + public RestHighLevelClient elasticsearchClient() { + List urlArr = restProperties.getUris(); + HttpHost[] httpPostArr = new HttpHost[urlArr.size()]; + for (int i = 0; i < urlArr.size(); i++) { + HttpHost httpHost = new HttpHost(urlArr.get(i).split(URI_SPLIT)[0].trim(), + Integer.parseInt(urlArr.get(i).split(URI_SPLIT)[1].trim()), SCHEME); + httpPostArr[i] = httpHost; + } + final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(AuthScope.ANY, + new UsernamePasswordCredentials(restProperties.getUsername(), restProperties.getPassword())); + RestClientBuilder builder = RestClient.builder(httpPostArr) + // 异步httpclient连接数配置 + .setHttpClientConfigCallback(httpClientBuilder -> { + // 账号密码登录 + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + // httpclient连接数配置 + httpClientBuilder.setMaxConnTotal(poolProperties.getMaxConnectNum()) + .setMaxConnPerRoute(poolProperties.getMaxConnectPerRoute()); + return httpClientBuilder; + }) + // 异步httpclient连接延时配置 + .setRequestConfigCallback(requestConfigBuilder -> { + requestConfigBuilder.setConnectTimeout(poolProperties.getConnectTimeOut()) + .setSocketTimeout(poolProperties.getSocketTimeOut()) + .setConnectionRequestTimeout(poolProperties.getConnectionRequestTimeOut()); + return requestConfigBuilder; + }); + return new RestHighLevelClient(builder); } } diff --git a/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/properties/RestClientPoolProperties.java b/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/properties/RestClientPoolProperties.java index 16b9d2328..d1d98f84d 100644 --- a/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/properties/RestClientPoolProperties.java +++ b/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/properties/RestClientPoolProperties.java @@ -4,6 +4,7 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; /** * es的httpClient连接池配置 @@ -18,6 +19,7 @@ @Getter @ConfigurationProperties(prefix = "zlt.elasticsearch.rest-pool") @RefreshScope +@Component public class RestClientPoolProperties { /** * 链接建立超时时间 diff --git a/zlt-commons/zlt-loadbalancer-spring-boot-starter/pom.xml b/zlt-commons/zlt-loadbalancer-spring-boot-starter/pom.xml index 0b9a91c96..f0390a899 100644 --- a/zlt-commons/zlt-loadbalancer-spring-boot-starter/pom.xml +++ b/zlt-commons/zlt-loadbalancer-spring-boot-starter/pom.xml @@ -30,8 +30,8 @@ true - org.apache.httpcomponents - httpclient + org.apache.httpcomponents.client5 + httpclient5 javax.servlet diff --git a/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/RestTemplateAutoConfigure.java b/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/RestTemplateAutoConfigure.java index b5fe3ef3d..818755371 100644 --- a/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/RestTemplateAutoConfigure.java +++ b/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/RestTemplateAutoConfigure.java @@ -1,20 +1,21 @@ package com.central.common.lb; import com.central.common.lb.config.RestTemplateProperties; -import org.apache.http.client.HttpClient; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.socket.ConnectionSocketFactory; +import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.core5.http.config.Registry; +import org.apache.hc.core5.http.config.RegistryBuilder; +import org.apache.hc.core5.util.Timeout; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @@ -26,6 +27,7 @@ * Blog: https://zlt2000.gitee.io * Github: https://github.com/zlt2000 */ +@Configuration @EnableConfigurationProperties(RestTemplateProperties.class) public class RestTemplateAutoConfigure { @Autowired @@ -61,19 +63,22 @@ public HttpClient httpClient() { // 同路由并发数20 connectionManager.setDefaultMaxPerRoute(restTemplateProperties.getMaxPerRoute()); - RequestConfig requestConfig = RequestConfig.custom() + ConnectionConfig connectConfig = ConnectionConfig.custom() // 读超时 - .setSocketTimeout(restTemplateProperties.getReadTimeout()) + .setSocketTimeout(Timeout.ofMicroseconds(restTemplateProperties.getReadTimeout())) // 链接超时 - .setConnectTimeout(restTemplateProperties.getConnectTimeout()) + .setConnectTimeout(Timeout.ofMicroseconds(restTemplateProperties.getConnectTimeout())) + .build(); + connectionManager.setDefaultConnectionConfig(connectConfig); + + RequestConfig requestConfig = RequestConfig.custom() // 链接不够用的等待时间 - .setConnectionRequestTimeout(restTemplateProperties.getReadTimeout()) + .setConnectionRequestTimeout(Timeout.ofMicroseconds(restTemplateProperties.getReadTimeout())) .build(); return HttpClientBuilder.create() .setDefaultRequestConfig(requestConfig) .setConnectionManager(connectionManager) - .setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)) .build(); } } diff --git a/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/FeignHttpInterceptorConfig.java b/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/FeignHttpInterceptorConfig.java index 4e0e006a2..9df3be552 100644 --- a/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/FeignHttpInterceptorConfig.java +++ b/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/FeignHttpInterceptorConfig.java @@ -11,7 +11,7 @@ import org.springframework.web.context.request.ServletRequestAttributes; import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; diff --git a/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/RestTemplateProperties.java b/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/RestTemplateProperties.java index b0dd15cbe..2bd54d8e1 100644 --- a/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/RestTemplateProperties.java +++ b/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/RestTemplateProperties.java @@ -3,6 +3,7 @@ import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; /** * RestTemplate 配置 @@ -16,6 +17,7 @@ @Setter @Getter @ConfigurationProperties(prefix = "zlt.rest-template") +@Component public class RestTemplateProperties { /** * 最大链接数 diff --git a/zlt-commons/zlt-log-spring-boot-starter/pom.xml b/zlt-commons/zlt-log-spring-boot-starter/pom.xml index f921e7a05..3b71b963a 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/pom.xml +++ b/zlt-commons/zlt-log-spring-boot-starter/pom.xml @@ -18,15 +18,6 @@ slf4j-api - - org.springframework.boot - spring-boot-starter - - - org.springframework.cloud - spring-cloud-context - - com.alibaba transmittable-thread-local @@ -52,11 +43,6 @@ spring-web true - - javax.servlet - javax.servlet-api - true - org.springframework.boot spring-boot-starter-jdbc @@ -72,5 +58,9 @@ feign-core true + + org.apache.tomcat.embed + tomcat-embed-core + diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/aspect/AuditLogAspect.java b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/aspect/AuditLogAspect.java index a94fd8a68..59ac9a068 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/aspect/AuditLogAspect.java +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/aspect/AuditLogAspect.java @@ -4,6 +4,7 @@ import com.central.log.model.Audit; import com.central.log.properties.AuditLogProperties; import com.central.log.service.IAuditService; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; @@ -20,7 +21,6 @@ import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; /** diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/AuditLogProperties.java b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/AuditLogProperties.java index 3f6713a87..cfc110b2c 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/AuditLogProperties.java +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/AuditLogProperties.java @@ -4,6 +4,7 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; /** * 审计日志配置 @@ -18,6 +19,7 @@ @Getter @ConfigurationProperties(prefix = "zlt.audit-log") @RefreshScope +@Component public class AuditLogProperties { /** * 是否开启审计日志 diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/LogDbProperties.java b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/LogDbProperties.java index 518fc72fb..ee9234216 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/LogDbProperties.java +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/LogDbProperties.java @@ -3,7 +3,9 @@ import com.zaxxer.hikari.HikariConfig; import lombok.Getter; import lombok.Setter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; /** * 日志数据源配置 @@ -18,5 +20,7 @@ @Setter @Getter @ConfigurationProperties(prefix = "zlt.audit-log.datasource") +@ConditionalOnClass(HikariConfig.class) +@Component public class LogDbProperties extends HikariConfig { } diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/TraceProperties.java b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/TraceProperties.java index a3daa5468..2a3cd2380 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/TraceProperties.java +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/TraceProperties.java @@ -4,6 +4,7 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; /** * 日志链路追踪配置 @@ -15,6 +16,7 @@ @Getter @ConfigurationProperties(prefix = "zlt.trace") @RefreshScope +@Component public class TraceProperties { /** * 是否开启日志链路追踪 diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/trace/WebTraceFilter.java b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/trace/WebTraceFilter.java index c7415f3e3..e5bfc34a4 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/trace/WebTraceFilter.java +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/trace/WebTraceFilter.java @@ -2,16 +2,16 @@ import cn.hutool.core.util.StrUtil; import com.central.log.properties.TraceProperties; +import jakarta.annotation.Resource; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; -import javax.annotation.Resource; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/org/slf4j/TtlMDCAdapter.java b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/org/slf4j/TtlMDCAdapter.java index a1df074b1..1bd01703b 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/org/slf4j/TtlMDCAdapter.java +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/org/slf4j/TtlMDCAdapter.java @@ -2,12 +2,10 @@ import ch.qos.logback.classic.util.LogbackMDCAdapter; import com.alibaba.ttl.TransmittableThreadLocal; +import org.slf4j.helpers.ThreadLocalMapOfStacks; import org.slf4j.spi.MDCAdapter; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 重构{@link LogbackMDCAdapter}类,搭配TransmittableThreadLocal实现父子线程之间的数据传递 @@ -16,17 +14,12 @@ * @date 2019/8/17 */ public class TtlMDCAdapter implements MDCAdapter { - private final ThreadLocal> copyOnInheritThreadLocal = new TransmittableThreadLocal<>(); - - private static final int WRITE_OPERATION = 1; - private static final int MAP_COPY_OPERATION = 2; + final ThreadLocal> readWriteThreadLocalMap = new TransmittableThreadLocal<>(); + final ThreadLocal> readOnlyThreadLocalMap = new TransmittableThreadLocal<>(); + private final ThreadLocalMapOfStacks threadLocalMapOfDeques = new ThreadLocalMapOfStacks(); private static TtlMDCAdapter mtcMDCAdapter; - /** - * keeps track of the last operation performed - */ - private final ThreadLocal lastOperation = new ThreadLocal<>(); static { mtcMDCAdapter = new TtlMDCAdapter(); @@ -37,60 +30,39 @@ public static MDCAdapter getInstance() { return mtcMDCAdapter; } - private Integer getAndSetLastOperation(int op) { - Integer lastOp = lastOperation.get(); - lastOperation.set(op); - return lastOp; - } - - private static boolean wasLastOpReadOrNull(Integer lastOp) { - return lastOp == null || lastOp == MAP_COPY_OPERATION; - } - - private Map duplicateAndInsertNewMap(Map oldMap) { - Map newMap = Collections.synchronizedMap(new HashMap<>()); - if (oldMap != null) { - // we don't want the parent thread modifying oldMap while we are - // iterating over it - synchronized (oldMap) { - newMap.putAll(oldMap); - } + public void put(String key, String val) throws IllegalArgumentException { + if (key == null) { + throw new IllegalArgumentException("key cannot be null"); + } + Map current = readWriteThreadLocalMap.get(); + if (current == null) { + current = new HashMap<>(); + readWriteThreadLocalMap.set(current); } - copyOnInheritThreadLocal.set(newMap); - return newMap; + current.put(key, val); + nullifyReadOnlyThreadLocalMap(); } /** - * Put a context value (the val parameter) as identified with the - * key parameter into the current thread's context map. Note that - * contrary to log4j, the val parameter can be null. + * Get the context identified by the key parameter. *

*

- * If the current thread does not have a context map it is created as a side - * effect of this call. - * - * @throws IllegalArgumentException in case the "key" parameter is null + * This method has no side effects. */ @Override - public void put(String key, String val) { - if (key == null) { - throw new IllegalArgumentException("key cannot be null"); - } - - Map oldMap = copyOnInheritThreadLocal.get(); - Integer lastOp = getAndSetLastOperation(WRITE_OPERATION); + public String get(String key) { + Map hashMap = readWriteThreadLocalMap.get(); - if (wasLastOpReadOrNull(lastOp) || oldMap == null) { - Map newMap = duplicateAndInsertNewMap(oldMap); - newMap.put(key, val); + if ((hashMap != null) && (key != null)) { + return hashMap.get(key); } else { - oldMap.put(key, val); + return null; } } /** - * Remove the the context identified by the key parameter. + *

Remove the context identified by the key parameter. *

*/ @Override @@ -98,53 +70,58 @@ public void remove(String key) { if (key == null) { return; } - Map oldMap = copyOnInheritThreadLocal.get(); - if (oldMap == null) { - return; - } - Integer lastOp = getAndSetLastOperation(WRITE_OPERATION); - - if (wasLastOpReadOrNull(lastOp)) { - Map newMap = duplicateAndInsertNewMap(oldMap); - newMap.remove(key); - } else { - oldMap.remove(key); + Map current = readWriteThreadLocalMap.get(); + if (current != null) { + current.remove(key); + nullifyReadOnlyThreadLocalMap(); } - } + private void nullifyReadOnlyThreadLocalMap() { + readOnlyThreadLocalMap.set(null); + } /** * Clear all entries in the MDC. */ @Override public void clear() { - lastOperation.set(WRITE_OPERATION); - copyOnInheritThreadLocal.remove(); + readWriteThreadLocalMap.set(null); + nullifyReadOnlyThreadLocalMap(); } /** - * Get the context identified by the key parameter. - *

+ *

Get the current thread's MDC as a map. This method is intended to be used + * internally.

+ * + * The returned map is unmodifiable (since version 1.3.2/1.4.2). */ - @Override - public String get(String key) { - final Map map = copyOnInheritThreadLocal.get(); - if ((map != null) && (key != null)) { - return map.get(key); - } else { - return null; + @SuppressWarnings("unchecked") + public Map getPropertyMap() { + Map readOnlyMap = readOnlyThreadLocalMap.get(); + if (readOnlyMap == null) { + Map current = readWriteThreadLocalMap.get(); + if (current != null) { + final Map tempMap = new HashMap<>(current); + readOnlyMap = Collections.unmodifiableMap(tempMap); + readOnlyThreadLocalMap.set(readOnlyMap); + } } + return readOnlyMap; } /** - * Get the current thread's MDC as a map. This method is intended to be used - * internally. + * Return a copy of the current thread's context map. Returned value may be + * null. */ - public Map getPropertyMap() { - lastOperation.set(MAP_COPY_OPERATION); - return copyOnInheritThreadLocal.get(); + public Map getCopyOfContextMap() { + Map readOnlyMap = getPropertyMap(); + if (readOnlyMap == null) { + return null; + } else { + return new HashMap<>(readOnlyMap); + } } /** @@ -152,37 +129,43 @@ public Map getPropertyMap() { * null. */ public Set getKeys() { - Map map = getPropertyMap(); + Map readOnlyMap = getPropertyMap(); - if (map != null) { - return map.keySet(); + if (readOnlyMap != null) { + return readOnlyMap.keySet(); } else { return null; } } - /** - * Return a copy of the current thread's context map. Returned value may be - * null. - */ - @Override - public Map getCopyOfContextMap() { - Map hashMap = copyOnInheritThreadLocal.get(); - if (hashMap == null) { - return null; + @SuppressWarnings("unchecked") + public void setContextMap(Map contextMap) { + if (contextMap != null) { + readWriteThreadLocalMap.set(new HashMap(contextMap)); } else { - return new HashMap<>(hashMap); + readWriteThreadLocalMap.set(null); } + nullifyReadOnlyThreadLocalMap(); } + @Override - public void setContextMap(Map contextMap) { - lastOperation.set(WRITE_OPERATION); + public void pushByKey(String key, String value) { + threadLocalMapOfDeques.pushByKey(key, value); + } - Map newMap = Collections.synchronizedMap(new HashMap<>()); - newMap.putAll(contextMap); + @Override + public String popByKey(String key) { + return threadLocalMapOfDeques.popByKey(key); + } + + @Override + public Deque getCopyOfDequeByKey(String key) { + return threadLocalMapOfDeques.getCopyOfDequeByKey(key); + } - // the newMap replaces the old one for serialisation's sake - copyOnInheritThreadLocal.set(newMap); + @Override + public void clearDequeByKey(String key) { + threadLocalMapOfDeques.clearDequeByKey(key); } } diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/resources/logback-spring.xml b/zlt-commons/zlt-log-spring-boot-starter/src/main/resources/logback-spring.xml index 3fe98f07c..016c7622d 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/src/main/resources/logback-spring.xml +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/resources/logback-spring.xml @@ -23,7 +23,6 @@ - true ${CONSOLE_LOG_PATTERN} UTF-8 diff --git a/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java b/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java index ac5a786dc..f4b919ab6 100644 --- a/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java +++ b/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java @@ -3,6 +3,7 @@ import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; /** * @author zlt @@ -14,6 +15,7 @@ @Setter @Getter @ConfigurationProperties(prefix = FileServerProperties.PREFIX) +@Component public class FileServerProperties { public static final String PREFIX = "zlt.file-server"; public static final String TYPE_FDFS = "fastdfs"; diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java index 6f25cec7a..49add5f5e 100644 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java @@ -1,13 +1,15 @@ package com.central.common.redis; import com.central.common.redis.properties.CacheManagerProperties; -import org.springframework.beans.factory.annotation.Autowired; +import jakarta.annotation.Resource; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; @@ -28,10 +30,12 @@ * Blog: https://zlt2000.gitee.io * Github: https://github.com/zlt2000 */ +@Configuration +@ComponentScan @EnableConfigurationProperties({RedisProperties.class, CacheManagerProperties.class}) @EnableCaching public class RedisAutoConfigure { - @Autowired + @Resource private CacheManagerProperties cacheManagerProperties; @Bean diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedissonDistributedLock.java b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedissonDistributedLock.java index fef19243a..7f7f17b33 100644 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedissonDistributedLock.java +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedissonDistributedLock.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; @@ -25,6 +26,7 @@ */ @ConditionalOnClass(RedissonClient.class) @ConditionalOnProperty(prefix = "zlt.lock", name = "lockerType", havingValue = "REDIS", matchIfMissing = true) +@Component public class RedissonDistributedLock implements DistributedLock { @Autowired private RedissonClient redisson; diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/properties/CacheManagerProperties.java b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/properties/CacheManagerProperties.java index 422c6ef06..4b969a940 100644 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/properties/CacheManagerProperties.java +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/properties/CacheManagerProperties.java @@ -3,6 +3,7 @@ import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; import java.util.List; @@ -13,6 +14,7 @@ @Setter @Getter @ConfigurationProperties(prefix = "zlt.cache-manager") +@Component public class CacheManagerProperties { private List configs; diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/template/RedisRepository.java b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/template/RedisRepository.java index 7c80302fc..4c6ffa5b2 100644 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/template/RedisRepository.java +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/template/RedisRepository.java @@ -10,6 +10,7 @@ import org.springframework.data.redis.core.*; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationUtils; +import org.springframework.stereotype.Component; import org.springframework.util.Assert; import java.util.*; @@ -25,6 +26,7 @@ * Github: https://github.com/zlt2000 */ @Slf4j +@Component public class RedisRepository { /** * Spring Redis Template diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories index c0dc55ef2..0aa42a0ea 100644 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -1,4 +1,2 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.common.redis.RedisAutoConfigure,\ -com.central.common.redis.lock.RedissonDistributedLock,\ -com.central.common.redis.template.RedisRepository \ No newline at end of file +com.central.common.redis.RedisAutoConfigure \ No newline at end of file diff --git a/zlt-commons/zlt-sentinel-spring-boot-starter/src/main/java/com/central/sentinel/config/SentinelAutoConfigure.java b/zlt-commons/zlt-sentinel-spring-boot-starter/src/main/java/com/central/sentinel/config/SentinelAutoConfigure.java index 864d85352..f525f4dc2 100644 --- a/zlt-commons/zlt-sentinel-spring-boot-starter/src/main/java/com/central/sentinel/config/SentinelAutoConfigure.java +++ b/zlt-commons/zlt-sentinel-spring-boot-starter/src/main/java/com/central/sentinel/config/SentinelAutoConfigure.java @@ -12,7 +12,7 @@ import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.server.ServerResponse; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; /** * Sentinel配置类 diff --git a/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerAutoConfiguration.java b/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerAutoConfiguration.java index 0919f96d3..576882b7e 100644 --- a/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerAutoConfiguration.java +++ b/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerAutoConfiguration.java @@ -58,7 +58,7 @@ public SwaggerProperties swaggerProperties() { return new SwaggerProperties(); } - @Bean + /*@Bean @ConditionalOnMissingBean @ConditionalOnProperty(name = "zlt.swagger.enabled", matchIfMissing = true) public List createRestApi(SwaggerProperties swaggerProperties) { @@ -131,7 +131,7 @@ public List createRestApi(SwaggerProperties swaggerProperties) { docketList.add(docket); } return docketList; - } + }*/ /** * 创建 Docket对象 @@ -139,7 +139,7 @@ public List createRestApi(SwaggerProperties swaggerProperties) { * @param swaggerProperties swagger配置 * @return Docket */ - private Docket createDocket(final SwaggerProperties swaggerProperties) { + /*private Docket createDocket(final SwaggerProperties swaggerProperties) { ApiInfo apiInfo = new ApiInfoBuilder() .title(swaggerProperties.getTitle()) .description(swaggerProperties.getDescription()) @@ -184,7 +184,7 @@ private Docket createDocket(final SwaggerProperties swaggerProperties) { .build() .securitySchemes(securitySchemes()) .securityContexts(securityContexts()); - } + }*/ @Override public void setBeanFactory(BeanFactory beanFactory) { diff --git a/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerProperties.java b/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerProperties.java index 89bbc8734..9bba37dca 100644 --- a/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerProperties.java +++ b/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerProperties.java @@ -4,6 +4,7 @@ import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -18,6 +19,7 @@ */ @Data @ConfigurationProperties("zlt.swagger") +@Component public class SwaggerProperties { /**是否开启swagger**/ private Boolean enabled; diff --git a/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/java/com/central/common/zookeeper/properties/ZookeeperProperty.java b/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/java/com/central/common/zookeeper/properties/ZookeeperProperty.java index 7ed7d167a..997770b10 100644 --- a/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/java/com/central/common/zookeeper/properties/ZookeeperProperty.java +++ b/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/java/com/central/common/zookeeper/properties/ZookeeperProperty.java @@ -3,6 +3,7 @@ import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; /** * zookeeper配置 @@ -17,6 +18,7 @@ @Setter @Getter @ConfigurationProperties(prefix = "zlt.zookeeper") +@Component public class ZookeeperProperty { /** * zk连接集群,多个用逗号隔开 diff --git a/zlt-config/src/main/resources/application-dev.properties b/zlt-config/src/main/resources/application-dev.properties index 43d5ef6f6..80bcb0ac2 100644 --- a/zlt-config/src/main/resources/application-dev.properties +++ b/zlt-config/src/main/resources/application-dev.properties @@ -5,9 +5,9 @@ zlt.datasource.username=root zlt.datasource.password=1q2w3e4r ##### redis配置 -spring.redis.host=192.168.28.130 -spring.redis.port=6379 -spring.redis.timeout=5000 +spring.data.redis.host=192.168.28.130 +spring.data.redis.port=6379 +spring.data.redis.timeout=5000 ##### elasticsearch配置 zlt.elasticsearch.uris=192.168.28.130:9200 diff --git a/zlt-config/src/main/resources/application-prod.properties b/zlt-config/src/main/resources/application-prod.properties index bce88d757..63aa58307 100644 --- a/zlt-config/src/main/resources/application-prod.properties +++ b/zlt-config/src/main/resources/application-prod.properties @@ -1,13 +1,13 @@ ########################## 统一变量配置 ########################## ##### 数据库配置 -zlt.datasource.ip=192.168.28.131 +zlt.datasource.ip=192.168.28.130 zlt.datasource.username=root zlt.datasource.password=1q2w3e4r ##### redis配置 -spring.redis.sentinel.master=mymaster -spring.redis.sentinel.nodes=172.17.0.1 -spring.redis.password= +spring.data.redis.sentinel.master=mymaster +spring.data.redis.sentinel.nodes=172.17.0.1 +spring.data.redis.password= ##### elasticsearch配置 zlt.elasticsearch.uris=192.168.28.130:9200 diff --git a/zlt-config/src/main/resources/application-test.properties b/zlt-config/src/main/resources/application-test.properties index ddf043952..619816712 100644 --- a/zlt-config/src/main/resources/application-test.properties +++ b/zlt-config/src/main/resources/application-test.properties @@ -1,13 +1,13 @@ ########################## 统一变量配置 ########################## ##### 数据库配置 -zlt.datasource.ip=192.168.28.131 +zlt.datasource.ip=192.168.28.130 zlt.datasource.username=root zlt.datasource.password=1q2w3e4r ##### redis配置 -spring.redis.host=192.168.28.130 -spring.redis.port=6379 -spring.redis.timeout=5000 +spring.data.redis.host=192.168.28.130 +spring.data.redis.port=6379 +spring.data.redis.timeout=5000 ##### elasticsearch配置 zlt.elasticsearch.uris=192.168.28.130:9200 diff --git a/zlt-config/src/main/resources/application.properties b/zlt-config/src/main/resources/application.properties index 99f7c0c00..8c903223f 100644 --- a/zlt-config/src/main/resources/application.properties +++ b/zlt-config/src/main/resources/application.properties @@ -1,4 +1,6 @@ ########################## application级别通用配置 ########################## +spring.main.allow-circular-references=true + ##### loadbalancer配置 ## 切换实例的重试 spring.cloud.loadbalancer.retry.enabled=false @@ -77,13 +79,13 @@ mybatis-plus.configuration.cache-enabled=false ##### redis配置 # 连接池最大连接数(使用负值表示没有限制) -spring.redis.lettuce.pool.max-active=8 +spring.data.redis.lettuce.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) -spring.redis.lettuce.pool.max-wait=-1 +spring.data.redis.lettuce.pool.max-wait=-1 # 连接池中的最大空闲连接 -spring.redis.lettuce.pool.max-idle=8 +spring.data.redis.lettuce.pool.max-idle=8 # 连接池中的最小空闲连接 -spring.redis.lettuce.pool.min-idle=0 +spring.data.redis.lettuce.pool.min-idle=0 ##### logging配置 logging.level.com.alibaba.nacos.client.naming=warn \ No newline at end of file diff --git a/zlt-demo/dubbo-demo/pom.xml b/zlt-demo/dubbo-demo/pom.xml index 1c1a07e76..a54a961ae 100644 --- a/zlt-demo/dubbo-demo/pom.xml +++ b/zlt-demo/dubbo-demo/pom.xml @@ -24,6 +24,7 @@ com.alibaba.cloud spring-cloud-starter-dubbo + 2021.1 diff --git a/zlt-demo/rocketmq-demo/rocketmq-consume/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java b/zlt-demo/rocketmq-demo/rocketmq-consume/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java deleted file mode 100644 index d377fc0cb..000000000 --- a/zlt-demo/rocketmq-demo/rocketmq-consume/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.rocketmq.demo.config; - -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Input; -import com.rocketmq.demo.config.RocketMqConfig.MySink; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.messaging.SubscribableChannel; - -/** - * @author zlt - */ -@EnableBinding({MySink.class}) -public class RocketMqConfig { - public interface MySink { - @Input(Sink.INPUT) - SubscribableChannel input(); - - @Input("input2") - SubscribableChannel input2(); - - @Input("input3") - SubscribableChannel input3(); - } -} diff --git a/zlt-demo/rocketmq-demo/rocketmq-consume/src/main/java/com/rocketmq/demo/service/ReceiveService.java b/zlt-demo/rocketmq-demo/rocketmq-consume/src/main/java/com/rocketmq/demo/service/ReceiveService.java index b27fb358d..ac81d7bd8 100644 --- a/zlt-demo/rocketmq-demo/rocketmq-consume/src/main/java/com/rocketmq/demo/service/ReceiveService.java +++ b/zlt-demo/rocketmq-demo/rocketmq-consume/src/main/java/com/rocketmq/demo/service/ReceiveService.java @@ -2,38 +2,38 @@ import com.rocketmq.demo.model.Order; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Sink; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.messaging.Message; -import org.springframework.messaging.handler.annotation.Payload; -import org.springframework.stereotype.Service; + +import java.util.function.Consumer; /** * @author zlt */ -@Service +@Configuration public class ReceiveService { /** * 字符串消息 */ - @StreamListener(Sink.INPUT) - public void receiveInput(String receiveMsg) { - System.out.println("input receive: " + receiveMsg); + @Bean + public Consumer receiveInput() { + return receiveMsg -> System.out.println("input receive: " + receiveMsg); } /** * 对象消息 */ - @StreamListener("input2") - public void receiveInput2(@Payload Order order) { - System.out.println("input2 receive: " + order); + @Bean + public Consumer receiveInput2() { + return order -> System.out.println("input2 receive: " + order); } /** * 通过spring.messaging对象来接收消息 */ - @StreamListener("input3") - public void receiveInput3(Message msg) { - System.out.println("input3 receive: " + msg); - } + @Bean + public Consumer> receiveInput3() { + return msg -> System.out.println("input3 receive: " + msg); + } } \ No newline at end of file diff --git a/zlt-demo/rocketmq-demo/rocketmq-consume/src/main/resources/application.yml b/zlt-demo/rocketmq-demo/rocketmq-consume/src/main/resources/application.yml index 3b839fe4b..86c2b8dd4 100644 --- a/zlt-demo/rocketmq-demo/rocketmq-consume/src/main/resources/application.yml +++ b/zlt-demo/rocketmq-demo/rocketmq-consume/src/main/resources/application.yml @@ -6,34 +6,35 @@ spring: name: rocketmq-produce cloud: stream: - rocketmq: - binder: - # RocketMQ 服务器地址 - name-server: 192.168.28.130:9876 - bindings: - input2: - consumer: - #增加tag过滤 - tags: tagObj + function: + definition: receiveInput;receiveInput2;receiveInput3 bindings: - input: + receiveInput-in-0: destination: test-topic content-type: text/plain group: consume-group1 consumer: #并发消费线程数 concurrency: 20 - input2: + receiveInput2-in-0: destination: test-topic content-type: application/json group: consume-group2 consumer: #并发消费线程数 concurrency: 20 - input3: + receiveInput3-in-0: destination: test-topic content-type: text/plain group: consume-group3 consumer: #并发消费线程数 - concurrency: 20 \ No newline at end of file + concurrency: 20 + rocketmq: + binder: + # RocketMQ 服务器地址 + name-server: 192.168.28.130:9876 + +logging: + level: + org.springframework.context.support: debug \ No newline at end of file diff --git a/zlt-demo/rocketmq-demo/rocketmq-produce/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java b/zlt-demo/rocketmq-demo/rocketmq-produce/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java deleted file mode 100644 index 264a4e50e..000000000 --- a/zlt-demo/rocketmq-demo/rocketmq-produce/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.rocketmq.demo.config; - -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Output; -import com.rocketmq.demo.config.RocketMqConfig.MySource; -import org.springframework.cloud.stream.messaging.Source; -import org.springframework.messaging.MessageChannel; - -/** - * 配置消息生产者 - * - * @author zlt - */ -@EnableBinding({MySource.class}) -public class RocketMqConfig { - public interface MySource { - @Output(Source.OUTPUT) - MessageChannel output(); - } -} diff --git a/zlt-demo/rocketmq-demo/rocketmq-produce/src/main/java/com/rocketmq/demo/service/SenderService.java b/zlt-demo/rocketmq-demo/rocketmq-produce/src/main/java/com/rocketmq/demo/service/SenderService.java index 0e1a16f16..012659ab1 100644 --- a/zlt-demo/rocketmq-demo/rocketmq-produce/src/main/java/com/rocketmq/demo/service/SenderService.java +++ b/zlt-demo/rocketmq-demo/rocketmq-produce/src/main/java/com/rocketmq/demo/service/SenderService.java @@ -1,37 +1,40 @@ package com.rocketmq.demo.service; import org.apache.rocketmq.common.message.MessageConst; -import com.rocketmq.demo.config.RocketMqConfig.MySource; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.stream.function.StreamBridge; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.support.MessageBuilder; import org.springframework.stereotype.Service; import org.springframework.util.MimeTypeUtils; +import javax.annotation.Resource; + /** * @author zlt */ @Service public class SenderService { - @Autowired - private MySource source; + private final static String TEST_OUT = "test-out-0"; + + @Resource + private StreamBridge streamBridge; /** * 发送字符消息 */ public void send(String msg) { - source.output().send(MessageBuilder.withPayload(msg).build()); + streamBridge.send(TEST_OUT, MessageBuilder.withPayload(msg).build()); } /** * 发送带tag的对象消息 */ public void sendWithTags(T msg, String tag) { - Message message = MessageBuilder.withPayload(msg) + Message message = MessageBuilder.withPayload(msg) .setHeader(MessageConst.PROPERTY_TAGS, tag) .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON) .build(); - source.output().send(message); + streamBridge.send(TEST_OUT, message); } } \ No newline at end of file diff --git a/zlt-demo/rocketmq-demo/rocketmq-produce/src/main/resources/application.yml b/zlt-demo/rocketmq-demo/rocketmq-produce/src/main/resources/application.yml index 821fb9fe8..3ed79230b 100644 --- a/zlt-demo/rocketmq-demo/rocketmq-produce/src/main/resources/application.yml +++ b/zlt-demo/rocketmq-demo/rocketmq-produce/src/main/resources/application.yml @@ -6,27 +6,16 @@ spring: name: rocketmq-produce cloud: stream: + bindings: + test-out-0: + destination: test-topic + content-type: application/json + group: produce-group rocketmq: binder: # RocketMQ 服务地址 name-server: 192.168.28.130:9876 - bindings: - output: - producer: - group: produce-group - output2: - producer: - group: test-group2 - bindings: - output: - destination: test-topic - content-type: application/json logging: level: - org: - springframework: - cloud: - stream: - binder: - rocketmq: DEBUG \ No newline at end of file + org.springframework.context.support: debug \ No newline at end of file diff --git a/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java b/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java deleted file mode 100644 index c9adc743e..000000000 --- a/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/config/RocketMqConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.rocketmq.demo.config; - -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.cloud.stream.messaging.Source; -import org.springframework.messaging.SubscribableChannel; - -import com.rocketmq.demo.config.RocketMqConfig.MySink; - -/** - * @author zlt - */ -@EnableBinding({ Source.class, MySink.class }) -public class RocketMqConfig { - public interface MySink { - @Input(Sink.INPUT) - SubscribableChannel input(); - - @Input("inputDlq") - SubscribableChannel inputDlq(); - } -} diff --git a/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/controller/OrderController.java b/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/controller/OrderController.java index 31c9993f1..e896b349d 100644 --- a/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/controller/OrderController.java +++ b/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/controller/OrderController.java @@ -3,8 +3,7 @@ import cn.hutool.core.util.RandomUtil; import com.central.common.utils.IdGenerator; import com.rocketmq.demo.model.Order; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.stream.messaging.Source; +import org.springframework.cloud.stream.function.StreamBridge; import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.Message; import org.springframework.web.bind.annotation.GetMapping; @@ -15,11 +14,11 @@ */ @RestController public class OrderController { - private final Source source; + private final static String ORDER_OUT = "order-out-0"; + private final StreamBridge streamBridge; - @Autowired - public OrderController(Source source) { - this.source = source; + public OrderController(StreamBridge streamBridge) { + this.streamBridge = streamBridge; } /** @@ -31,12 +30,12 @@ public String success() { order.setOrderId(IdGenerator.getId()); order.setOrderNo(RandomUtil.randomString(4)); - Message message = MessageBuilder + Message message = MessageBuilder .withPayload(order) .setHeader("orderId", order.getOrderId()) .build(); //发送半消息 - source.output().send(message); + streamBridge.send(ORDER_OUT, message); return "下单成功"; } @@ -49,13 +48,13 @@ public String produceError() { order.setOrderId(IdGenerator.getId()); order.setOrderNo(RandomUtil.randomString(4)); - Message message = MessageBuilder + Message message = MessageBuilder .withPayload(order) .setHeader("orderId", order.getOrderId()) .setHeader("produceError", "1") .build(); //发送半消息 - source.output().send(message); + streamBridge.send(ORDER_OUT, message); return "发送消息失败"; } @@ -68,13 +67,13 @@ public String consumeError() { order.setOrderId(IdGenerator.getId()); order.setOrderNo(RandomUtil.randomString(4)); - Message message = MessageBuilder + Message message = MessageBuilder .withPayload(order) .setHeader("orderId", order.getOrderId()) .setHeader("consumeError", "1") .build(); //发送半消息 - source.output().send(message); + streamBridge.send(ORDER_OUT, message); return "消费消息失败"; } } diff --git a/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/listener/OrderTransactionListenerImpl.java b/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/listener/OrderTransactionListenerImpl.java index 103551bca..f161602e3 100644 --- a/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/listener/OrderTransactionListenerImpl.java +++ b/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/listener/OrderTransactionListenerImpl.java @@ -3,31 +3,32 @@ import com.central.common.utils.JsonUtil; import com.rocketmq.demo.model.Order; import com.rocketmq.demo.service.IOrderService; -import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; -import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; -import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.messaging.Message; +import jakarta.annotation.Resource; +import org.apache.rocketmq.client.producer.LocalTransactionState; +import org.apache.rocketmq.client.producer.TransactionListener; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageExt; +import org.springframework.stereotype.Component; /** * @author zlt */ -@RocketMQTransactionListener(txProducerGroup = "order-tx-produce-group", corePoolSize = 5, maximumPoolSize = 10) -public class OrderTransactionListenerImpl implements RocketMQLocalTransactionListener { - @Autowired +@Component("myTransactionListener") +public class OrderTransactionListenerImpl implements TransactionListener { + @Resource private IOrderService orderService; /** * 提交本地事务 */ @Override - public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object arg) { + public LocalTransactionState executeLocalTransaction(Message message, Object arg) { //插入订单数据 - String orderJson = new String(((byte[])message.getPayload())); + String orderJson = new String((message.getBody())); Order order = JsonUtil.toObject(orderJson, Order.class); orderService.save(order); - String produceError = (String)message.getHeaders().get("produceError"); + String produceError = message.getProperty("produceError"); if ("1".equals(produceError)) { System.err.println("============Exception:订单进程挂了,事务消息没提交"); //模拟插入订单后服务器挂了,没有commit事务消息 @@ -35,7 +36,7 @@ public RocketMQLocalTransactionState executeLocalTransaction(Message message, Ob } //提交事务消息 - return RocketMQLocalTransactionState.COMMIT; + return LocalTransactionState.COMMIT_MESSAGE; } /** @@ -46,13 +47,13 @@ public RocketMQLocalTransactionState executeLocalTransaction(Message message, Ob * 否:回滚事务消息 */ @Override - public RocketMQLocalTransactionState checkLocalTransaction(Message message) { - String orderId = (String)message.getHeaders().get("orderId"); + public LocalTransactionState checkLocalTransaction(MessageExt message) { + String orderId = message.getProperty("orderId"); System.out.println("============事务回查-orderId:" + orderId); //判断之前的事务是否已经提交:订单记录是否已经保存 int count = 1; //select count(1) from t_order where order_id = ${orderId} System.out.println("============事务回查-订单已生成-提交事务消息"); - return count > 0 ? RocketMQLocalTransactionState.COMMIT : RocketMQLocalTransactionState.ROLLBACK; + return count > 0 ? LocalTransactionState.COMMIT_MESSAGE : LocalTransactionState.ROLLBACK_MESSAGE; } } \ No newline at end of file diff --git a/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/service/impl/IntegralReceiveService.java b/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/service/impl/IntegralReceiveService.java index 509ca48bf..3277c37ba 100644 --- a/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/service/impl/IntegralReceiveService.java +++ b/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/java/com/rocketmq/demo/service/impl/IntegralReceiveService.java @@ -1,36 +1,42 @@ package com.rocketmq.demo.service.impl; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Sink; +import com.rocketmq.demo.model.Order; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.messaging.Message; -import org.springframework.stereotype.Service; + +import java.util.function.Consumer; /** * 积分服务的消费者,接收到下单成功后增加积分 * * @author zlt */ -@Service +@Configuration public class IntegralReceiveService { - @StreamListener(Sink.INPUT) - public void receive(Message message) { - //模拟消费异常 - String consumeError = (String)message.getHeaders().get("consumeError"); - if ("1".equals(consumeError)) { - System.err.println("============Exception:积分进程挂了,消费消息失败"); - //模拟插入订单后服务器挂了,没有commit事务消息 - throw new RuntimeException("积分服务器挂了"); - } + @Bean + public Consumer> receive() { + return message -> { + //模拟消费异常 + String consumeError = (String)message.getHeaders().get("consumeError"); + if ("1".equals(consumeError)) { + System.err.println("============Exception:积分进程挂了,消费消息失败"); + //模拟插入订单后服务器挂了,没有commit事务消息 + throw new RuntimeException("积分服务器挂了"); + } - System.out.println("============收到订单信息,增加积分:" + message); + System.out.println("============收到订单信息,增加积分:" + message); + }; } /** * 消费死信队列 */ - @StreamListener("inputDlq") - public void receiveDlq(Message message) { - String orderId = (String)message.getHeaders().get("orderId"); - System.err.println("============消费死信队列消息,记录日志并预警:" + orderId); + @Bean + public Consumer> receiveDlq() { + return message -> { + String orderId = (String)message.getHeaders().get("orderId"); + System.err.println("============消费死信队列消息,记录日志并预警:" + orderId); + }; } } diff --git a/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/resources/application.yml b/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/resources/application.yml index 942a82f71..3fccf6977 100644 --- a/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/resources/application.yml +++ b/zlt-demo/rocketmq-demo/rocketmq-transactional/src/main/resources/application.yml @@ -6,27 +6,16 @@ spring: name: rocketmq-tx cloud: stream: - rocketmq: - binder: - # RocketMQ 服务器地址 - name-server: 192.168.28.130:9876 - bindings: - output: - producer: - group: order-tx-produce-group - #开启事务消息 - transactional: true - input: - consumer: - #重试失败直接进入死信队列 - delayLevelWhenNextConsume: -1 + function: + definition: receive;receiveDlq bindings: # 生产者 - output: + order-out-0: destination: TransactionTopic content-type: application/json + group: order-tx-produce-group # 消费者 - input: + receive-in-0: destination: TransactionTopic content-type: application/json group: order-tx-consume-group @@ -35,18 +24,27 @@ spring: concurrency: 20 #重试1次 maxAttempts: 2 - inputDlq: - destination: '%DLQ%${spring.cloud.stream.bindings.input.group}' + receiveDlq-in-0: + destination: '%DLQ%${spring.cloud.stream.bindings.receive-in-0.group}' content-type: application/json group: order-dlq-group consumer: concurrency: 20 + rocketmq: + binder: + # RocketMQ 服务器地址 + name-server: 192.168.28.130:9876 + bindings: + order-out-0: + producer: + #开启事务消息 + transactionListener: myTransactionListener + producerType: Trans + receive-in-0: + consumer: + #重试失败直接进入死信队列 + delayLevelWhenNextConsume: -1 logging: level: - org: - springframework: - cloud: - stream: - binder: - rocketmq: DEBUG \ No newline at end of file + org.springframework.context.support: debug \ No newline at end of file diff --git a/zlt-demo/sso-demo/oidc-sso/src/main/java/com/sso/demo/controller/ApiController.java b/zlt-demo/sso-demo/oidc-sso/src/main/java/com/sso/demo/controller/ApiController.java index 04b2b1c5d..20506119e 100644 --- a/zlt-demo/sso-demo/oidc-sso/src/main/java/com/sso/demo/controller/ApiController.java +++ b/zlt-demo/sso-demo/oidc-sso/src/main/java/com/sso/demo/controller/ApiController.java @@ -23,7 +23,7 @@ import org.springframework.web.client.RestTemplate; import org.apache.commons.codec.binary.Base64; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.nio.charset.StandardCharsets; import java.security.interfaces.RSAPublicKey; import java.util.*; diff --git a/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SecurityConfig.java b/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SecurityConfig.java index e3d4e19a5..f79c61316 100644 --- a/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SecurityConfig.java +++ b/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SecurityConfig.java @@ -3,9 +3,10 @@ import cn.hutool.core.util.StrUtil; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import javax.annotation.Resource; @@ -21,16 +22,16 @@ */ @EnableOAuth2Sso @Configuration -public class SecurityConfig extends WebSecurityConfigurerAdapter { +public class SecurityConfig { @Value("${security.oauth2.sso.login-path:}") private String loginPath; @Resource private LogoutSuccessHandler ssoLogoutSuccessHandler; - @Override - public void configure(HttpSecurity http) throws Exception { - http.authorizeRequests().anyRequest().authenticated() + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.authorizeHttpRequests().anyRequest().authenticated() .and() .csrf().disable() .logout() @@ -38,5 +39,6 @@ public void configure(HttpSecurity http) throws Exception { if (StrUtil.isNotEmpty(loginPath)) { http.formLogin().loginProcessingUrl(loginPath); } + return http.build(); } } \ No newline at end of file diff --git a/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SsoLogoutSuccessHandler.java b/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SsoLogoutSuccessHandler.java index 4a5915009..e942b9baf 100644 --- a/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SsoLogoutSuccessHandler.java +++ b/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SsoLogoutSuccessHandler.java @@ -9,8 +9,8 @@ import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.stereotype.Component; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; /** diff --git a/zlt-demo/sso-demo/web-sso/src/main/java/com/sso/demo/controller/ApiController.java b/zlt-demo/sso-demo/web-sso/src/main/java/com/sso/demo/controller/ApiController.java index f15bbdc98..7dd0b5230 100644 --- a/zlt-demo/sso-demo/web-sso/src/main/java/com/sso/demo/controller/ApiController.java +++ b/zlt-demo/sso-demo/web-sso/src/main/java/com/sso/demo/controller/ApiController.java @@ -16,7 +16,7 @@ import org.springframework.web.client.RestTemplate; import org.apache.commons.codec.binary.Base64; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.io.UnsupportedEncodingException; import java.util.*; diff --git a/zlt-demo/websocket-demo/src/main/java/org/zlt/controller/TestWebSocketController.java b/zlt-demo/websocket-demo/src/main/java/org/zlt/controller/TestWebSocketController.java index d14f94d33..a83b48a79 100644 --- a/zlt-demo/websocket-demo/src/main/java/org/zlt/controller/TestWebSocketController.java +++ b/zlt-demo/websocket-demo/src/main/java/org/zlt/controller/TestWebSocketController.java @@ -1,12 +1,12 @@ package org.zlt.controller; import com.central.oauth2.common.config.WcAuthConfigurator; +import jakarta.websocket.OnOpen; +import jakarta.websocket.Session; +import jakarta.websocket.server.ServerEndpoint; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import javax.websocket.OnOpen; -import javax.websocket.Session; -import javax.websocket.server.ServerEndpoint; import java.io.IOException; /** diff --git a/zlt-gateway/sc-gateway/pom.xml b/zlt-gateway/sc-gateway/pom.xml index b91540838..88c12ce5d 100644 --- a/zlt-gateway/sc-gateway/pom.xml +++ b/zlt-gateway/sc-gateway/pom.xml @@ -10,6 +10,7 @@ spring cloud gateway网关 + com.zlt zlt-config @@ -18,6 +19,7 @@ com.zlt zlt-log-spring-boot-starter + com.zlt zlt-loadbalancer-spring-boot-starter @@ -26,15 +28,22 @@ com.zlt zlt-sentinel-spring-boot-starter - + - com.zlt - zlt-auth-client-spring-boot-starter + org.springframework.cloud + spring-cloud-starter-gateway + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + org.springframework.boot + spring-boot-starter-webflux - com.zlt zlt-redis-spring-boot-starter @@ -45,19 +54,11 @@ - - - org.springframework.cloud - spring-cloud-starter-gateway - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-discovery - - - org.springframework.boot - spring-boot-starter-webflux + com.zlt + zlt-auth-client-spring-boot-starter + org.springframework.cloud spring-cloud-starter-openfeign @@ -74,7 +75,8 @@ com.github.xiaoymin - knife4j-spring-boot-starter + knife4j-gateway-spring-boot-starter + 4.2.0 diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java index 5f8edf6aa..ade1485b6 100644 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java @@ -2,15 +2,15 @@ import com.central.gateway.auth.*; import com.central.oauth2.common.properties.SecurityProperties; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.ReactiveAuthenticationManager; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.SecurityWebFiltersOrder; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.oauth2.server.resource.web.server.ServerBearerTokenAuthenticationConverter; +import org.springframework.security.oauth2.server.resource.web.server.authentication.ServerBearerTokenAuthenticationConverter; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.authentication.AuthenticationWebFilter; import org.springframework.security.web.server.authentication.ServerAuthenticationEntryPointFailureHandler; @@ -25,18 +25,11 @@ * Github: https://github.com/zlt2000 */ @Configuration +@EnableWebFluxSecurity public class ResourceServerConfiguration { - @Autowired - private SecurityProperties securityProperties; - - @Autowired - private TokenStore tokenStore; - - @Autowired - private PermissionAuthManager permissionAuthManager; - @Bean - SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http + , SecurityProperties securityProperties, TokenStore tokenStore, PermissionAuthManager permissionAuthManager) { //认证处理器 ReactiveAuthenticationManager customAuthenticationManager = new CustomAuthenticationManager(tokenStore); JsonAuthenticationEntryPoint entryPoint = new JsonAuthenticationEntryPoint(); diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/CustomErrorWebFluxAutoConfiguration.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/CustomErrorWebFluxAutoConfiguration.java index 174d70c0a..abbecc018 100644 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/CustomErrorWebFluxAutoConfiguration.java +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/CustomErrorWebFluxAutoConfiguration.java @@ -1,7 +1,7 @@ package com.central.gateway.error; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.web.ServerProperties; @@ -12,16 +12,11 @@ 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.config.WebFluxConfigurer; import org.springframework.web.reactive.result.view.ViewResolver; -import java.util.Collections; -import java.util.List; - /** * 自定义异常处理 * @@ -31,45 +26,28 @@ * Blog: https://zlt2000.gitee.io * Github: https://github.com/zlt2000 */ -@Configuration +@AutoConfiguration(before = WebFluxAutoConfiguration.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) @ConditionalOnClass(WebFluxConfigurer.class) -@AutoConfigureBefore(WebFluxAutoConfiguration.class) -@EnableConfigurationProperties({ServerProperties.class, WebProperties.class}) +@EnableConfigurationProperties({ ServerProperties.class, WebProperties.class }) public class CustomErrorWebFluxAutoConfiguration { private final ServerProperties serverProperties; - private final ApplicationContext applicationContext; - - private final WebProperties webProperties; - - private final List viewResolvers; - - private final ServerCodecConfigurer serverCodecConfigurer; - - public CustomErrorWebFluxAutoConfiguration(ServerProperties serverProperties, - WebProperties webProperties, - ObjectProvider> viewResolversProvider, - ServerCodecConfigurer serverCodecConfigurer, - ApplicationContext applicationContext) { + public CustomErrorWebFluxAutoConfiguration(ServerProperties serverProperties) { this.serverProperties = serverProperties; - this.applicationContext = applicationContext; - this.webProperties = webProperties; - this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); - this.serverCodecConfigurer = serverCodecConfigurer; } @Bean - @Order(Ordered.HIGHEST_PRECEDENCE) - public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) { - JsonErrorWebExceptionHandler exceptionHandler = new JsonErrorWebExceptionHandler( - errorAttributes, - this.webProperties.getResources(), - this.serverProperties.getError(), - this.applicationContext); - exceptionHandler.setViewResolvers(this.viewResolvers); - exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters()); - exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders()); + @Order(-1) + public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes, + WebProperties webProperties, ObjectProvider viewResolvers, + ServerCodecConfigurer serverCodecConfigurer, ApplicationContext applicationContext) { + JsonErrorWebExceptionHandler exceptionHandler = new JsonErrorWebExceptionHandler(errorAttributes, + webProperties.getResources(), this.serverProperties.getError(), applicationContext); + exceptionHandler.setViewResolvers(viewResolvers.orderedStream().toList()); + exceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters()); + exceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders()); return exceptionHandler; } + } diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/JsonErrorWebExceptionHandler.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/JsonErrorWebExceptionHandler.java index 93814e37f..e401f560f 100644 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/JsonErrorWebExceptionHandler.java +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/JsonErrorWebExceptionHandler.java @@ -80,7 +80,7 @@ private String buildMessage(ServerRequest request, Throwable ex) { */ private Map responseError(ServerRequest request, Throwable error) { String errorMessage = buildMessage(request, error); - int httpStatus = getHttpStatus(error); + int httpStatus = 200;//getHttpStatus(error); Map map = new HashMap<>(); map.put("resp_code", 1); map.put("resp_msg", errorMessage); diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/feign/AsynMenuService.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/feign/AsynMenuService.java index b6577abd2..6b08b6737 100644 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/feign/AsynMenuService.java +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/feign/AsynMenuService.java @@ -1,13 +1,12 @@ package com.central.gateway.feign; import com.central.common.model.SysMenu; -import org.springframework.beans.factory.annotation.Autowired; +import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Component; -import javax.annotation.Resource; import java.util.List; import java.util.concurrent.Future; diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/feign/MenuService.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/feign/MenuService.java index 597815895..9253ba0b4 100644 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/feign/MenuService.java +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/feign/MenuService.java @@ -12,7 +12,7 @@ /** * @author zlt */ -@FeignClient(name = ServiceNameConstants.USER_SERVICE, fallbackFactory = MenuServiceFallbackFactory.class, decode404 = true) +@FeignClient(name = ServiceNameConstants.USER_SERVICE, fallbackFactory = MenuServiceFallbackFactory.class, dismiss404 = true) public interface MenuService { /** * 角色菜单列表 diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerAggProperties.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerAggProperties.java deleted file mode 100644 index df7762d81..000000000 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerAggProperties.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.central.gateway.swagger; - -import lombok.Getter; -import lombok.Setter; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; - -import java.util.HashSet; -import java.util.Set; - -/** - * swagger聚合配置 - * - * @author zlt - * @date 2019/10/5 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Setter -@Getter -@ConfigurationProperties("zlt.swagger-agg") -@RefreshScope -public class SwaggerAggProperties { - /** - * Swagger返回JSON文档的接口路径(全局配置) - */ - private String apiDocsPath = "/v2/api-docs"; - - /** - * Swagger文档版本(全局配置) - */ - private String swaggerVersion = "2.0"; - - /** - * 自动生成文档的路由名称,设置了generateRoutes之后,ignoreRoutes不生效 - */ - private Set generateRoutes = new HashSet<>(); - - /** - * 不自动生成文档的路由名称,设置了generateRoutes之后,本配置不生效 - */ - private Set ignoreRoutes = new HashSet<>(); - - /** - * 是否显示该路由 - */ - public boolean isShow(String route) { - int generateRoutesSize = generateRoutes.size(); - int ignoreRoutesSize = ignoreRoutes.size(); - - if(generateRoutesSize > 0 && !generateRoutes.contains(route)) { - return false; - } - - if(ignoreRoutesSize > 0 && ignoreRoutes.contains(route)) { - return false; - } - - return true; - } -} diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerHandler.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerHandler.java deleted file mode 100644 index f9be8322c..000000000 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerHandler.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.central.gateway.swagger; - -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.Optional; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import reactor.core.publisher.Mono; -import springfox.documentation.swagger.web.SecurityConfiguration; -import springfox.documentation.swagger.web.SecurityConfigurationBuilder; -import springfox.documentation.swagger.web.SwaggerResourcesProvider; -import springfox.documentation.swagger.web.UiConfiguration; -import springfox.documentation.swagger.web.UiConfigurationBuilder; - -/** - * @author zlt - * @date 2019/10/5 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@RestController -@RequestMapping("/swagger-resources" ) -public class SwaggerHandler { - private final SwaggerResourcesProvider swaggerResources; - @Autowired(required = false) - private SecurityConfiguration securityConfiguration; - @Autowired(required = false) - private UiConfiguration uiConfiguration; - - @Autowired - public SwaggerHandler(SwaggerResourcesProvider swaggerResources) { - this.swaggerResources = swaggerResources; - } - - @GetMapping("/configuration/security" ) - public Mono> securityConfiguration() { - return Mono.just(new ResponseEntity<>( - Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK)); - } - - @GetMapping("/configuration/ui" ) - public Mono> uiConfiguration() { - return Mono.just(new ResponseEntity<>( - Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); - } - - @GetMapping - public Mono swaggerResources() { - return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); - } -} \ No newline at end of file diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerProvider.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerProvider.java deleted file mode 100644 index 5156a0773..000000000 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/swagger/SwaggerProvider.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.central.gateway.swagger; - -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.gateway.config.GatewayProperties; -import org.springframework.cloud.gateway.route.RouteLocator; -import org.springframework.cloud.gateway.support.NameUtils; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Component; -import springfox.documentation.swagger.web.SwaggerResource; -import springfox.documentation.swagger.web.SwaggerResourcesProvider; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * 跨域配置 - * - * @author zlt - * @date 2019/10/5 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Component -@EnableConfigurationProperties(SwaggerAggProperties.class) -@Primary -public class SwaggerProvider implements SwaggerResourcesProvider { - private final RouteLocator routeLocator; - private final GatewayProperties gatewayProperties; - - @Resource - private SwaggerAggProperties swaggerAggProperties; - - public SwaggerProvider(RouteLocator routeLocator, GatewayProperties gatewayProperties) { - this.routeLocator = routeLocator; - this.gatewayProperties = gatewayProperties; - } - - @Override - public List get() { - List resources = new ArrayList<>(); - Set routes = new HashSet<>(); - //取出Spring Cloud Gateway中的route - routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); - //结合application.yml中的路由配置,只获取有效的route节点 - gatewayProperties.getRoutes().stream().filter( - routeDefinition -> ( - routes.contains(routeDefinition.getId()) && swaggerAggProperties.isShow(routeDefinition.getId()) - ) - ).forEach(routeDefinition -> routeDefinition.getPredicates().stream() - .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName())) - .forEach(predicateDefinition -> resources.add( - swaggerResource( - routeDefinition.getId(), - predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", swaggerAggProperties.getApiDocsPath()) - ) - ) - ) - ); - return resources; - } - - private SwaggerResource swaggerResource(String name, String location) { - SwaggerResource swaggerResource = new SwaggerResource(); - swaggerResource.setName(name); - swaggerResource.setLocation(location); - swaggerResource.setSwaggerVersion(swaggerAggProperties.getSwaggerVersion()); - return swaggerResource; - } -} \ No newline at end of file diff --git a/zlt-gateway/sc-gateway/src/main/resources/bootstrap.yml b/zlt-gateway/sc-gateway/src/main/resources/bootstrap.yml index a41f0b3d1..02691bb3e 100644 --- a/zlt-gateway/sc-gateway/src/main/resources/bootstrap.yml +++ b/zlt-gateway/sc-gateway/src/main/resources/bootstrap.yml @@ -3,4 +3,6 @@ server: spring: application: - name: sc-gateway \ No newline at end of file + name: sc-gateway + main: + web-application-type: reactive \ No newline at end of file diff --git a/zlt-monitor/sc-admin/src/main/java/com/central/gateway/monitor/config/SecuritySecureConfig.java b/zlt-monitor/sc-admin/src/main/java/com/central/gateway/monitor/config/SecuritySecureConfig.java index f178536df..14278ad67 100644 --- a/zlt-monitor/sc-admin/src/main/java/com/central/gateway/monitor/config/SecuritySecureConfig.java +++ b/zlt-monitor/sc-admin/src/main/java/com/central/gateway/monitor/config/SecuritySecureConfig.java @@ -1,9 +1,10 @@ package com.central.gateway.monitor.config; import de.codecentric.boot.admin.server.config.AdminServerProperties; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; /** @@ -11,22 +12,22 @@ * @date 2019/1/8 */ @Configuration -public class SecuritySecureConfig extends WebSecurityConfigurerAdapter { +public class SecuritySecureConfig { private final String adminContextPath; public SecuritySecureConfig(AdminServerProperties adminServerProperties) { this.adminContextPath = adminServerProperties.getContextPath(); } - @Override - protected void configure(HttpSecurity http) throws Exception { + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); successHandler.setTargetUrlParameter("redirectTo"); successHandler.setDefaultTargetUrl(adminContextPath + "/"); - http.authorizeRequests() - .antMatchers(adminContextPath + "/assets/**").permitAll() - .antMatchers(adminContextPath + "/login").permitAll() + http.authorizeHttpRequests() + .requestMatchers(adminContextPath + "/assets/**").permitAll() + .requestMatchers(adminContextPath + "/login").permitAll() .anyRequest().authenticated() .and() .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and() @@ -38,5 +39,6 @@ protected void configure(HttpSecurity http) throws Exception { .disable() .and() .csrf().disable(); + return http.build(); } } diff --git a/zlt-uaa/pom.xml b/zlt-uaa/pom.xml index 59d3d2749..b21c593fa 100644 --- a/zlt-uaa/pom.xml +++ b/zlt-uaa/pom.xml @@ -21,10 +21,10 @@ com.zlt zlt-common-spring-boot-starter - + com.zlt zlt-db-spring-boot-starter @@ -33,9 +33,14 @@ com.zlt zlt-loadbalancer-spring-boot-starter - + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + 4.2.0 com.zlt @@ -102,6 +107,14 @@ junit test + + org.apache.tomcat.embed + tomcat-embed-core + + + javax.servlet + javax.servlet-api + diff --git a/zlt-uaa/src/main/java/com/central/UaaServerApp.java b/zlt-uaa/src/main/java/com/central/UaaServerApp.java index b3ac5a297..a52b34e4b 100644 --- a/zlt-uaa/src/main/java/com/central/UaaServerApp.java +++ b/zlt-uaa/src/main/java/com/central/UaaServerApp.java @@ -1,6 +1,7 @@ package com.central; import com.central.common.lb.annotation.EnableFeignInterceptor; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @@ -10,6 +11,7 @@ * @author zlt */ @EnableFeignClients +@MapperScan(basePackages = "com.central.oauth.mapper") @EnableFeignInterceptor @EnableDiscoveryClient //@EnableRedisHttpSession diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java deleted file mode 100644 index e7d68db9e..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.central.oauth.config; - -import cn.hutool.core.util.StrUtil; -import com.central.common.constant.SecurityConstants; -import com.central.common.model.SysUser; -import com.central.oauth.model.Client; -import com.central.oauth.service.IClientService; -import com.central.oauth.service.impl.RedisClientDetailsService; -import com.central.oauth.service.impl.UserDetailServiceFactory; -import com.central.oauth.utils.OidcIdTokenBuilder; -import com.central.oauth2.common.constants.IdTokenClaimNames; -import com.central.oauth2.common.properties.TokenStoreProperties; -import com.central.oauth2.common.util.AuthUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.cloud.bootstrap.encrypt.KeyProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; -import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.TokenGranter; -import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; -import org.springframework.security.oauth2.provider.token.TokenEnhancer; -import org.springframework.security.oauth2.provider.token.TokenStore; - -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * OAuth2 授权服务器配置 - * - * @author zlt - * @date 2018/10/24 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Configuration -@EnableAuthorizationServer -@AutoConfigureAfter(AuthorizationServerEndpointsConfigurer.class) -public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { - /** - * 注入authenticationManager 来支持 password grant type - */ - @Autowired - private AuthenticationManager authenticationManager; - - @Resource - private UserDetailServiceFactory userDetailsServiceFactory; - - @Autowired - private TokenStore tokenStore; - - @Autowired - private WebResponseExceptionTranslator webResponseExceptionTranslator; - - @Autowired - private RedisClientDetailsService clientDetailsService; - - @Autowired - private RandomValueAuthorizationCodeServices authorizationCodeServices; - - @Autowired - private TokenGranter tokenGranter; - - /** - * 配置身份认证器,配置认证方式,TokenStore,TokenGranter,OAuth2RequestFactory - * @param endpoints - */ - @Override - public void configure(AuthorizationServerEndpointsConfigurer endpoints) { - endpoints.tokenStore(tokenStore) - .authenticationManager(authenticationManager) - //.userDetailsService(userDetailsServiceFactory.getService(SecurityConstants.DEF_ACCOUNT_TYPE)) - .authorizationCodeServices(authorizationCodeServices) - .exceptionTranslator(webResponseExceptionTranslator) - .tokenGranter(tokenGranter); - } - - /** - * 配置应用名称 应用id - * 配置OAuth2的客户端相关信息 - * @param clients - * @throws Exception - */ - @Override - public void configure(ClientDetailsServiceConfigurer clients) throws Exception { - clients.withClientDetails(clientDetailsService); - clientDetailsService.loadAllClientToCache(); - } - - /** - * 对应于配置AuthorizationServer安全认证的相关信息,创建ClientCredentialsTokenEndpointFilter核心过滤器 - * @param security - */ - @Override - public void configure(AuthorizationServerSecurityConfigurer security) { - security - .tokenKeyAccess("isAuthenticated()") - .checkTokenAccess("permitAll()") - //让/oauth/token支持client_id以及client_secret作登录认证 - .allowFormAuthenticationForClients(); - } - - @Bean - @Order(1) - public TokenEnhancer tokenEnhancer(@Autowired(required = false) KeyProperties keyProperties - , IClientService clientService - , TokenStoreProperties tokenStoreProperties) { - return (accessToken, authentication) -> { - Set responseTypes = authentication.getOAuth2Request().getResponseTypes(); - Map additionalInfo = new HashMap<>(3); - String accountType = AuthUtils.getAccountType(authentication.getUserAuthentication()); - if (StrUtil.isNotEmpty(accountType)) { - additionalInfo.put(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME, accountType); - } - - if (responseTypes.contains(SecurityConstants.ID_TOKEN) - || "authJwt".equals(tokenStoreProperties.getType())) { - Object principal = authentication.getPrincipal(); - //增加id参数 - if (principal instanceof SysUser) { - SysUser user = (SysUser)principal; - if (responseTypes.contains(SecurityConstants.ID_TOKEN)) { - //生成id_token - setIdToken(additionalInfo, authentication, keyProperties, clientService, user); - } - if ("authJwt".equals(tokenStoreProperties.getType())) { - additionalInfo.put("id", user.getId()); - } - } - } - ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo); - return accessToken; - }; - } - - /** - * 生成id_token - * @param additionalInfo 存储token附加信息对象 - * @param authentication 授权对象 - * @param keyProperties 密钥 - * @param clientService 应用service - */ - private void setIdToken(Map additionalInfo, OAuth2Authentication authentication - , KeyProperties keyProperties, IClientService clientService, SysUser user) { - String clientId = authentication.getOAuth2Request().getClientId(); - Client client = clientService.loadClientByClientId(clientId); - if (client.getSupportIdToken()) { - String nonce = authentication.getOAuth2Request().getRequestParameters().get(IdTokenClaimNames.NONCE); - long now = System.currentTimeMillis(); - long expiresAt = System.currentTimeMillis() + client.getIdTokenValiditySeconds() * 1000; - String idToken = OidcIdTokenBuilder.builder(keyProperties) - .issuer(SecurityConstants.ISS) - .issuedAt(now) - .expiresAt(expiresAt) - .subject(String.valueOf(user.getId())) - .name(user.getNickname()) - .loginName(user.getUsername()) - .picture(user.getHeadImgUrl()) - .audience(clientId) - .nonce(nonce) - .build(); - - additionalInfo.put(SecurityConstants.ID_TOKEN, idToken); - } - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java deleted file mode 100644 index 359c84756..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.central.oauth.config; - -import com.central.common.constant.SecurityConstants; -import com.central.common.properties.TenantProperties; -import com.central.oauth.filter.LoginProcessSetTenantFilter; -import com.central.oauth.handler.OauthLogoutSuccessHandler; -import com.central.oauth.password.PasswordAuthenticationProvider; -import com.central.oauth.service.impl.UserDetailServiceFactory; -import com.central.oauth.tenant.TenantAuthenticationSecurityConfig; -import com.central.oauth.tenant.TenantUsernamePasswordAuthenticationFilter; -import com.central.oauth.mobile.MobileAuthenticationSecurityConfig; -import com.central.oauth.openid.OpenIdAuthenticationSecurityConfig; -import com.central.common.config.DefaultPasswordConfig; -import com.central.oauth2.common.token.CustomWebAuthenticationDetails; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.security.authentication.AuthenticationDetailsSource; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; -import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.security.web.authentication.logout.LogoutHandler; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; - -/** - * spring security配置 - * 在WebSecurityConfigurerAdapter不拦截oauth要开放的资源 - * - * @author zlt - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Configuration -@Import(DefaultPasswordConfig.class) -public class SecurityConfig extends WebSecurityConfigurerAdapter { - - @Autowired - private AuthenticationSuccessHandler authenticationSuccessHandler; - - @Autowired(required = false) - private AuthenticationEntryPoint authenticationEntryPoint; - - @Resource - private UserDetailServiceFactory userDetailsServiceFactory; - - @Autowired - private PasswordEncoder passwordEncoder; - - @Resource - private LogoutHandler logoutHandler; - - @Resource - private LogoutSuccessHandler logoutSuccessHandler; - - @Autowired - private OpenIdAuthenticationSecurityConfig openIdAuthenticationSecurityConfig; - - @Autowired - private MobileAuthenticationSecurityConfig mobileAuthenticationSecurityConfig; - - @Autowired - private AuthenticationManager authenticationManager; - - @Autowired - private TenantAuthenticationSecurityConfig tenantAuthenticationSecurityConfig; - - @Autowired - private TenantProperties tenantProperties; - - @Autowired - private AuthenticationDetailsSource authenticationDetailsSource; - - /** - * 这一步的配置是必不可少的,否则SpringBoot会自动配置一个AuthenticationManager,覆盖掉内存中的用户 - * @return 认证管理对象 - */ - @Bean - @Override - public AuthenticationManager authenticationManagerBean() throws Exception { - return super.authenticationManagerBean(); - } - - @Bean - public TenantUsernamePasswordAuthenticationFilter tenantAuthenticationFilter(AuthenticationManager authenticationManager) { - TenantUsernamePasswordAuthenticationFilter filter = new TenantUsernamePasswordAuthenticationFilter(); - filter.setAuthenticationManager(authenticationManager); - filter.setFilterProcessesUrl(SecurityConstants.OAUTH_LOGIN_PRO_URL); - filter.setAuthenticationSuccessHandler(authenticationSuccessHandler); - filter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler(SecurityConstants.LOGIN_FAILURE_PAGE)); - filter.setAuthenticationDetailsSource(authenticationDetailsSource); - return filter; - } - - @Override - protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests() - .anyRequest() - //授权服务器关闭basic认证 - .permitAll() - .and() - .logout() - .logoutUrl(SecurityConstants.LOGOUT_URL) - .logoutSuccessHandler(logoutSuccessHandler) - .addLogoutHandler(logoutHandler) - .clearAuthentication(true) - .and() - .apply(openIdAuthenticationSecurityConfig) - .and() - .apply(mobileAuthenticationSecurityConfig) - .and() - .addFilterBefore(new LoginProcessSetTenantFilter(), UsernamePasswordAuthenticationFilter.class) - .csrf().disable() - // 解决不允许显示在iframe的问题 - .headers().frameOptions().disable().cacheControl(); - - if (tenantProperties.getEnable()) { - //解决不同租户单点登录时角色没变化 - http.formLogin() - .loginPage(SecurityConstants.LOGIN_PAGE) - .and() - .addFilterAt(tenantAuthenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class) - .apply(tenantAuthenticationSecurityConfig); - } else { - http.formLogin() - .loginPage(SecurityConstants.LOGIN_PAGE) - .loginProcessingUrl(SecurityConstants.OAUTH_LOGIN_PRO_URL) - .successHandler(authenticationSuccessHandler) - .authenticationDetailsSource(authenticationDetailsSource); - } - - - // 基于密码 等模式可以无session,不支持授权码模式 - if (authenticationEntryPoint != null) { - http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint); - http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); - } else { - // 授权码模式单独处理,需要session的支持,此模式可以支持所有oauth2的认证 - http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED); - } - } - - /** - * 全局用户信息 - */ - @Override - public void configure(AuthenticationManagerBuilder auth) { - PasswordAuthenticationProvider provider = new PasswordAuthenticationProvider(); - provider.setPasswordEncoder(passwordEncoder); - provider.setUserDetailsServiceFactory(userDetailsServiceFactory); - auth.authenticationProvider(provider); - } - /*public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception { - auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder); - }*/ -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/SecurityHandlerConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/SecurityHandlerConfig.java deleted file mode 100644 index 214663136..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/config/SecurityHandlerConfig.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.central.oauth.config; - -import com.central.oauth.exception.ValidateCodeException; -import com.central.oauth.handler.OauthLogoutHandler; -import com.central.oauth.handler.OauthLogoutSuccessHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.ResponseEntity; -import org.springframework.security.authentication.InternalAuthenticationServiceException; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.common.exceptions.*; -import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; -import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; -import org.springframework.security.web.authentication.logout.LogoutHandler; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * 认证错误处理 - * - * @author zlt - */ -@Slf4j -@Configuration -public class SecurityHandlerConfig { - @Bean - public LogoutHandler logoutHandler() { - return new OauthLogoutHandler(); - } - - @Bean - public LogoutSuccessHandler logoutSuccessHandler() { - return new OauthLogoutSuccessHandler(); - } - - @Bean - public WebResponseExceptionTranslator webResponseExceptionTranslator() { - return new DefaultWebResponseExceptionTranslator() { - private static final String BAD_MSG = "坏的凭证"; - private static final String BAD_MSG_EN = "Bad credentials"; - - @Override - public ResponseEntity translate(Exception e) throws Exception { - OAuth2Exception oAuth2Exception; - if (e.getMessage() != null - && (BAD_MSG.equals(e.getMessage()) || BAD_MSG_EN.equals(e.getMessage()))) { - oAuth2Exception = new InvalidGrantException("用户名或密码错误", e); - } else if (e instanceof InternalAuthenticationServiceException - || e instanceof ValidateCodeException) { - oAuth2Exception = new InvalidGrantException(e.getMessage(), e); - } else if (e instanceof OAuth2Exception) { - oAuth2Exception = (OAuth2Exception)e; - } else { - oAuth2Exception = new UnsupportedResponseTypeException("服务内部错误", e); - } - ResponseEntity response = super.translate(oAuth2Exception); - ResponseEntity.status(oAuth2Exception.getHttpErrorCode()); - response.getBody().addAdditionalInformation("resp_code", oAuth2Exception.getHttpErrorCode() + ""); - response.getBody().addAdditionalInformation("resp_msg", oAuth2Exception.getMessage()); - - return response; - } - }; - } - - /** - * 登陆成功 - */ - @Bean - public AuthenticationSuccessHandler loginSuccessHandler() { - return new SavedRequestAwareAuthenticationSuccessHandler() { - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, - Authentication authentication) throws IOException, ServletException { - super.onAuthenticationSuccess(request, response, authentication); - } - }; - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/TokenGranterConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/TokenGranterConfig.java deleted file mode 100644 index 067ca3c78..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/config/TokenGranterConfig.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.central.oauth.config; - -import com.central.oauth.granter.MobilePwdGranter; -import com.central.oauth.granter.OpenIdGranter; -import com.central.oauth.granter.PwdImgCodeGranter; -import com.central.oauth.service.IValidateCodeService; -import com.central.oauth.service.impl.CustomTokenServices; -import com.central.oauth.service.impl.UserDetailServiceFactory; -import com.central.oauth.service.impl.UserDetailsByNameServiceFactoryWrapper; -import com.central.oauth2.common.properties.SecurityProperties; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.ProviderManager; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.*; -import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; -import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; -import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; -import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; -import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices; -import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter; -import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter; -import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter; -import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; -import org.springframework.security.oauth2.provider.token.*; -import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * token授权模式配置类 - * - * @author zlt - * @date 2020/7/11 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Configuration -public class TokenGranterConfig { - @Autowired - private ClientDetailsService clientDetailsService; - - @Resource - private UserDetailServiceFactory userDetailsServiceFactory; - - @Autowired - private AuthenticationManager authenticationManager; - - @Autowired - private TokenStore tokenStore; - - @Autowired(required = false) - private List tokenEnhancer; - - @Autowired - private IValidateCodeService validateCodeService; - - @Autowired - private RandomValueAuthorizationCodeServices authorizationCodeServices; - - private boolean reuseRefreshToken = true; - - private AuthorizationServerTokenServices tokenServices; - - private TokenGranter tokenGranter; - - @Resource - private SecurityProperties securityProperties; - - /** - * 授权模式 - */ - @Bean - @ConditionalOnMissingBean - public TokenGranter tokenGranter(DefaultTokenServices tokenServices) { - if (tokenGranter == null) { - tokenGranter = new TokenGranter() { - private CompositeTokenGranter delegate; - - @Override - public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { - if (delegate == null) { - delegate = new CompositeTokenGranter(getAllTokenGranters(tokenServices)); - } - return delegate.grant(grantType, tokenRequest); - } - }; - } - return tokenGranter; - } - - /** - * 所有授权模式:默认的5种模式 + 自定义的模式 - */ - protected List getAllTokenGranters(DefaultTokenServices tokenServices) { - AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices(); - OAuth2RequestFactory requestFactory = requestFactory(); - //获取默认的授权模式 - List tokenGranters = getDefaultTokenGranters(tokenServices, authorizationCodeServices, requestFactory); - if (authenticationManager != null) { - // 添加密码加图形验证码模式 - tokenGranters.add(new PwdImgCodeGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory, validateCodeService)); - // 添加openId模式 - tokenGranters.add(new OpenIdGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory)); - // 添加手机号加密码授权模式 - tokenGranters.add(new MobilePwdGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory)); - } - return tokenGranters; - } - - /** - * 默认的授权模式 - */ - private List getDefaultTokenGranters(AuthorizationServerTokenServices tokenServices - , AuthorizationCodeServices authorizationCodeServices, OAuth2RequestFactory requestFactory) { - List tokenGranters = new ArrayList<>(); - // 添加授权码模式 - tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetailsService, requestFactory)); - // 添加刷新令牌的模式 - tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetailsService, requestFactory)); - // 添加隐士授权模式 - tokenGranters.add(new ImplicitTokenGranter(tokenServices, clientDetailsService, requestFactory)); - // 添加客户端模式 - tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, requestFactory)); - if (authenticationManager != null) { - // 添加密码模式 - tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory)); - } - return tokenGranters; - } - - private AuthorizationCodeServices authorizationCodeServices() { - if (authorizationCodeServices == null) { - authorizationCodeServices = new InMemoryAuthorizationCodeServices(); - } - return authorizationCodeServices; - } - - private OAuth2RequestFactory requestFactory() { - return new DefaultOAuth2RequestFactory(clientDetailsService); - } - - @Bean - @ConditionalOnMissingBean - protected DefaultTokenServices createDefaultTokenServices() { - DefaultTokenServices tokenServices = new CustomTokenServices(securityProperties.getAuth()); - tokenServices.setTokenStore(tokenStore); - tokenServices.setSupportRefreshToken(true); - tokenServices.setReuseRefreshToken(reuseRefreshToken); - tokenServices.setClientDetailsService(clientDetailsService); - tokenServices.setTokenEnhancer(tokenEnhancer()); - addUserDetailsService(tokenServices); - return tokenServices; - } - - private TokenEnhancer tokenEnhancer() { - if (tokenEnhancer != null) { - TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain(); - tokenEnhancerChain.setTokenEnhancers(tokenEnhancer); - return tokenEnhancerChain; - } - return null; - } - - private void addUserDetailsService(DefaultTokenServices tokenServices) { - if (this.userDetailsServiceFactory != null) { - PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider(); - provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceFactoryWrapper<>(this.userDetailsServiceFactory)); - tokenServices.setAuthenticationManager(new ProviderManager(Collections.singletonList(provider))); - } - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/WebMvcConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/WebMvcConfig.java index b98efd9a3..fd4b21a07 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/config/WebMvcConfig.java +++ b/zlt-uaa/src/main/java/com/central/oauth/config/WebMvcConfig.java @@ -1,12 +1,14 @@ package com.central.oauth.config; -import com.central.common.config.DefaultWebMvcConfig; -import org.springframework.context.annotation.Configuration; +/*import com.central.common.config.DefaultWebMvcConfig; +import org.springframework.context.annotation.Configuration;*/ /** * @author zlt * @date 2019/8/5 */ +/* @Configuration public class WebMvcConfig extends DefaultWebMvcConfig { } +*/ diff --git a/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java b/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java index 4dd8097a5..cc33dad2e 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java +++ b/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java @@ -6,8 +6,8 @@ import com.central.oauth.model.Client; import com.central.oauth.service.IClientService; import com.google.common.collect.Maps; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -22,7 +22,7 @@ * Blog: https://zlt2000.gitee.io * Github: https://github.com/zlt2000 */ -@Api(tags = "应用") +@Tag(name = "应用") @RestController @RequestMapping("/clients") public class ClientController { @@ -30,32 +30,32 @@ public class ClientController { private IClientService clientService; @GetMapping("/list") - @ApiOperation(value = "应用列表") + @Operation(summary = "应用列表") public PageResult list(@RequestParam Map params) { return clientService.listClient(params, true); } @GetMapping("/{id}") - @ApiOperation(value = "根据id获取应用") + @Operation(summary = "根据id获取应用") public Client get(@PathVariable Long id) { return clientService.getById(id); } @GetMapping("/all") - @ApiOperation(value = "所有应用") + @Operation(summary = "所有应用") public Result> allClient() { PageResult page = clientService.listClient(Maps.newHashMap(), false); return Result.succeed(page.getData()); } @DeleteMapping("/{id}") - @ApiOperation(value = "删除应用") + @Operation(summary = "删除应用") public void delete(@PathVariable Long id) { clientService.delClient(id); } @PostMapping("/saveOrUpdate") - @ApiOperation(value = "保存或者修改应用") + @Operation(summary = "保存或者修改应用") public Result saveOrUpdate(@RequestBody ClientDto clientDto) throws Exception { return clientService.saveClient(clientDto); } diff --git a/zlt-uaa/src/main/java/com/central/oauth/controller/TokensController.java b/zlt-uaa/src/main/java/com/central/oauth/controller/TokensController.java deleted file mode 100644 index 088d44f36..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/controller/TokensController.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.central.oauth.controller; - -import com.central.common.constant.SecurityConstants; -import com.central.common.model.PageResult; -import com.central.common.model.Result; -import com.central.oauth.model.TokenVo; -import com.central.oauth.service.ITokensService; -import com.central.oauth2.common.util.AuthUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.io.ClassPathResource; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * token管理接口 - * - * @author zlt - */ -@Api(tags = "Token管理") -@Slf4j -@RestController -@RequestMapping("/tokens") -public class TokensController { - @Resource - private ITokensService tokensService; - - @Resource - private ClientDetailsService clientDetailsService; - - @Resource - private PasswordEncoder passwordEncoder; - - @GetMapping("") - @ApiOperation(value = "token列表") - public PageResult list(@RequestParam Map params, String tenantId) { - return tokensService.listTokens(params, tenantId); - } - - @GetMapping("/key") - @ApiOperation(value = "获取jwt密钥") - public Result key(HttpServletRequest request) { - try { - String[] clientArr = AuthUtils.extractClient(request); - ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientArr[0]); - if (clientDetails == null || !passwordEncoder.matches(clientArr[1], clientDetails.getClientSecret())) { - throw new BadCredentialsException("应用ID或密码错误"); - } - } catch (AuthenticationException ae) { - return Result.failed(ae.getMessage()); - } - org.springframework.core.io.Resource res = new ClassPathResource(SecurityConstants.RSA_PUBLIC_KEY); - try (BufferedReader br = new BufferedReader(new InputStreamReader(res.getInputStream()))) { - return Result.succeed(br.lines().collect(Collectors.joining("\n"))); - } catch (IOException ioe) { - log.error("key error", ioe); - return Result.failed(ioe.getMessage()); - } - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/controller/ValidateCodeController.java b/zlt-uaa/src/main/java/com/central/oauth/controller/ValidateCodeController.java index a85d4726c..dd7170ceb 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/controller/ValidateCodeController.java +++ b/zlt-uaa/src/main/java/com/central/oauth/controller/ValidateCodeController.java @@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; /** * 验证码提供 @@ -31,7 +32,7 @@ public class ValidateCodeController { * @throws Exception */ @GetMapping(SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX + "/{deviceId}") - public void createCode(@PathVariable String deviceId, HttpServletResponse response) throws Exception { + public void createCode(@PathVariable String deviceId, HttpServletResponse response) throws IOException { Assert.notNull(deviceId, "机器码不能为空"); // 设置请求头为输出图片类型 CaptchaUtil.setHeader(response); @@ -54,7 +55,7 @@ public void createCode(@PathVariable String deviceId, HttpServletResponse respon */ @ResponseBody @GetMapping(SecurityConstants.MOBILE_VALIDATE_CODE_URL_PREFIX + "/{mobile}") - public Result createCode(@PathVariable String mobile) { + public Result createCode(@PathVariable String mobile) { Assert.notNull(mobile, "手机号不能为空"); return validateCodeService.sendSmsCode(mobile); } diff --git a/zlt-uaa/src/main/java/com/central/oauth/filter/LoginProcessSetTenantFilter.java b/zlt-uaa/src/main/java/com/central/oauth/filter/LoginProcessSetTenantFilter.java deleted file mode 100644 index da6dad123..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/filter/LoginProcessSetTenantFilter.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.central.oauth.filter; - -import cn.hutool.core.util.ArrayUtil; -import com.central.common.constant.SecurityConstants; -import com.central.common.context.TenantContextHolder; -import org.springframework.http.HttpMethod; -import org.springframework.security.web.savedrequest.DefaultSavedRequest; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; -import org.springframework.security.web.util.matcher.RequestMatcher; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * 设置租户id过滤器 - * - * @author zlt - * @date 2020/3/29 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class LoginProcessSetTenantFilter extends OncePerRequestFilter { - private static final String SAVED_REQUEST = "SPRING_SECURITY_SAVED_REQUEST"; - - private RequestMatcher requiresAuthenticationRequestMatcher; - public LoginProcessSetTenantFilter() { - requiresAuthenticationRequestMatcher = new AntPathRequestMatcher(SecurityConstants.OAUTH_LOGIN_PRO_URL, HttpMethod.POST.name()); - } - - /** - * 返回true代表不执行过滤器,false代表执行 - */ - @Override - protected boolean shouldNotFilter(HttpServletRequest request) { - if (requiresAuthentication(request)) { - return false; - } - return true; - } - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { - try { - DefaultSavedRequest savedRequest = (DefaultSavedRequest)request.getSession().getAttribute(SAVED_REQUEST); - if (savedRequest != null) { - String[] clientIds = savedRequest.getParameterValues("client_id"); - if (ArrayUtil.isNotEmpty(clientIds)) { - //保存租户id - TenantContextHolder.setTenant(clientIds[0]); - } - } - chain.doFilter(request, response); - } finally { - TenantContextHolder.clear(); - } - } - - private boolean requiresAuthentication(HttpServletRequest request) { - return requiresAuthenticationRequestMatcher.matches(request); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/filter/OauthTokenAspect.java b/zlt-uaa/src/main/java/com/central/oauth/filter/OauthTokenAspect.java deleted file mode 100644 index 822b9c7c9..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/filter/OauthTokenAspect.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.central.oauth.filter; - -import com.central.common.constant.SecurityConstants; -import com.central.common.context.TenantContextHolder; -import com.central.common.model.Result; -import com.central.oauth.handler.decryptParamHandler.IDecryptParamHandler; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import java.security.Principal; -import java.util.Map; - -/** - * oauth-token拦截器 - * 1. 赋值租户 - * 2. 统一返回token格式 - * - * @author zlt - * @date 2020/3/29 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -@Component -@Aspect -public class OauthTokenAspect { - @Resource - private IDecryptParamHandler decryptParamHandler; - - @Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))") - public Object handleControllerMethod(ProceedingJoinPoint joinPoint) throws Throwable { - try { - Object[] args = joinPoint.getArgs(); - Principal principal = (Principal) args[0]; - if (!(principal instanceof Authentication)) { - throw new OAuth2Exception( - "There is no client authentication. Try adding an appropriate authentication filter."); - } - String clientId = getClientId(principal); - Map parameters = (Map) args[1]; - //解密参数 - decryptParamHandler.decryptParams(parameters); - - String grantType = parameters.get(OAuth2Utils.GRANT_TYPE); - if (!parameters.containsKey(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME)) { - parameters.put(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME, SecurityConstants.DEF_ACCOUNT_TYPE); - } - - //保存租户id - TenantContextHolder.setTenant(clientId); - Object proceed = joinPoint.proceed(args); - if (SecurityConstants.AUTHORIZATION_CODE.equals(grantType)) { - /* - 如果使用 @EnableOAuth2Sso 注解不能修改返回格式,否则授权码模式可以统一改 - 因为本项目的 sso-demo/ss-sso 里面使用了 @EnableOAuth2Sso 注解,所以这里就不修改授权码模式的token返回值了 - */ - return proceed; - } else { - ResponseEntity responseEntity = (ResponseEntity) proceed; - OAuth2AccessToken body = responseEntity.getBody(); - return ResponseEntity - .status(HttpStatus.OK) - .body(Result.succeed(body)); - } - } finally { - TenantContextHolder.clear(); - } - } - - private String getClientId(Principal principal) { - Authentication client = (Authentication) principal; - if (!client.isAuthenticated()) { - throw new OAuth2Exception("The client is not authenticated."); - } - String clientId = client.getName(); - if (client instanceof OAuth2Authentication) { - clientId = ((OAuth2Authentication) client).getOAuth2Request().getClientId(); - } - return clientId; - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/granter/MobilePwdGranter.java b/zlt-uaa/src/main/java/com/central/oauth/granter/MobilePwdGranter.java deleted file mode 100644 index 1f774e0db..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/granter/MobilePwdGranter.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.central.oauth.granter; - -import com.central.oauth2.common.token.MobileAuthenticationToken; -import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.core.Authentication; -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 java.util.LinkedHashMap; -import java.util.Map; - -/** - * openId授权模式 - * - * @author zlt - * @date 2020/7/11 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class MobilePwdGranter extends AbstractTokenGranter { - private static final String GRANT_TYPE = "mobile_password"; - - private final AuthenticationManager authenticationManager; - - public MobilePwdGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices - , ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { - super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); - this.authenticationManager = authenticationManager; - } - - @Override - protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { - Map parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters()); - String mobile = parameters.get("mobile"); - String password = parameters.get("password"); - // Protect from downstream leaks of password - parameters.remove("password"); - - Authentication userAuth = new MobileAuthenticationToken(mobile, password); - ((AbstractAuthenticationToken) userAuth).setDetails(parameters); - userAuth = authenticationManager.authenticate(userAuth); - if (userAuth == null || !userAuth.isAuthenticated()) { - throw new InvalidGrantException("Could not authenticate mobile: " + mobile); - } - - OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest); - return new OAuth2Authentication(storedOAuth2Request, userAuth); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/granter/OpenIdGranter.java b/zlt-uaa/src/main/java/com/central/oauth/granter/OpenIdGranter.java deleted file mode 100644 index fc95bce4f..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/granter/OpenIdGranter.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.central.oauth.granter; - -import com.central.oauth2.common.token.OpenIdAuthenticationToken; -import org.springframework.security.authentication.*; -import org.springframework.security.core.Authentication; -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 java.util.LinkedHashMap; -import java.util.Map; - -/** - * openId授权模式 - * - * @author zlt - * @date 2020/7/11 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class OpenIdGranter extends AbstractTokenGranter { - private static final String GRANT_TYPE = "openId"; - - private final AuthenticationManager authenticationManager; - - public OpenIdGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices - , ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { - super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); - this.authenticationManager = authenticationManager; - } - - @Override - protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { - Map parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters()); - String openId = parameters.get("openId"); - - Authentication userAuth = new OpenIdAuthenticationToken(openId); - ((AbstractAuthenticationToken) userAuth).setDetails(parameters); - userAuth = authenticationManager.authenticate(userAuth); - if (userAuth == null || !userAuth.isAuthenticated()) { - throw new InvalidGrantException("Could not authenticate openId: " + openId); - } - - OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest); - return new OAuth2Authentication(storedOAuth2Request, userAuth); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/granter/PwdImgCodeGranter.java b/zlt-uaa/src/main/java/com/central/oauth/granter/PwdImgCodeGranter.java deleted file mode 100644 index 53d2b0d6c..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/granter/PwdImgCodeGranter.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.central.oauth.granter; - -import com.central.oauth.service.IValidateCodeService; -import org.springframework.security.authentication.*; -import org.springframework.security.oauth2.provider.*; -import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter; -import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * password添加图像验证码授权模式 - * - * @author zlt - * @date 2020/7/11 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class PwdImgCodeGranter extends ResourceOwnerPasswordTokenGranter { - private static final String GRANT_TYPE = "password_code"; - - private final IValidateCodeService validateCodeService; - - public PwdImgCodeGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices - , ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, IValidateCodeService validateCodeService) { - super(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); - this.validateCodeService = validateCodeService; - } - - @Override - protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { - Map parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters()); - String deviceId = parameters.get("deviceId"); - String validCode = parameters.get("validCode"); - //校验图形验证码 - validateCodeService.validate(deviceId, validCode); - - return super.getOAuth2Authentication(client, tokenRequest); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutHandler.java b/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutHandler.java deleted file mode 100644 index b3a3d49f5..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.central.oauth.handler; - -import cn.hutool.core.util.StrUtil; -import com.central.oauth.utils.UsernameHolder; -import com.central.oauth2.common.properties.SecurityProperties; -import com.central.oauth2.common.util.AuthUtils; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.OAuth2RefreshToken; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.web.authentication.logout.LogoutHandler; -import org.springframework.util.Assert; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * @author zlt - * @date 2018/10/17 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -public class OauthLogoutHandler implements LogoutHandler { - @Resource - private TokenStore tokenStore; - - @Resource - private SecurityProperties securityProperties; - - @Override - public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { - Assert.notNull(tokenStore, "tokenStore must be set"); - String token = request.getParameter("token"); - if (StrUtil.isEmpty(token)) { - token = AuthUtils.extractToken(request); - } - if(StrUtil.isNotEmpty(token)){ - if (securityProperties.getAuth().getUnifiedLogout()) { - OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(token); - UsernameHolder.setContext(oAuth2Authentication.getName()); - } - - OAuth2AccessToken existingAccessToken = tokenStore.readAccessToken(token); - OAuth2RefreshToken refreshToken; - if (existingAccessToken != null) { - if (existingAccessToken.getRefreshToken() != null) { - log.info("remove refreshToken!", existingAccessToken.getRefreshToken()); - refreshToken = existingAccessToken.getRefreshToken(); - tokenStore.removeRefreshToken(refreshToken); - } - log.info("remove existingAccessToken!", existingAccessToken); - tokenStore.removeAccessToken(existingAccessToken); - } - } - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutSuccessHandler.java b/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutSuccessHandler.java deleted file mode 100644 index 78dae8e06..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutSuccessHandler.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.central.oauth.handler; - -import cn.hutool.core.util.StrUtil; -import com.central.common.model.Result; -import com.central.common.utils.JsonUtil; -import com.central.oauth.service.impl.UnifiedLogoutService; -import com.central.oauth2.common.properties.SecurityProperties; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.DefaultRedirectStrategy; -import org.springframework.security.web.RedirectStrategy; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; - -/** - * @author zlt - * @date 2020/3/10 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -public class OauthLogoutSuccessHandler implements LogoutSuccessHandler { - private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); - - @Resource - private UnifiedLogoutService unifiedLogoutService; - - @Resource - private SecurityProperties securityProperties; - - @Override - public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { - if (securityProperties.getAuth().getUnifiedLogout()) { - unifiedLogoutService.allLogout(); - } - - String redirectUri = request.getParameter("redirect_uri"); - if (StrUtil.isNotEmpty(redirectUri)) { - //重定向指定的地址 - redirectStrategy.sendRedirect(request, response, redirectUri); - } else { - response.setStatus(HttpStatus.OK.value()); - response.setCharacterEncoding("UTF-8"); - response.setContentType(MediaType.APPLICATION_JSON_VALUE); - PrintWriter writer = response.getWriter(); - String jsonStr = JsonUtil.toJSONString(Result.succeed("登出成功")); - writer.write(jsonStr); - writer.flush(); - } - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/handler/decryptParamHandler/IDecryptParamHandler.java b/zlt-uaa/src/main/java/com/central/oauth/handler/decryptParamHandler/IDecryptParamHandler.java deleted file mode 100644 index 942f3e1c3..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/handler/decryptParamHandler/IDecryptParamHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.central.oauth.handler.decryptParamHandler; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; - -import java.util.Map; - -/** - * 解密参数的处理接口 - * - * @author zlt - * @version 1.0 - * @date 2022/12/29 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public interface IDecryptParamHandler { - String SEPARATOR = ";"; - /** - * 需要解密的参数名,多个以 ; 隔离 - * 例如:decrypt_param=username;password - */ - String PARAM_KEY_DECRYPT_PARAM = "decrypt_param"; - - /** - * 根据 parameters里面decrypt_param 的值进行参数解密,并把解密后的值替换原值 - * @param parameters 参数集合 - */ - default void decryptParams(Map parameters) { - if (CollUtil.isNotEmpty(parameters)) { - //从 parameters 中获取 decrypt_param 参数值 - String decryptParam = parameters.get(PARAM_KEY_DECRYPT_PARAM); - //如果参数decrypt_param有值,则进行参数解密 - if (StrUtil.isNotEmpty(decryptParam)) { - String[] paramNames = decryptParam.split(SEPARATOR); - this.decrypt(paramNames, parameters); - } - } - } - - /** - * 解密并更新参数值 - * @param paramNames 需要解密的参数名 - * @param parameters 参数集合(参数名:参数值) - */ - void decrypt(String[] paramNames, Map parameters); -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/handler/decryptParamHandler/RsaDecryptParamHandler.java b/zlt-uaa/src/main/java/com/central/oauth/handler/decryptParamHandler/RsaDecryptParamHandler.java deleted file mode 100644 index ea324f5eb..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/handler/decryptParamHandler/RsaDecryptParamHandler.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.central.oauth.handler.decryptParamHandler; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.crypto.SecureUtil; -import cn.hutool.crypto.asymmetric.KeyType; -import cn.hutool.crypto.asymmetric.RSA; -import com.central.oauth2.common.properties.AuthProperties; -import com.central.oauth2.common.properties.SecurityProperties; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.stereotype.Service; - -import java.util.Map; - -/** - * 使用rsa算法对参数进行解密 - * - * @author zlt - * @version 1.0 - * @date 2022/12/29 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Service -public class RsaDecryptParamHandler implements IDecryptParamHandler { - private final AuthProperties authProperties; - - public RsaDecryptParamHandler(SecurityProperties securityProperties) { - this.authProperties = securityProperties.getAuth(); - } - - @Override - public void decrypt(String[] paramNames, Map parameters) { - RSA rsaTools = SecureUtil.rsa(authProperties.getDecryptParamPrivateKey(), null); - String value; - for (String param : paramNames) { - value = parameters.get(param); - if (StrUtil.isNotEmpty(value)) { - //解密 - value = this.decrypt(rsaTools, value, param); - //更新参数为解密后的值 - parameters.put(param, value); - } - } - } - - private String decrypt(RSA rsaTools, String value, String param) { - try { - return rsaTools.decryptStr(value, KeyType.PrivateKey); - } catch (Exception e) { - throw new OAuth2Exception("参数 " + param + " 解密失败!"); - } - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/listener/RedisKeyExpirationListener.java b/zlt-uaa/src/main/java/com/central/oauth/listener/RedisKeyExpirationListener.java deleted file mode 100644 index eb4e1db79..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/listener/RedisKeyExpirationListener.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.central.oauth.listener; - -import com.central.common.constant.SecurityConstants; -import com.central.common.redis.template.RedisRepository; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.data.redis.connection.Message; -import org.springframework.data.redis.connection.RedisConnection; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; -import org.springframework.data.redis.listener.RedisMessageListenerContainer; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy; -import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy; -import org.springframework.stereotype.Component; - -/** - * - * redis过期key监听器 - * @author zlt - * - */ -@Component -@Slf4j -public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener { - @Autowired - private RedisRepository redisRepository; - private RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy(); - private final RedisConnectionFactory connectionFactory; - - public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer, RedisConnectionFactory connectionFactory) { - super(listenerContainer); - this.connectionFactory = connectionFactory; - } - - @Override - public void onMessage(Message message, byte[] pattern) { - if (message == null) { - log.debug("message不能为空"); - return; - } - //获取失效的的key - String expiredKey = message.toString(); - if (StringUtils.isEmpty(expiredKey)) { - log.debug("expiredKey不能为空"); - return; - } - String accesskey = expiredKey.substring(0, expiredKey.indexOf(":") + 1); - if (!"access:".equals(accesskey)) { - log.debug("非需要监听key,跳过"); - return; - } - String accessValue = expiredKey.substring(expiredKey.indexOf(":") + 1); - // 分布式集群部署下防止一个过期被多个服务重复消费 - String qc = "qc:" + accessValue; - String oldLock = redisRepository.getAndSet(qc, "1"); - if (StringUtils.isNotEmpty(oldLock) && "1".equals(oldLock)) { - log.debug("其他节点已经处理了该数据,跳过"); - return; - } - byte[] accessBakKey = serializeKey(SecurityConstants.ACCESS_BAK + accessValue); - byte[] authKey = serializeKey(SecurityConstants.REDIS_TOKEN_AUTH + accessValue); - RedisConnection conn = getConnection(); - try { - byte[] access = conn.get(accessBakKey); - byte[] auth = conn.get(authKey); - OAuth2Authentication authentication = deserializeAuthentication(auth); - if (authentication != null) { - byte[] unameKey = serializeKey(SecurityConstants.REDIS_UNAME_TO_ACCESS + getApprovalKey(authentication)); - byte[] clientId = serializeKey(SecurityConstants.REDIS_CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId()); - conn.openPipeline(); - conn.lRem(unameKey, 1, access); - conn.lRem(clientId, 1, access); - conn.closePipeline(); - } - } catch (Exception e) { - log.error(e.getMessage()); - } finally { - conn.del(serializeKey(qc)); - conn.close(); - } - - } - - private byte[] serializeKey(String object) { - return serialize("" + object); - } - - private byte[] serialize(String string) { - return serializationStrategy.serialize(string); - } - - private RedisConnection getConnection() { - return connectionFactory.getConnection(); - } - - private OAuth2Authentication deserializeAuthentication(byte[] bytes) { - return serializationStrategy.deserialize(bytes, OAuth2Authentication.class); - } - - private static String getApprovalKey(OAuth2Authentication authentication) { - String userName = authentication.getUserAuthentication() == null ? "" - : authentication.getUserAuthentication().getName(); - return getApprovalKey(authentication.getOAuth2Request().getClientId(), userName); - } - - private static String getApprovalKey(String clientId, String userName) { - return clientId + (userName == null ? "" : ":" + userName); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/mobile/MobileAuthenticationProvider.java b/zlt-uaa/src/main/java/com/central/oauth/mobile/MobileAuthenticationProvider.java deleted file mode 100644 index 99e5fcdea..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/mobile/MobileAuthenticationProvider.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.central.oauth.mobile; - -import com.central.oauth.service.impl.UserDetailServiceFactory; -import com.central.oauth2.common.token.MobileAuthenticationToken; -import lombok.Getter; -import lombok.Setter; -import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.authentication.InternalAuthenticationServiceException; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.crypto.password.PasswordEncoder; - -/** - * @author zlt - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Setter -@Getter -public class MobileAuthenticationProvider implements AuthenticationProvider { - private UserDetailServiceFactory userDetailsServiceFactory; - private PasswordEncoder passwordEncoder; - - @Override - public Authentication authenticate(Authentication authentication) { - MobileAuthenticationToken authenticationToken = (MobileAuthenticationToken) authentication; - String mobile = (String) authenticationToken.getPrincipal(); - String password = (String) authenticationToken.getCredentials(); - UserDetails user = userDetailsServiceFactory.getService(authenticationToken).loadUserByMobile(mobile); - if (user == null) { - throw new InternalAuthenticationServiceException("手机号或密码错误"); - } - if (!passwordEncoder.matches(password, user.getPassword())) { - throw new InternalAuthenticationServiceException("手机号或密码错误"); - } - MobileAuthenticationToken authenticationResult = new MobileAuthenticationToken(user, password, user.getAuthorities()); - authenticationResult.setDetails(authenticationToken.getDetails()); - return authenticationResult; - } - - @Override - public boolean supports(Class authentication) { - return MobileAuthenticationToken.class.isAssignableFrom(authentication); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/mobile/MobileAuthenticationSecurityConfig.java b/zlt-uaa/src/main/java/com/central/oauth/mobile/MobileAuthenticationSecurityConfig.java deleted file mode 100644 index 4aaa7a9af..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/mobile/MobileAuthenticationSecurityConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.central.oauth.mobile; - -import com.central.oauth.service.impl.UserDetailServiceFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.config.annotation.SecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.DefaultSecurityFilterChain; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * mobile的相关处理配置 - * - * @author zlt - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Component -public class MobileAuthenticationSecurityConfig extends SecurityConfigurerAdapter { - @Resource - private UserDetailServiceFactory userDetailsServiceFactory; - - @Autowired - private PasswordEncoder passwordEncoder; - - @Override - public void configure(HttpSecurity http) { - //mobile provider - MobileAuthenticationProvider provider = new MobileAuthenticationProvider(); - provider.setUserDetailsServiceFactory(userDetailsServiceFactory); - provider.setPasswordEncoder(passwordEncoder); - http.authenticationProvider(provider); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/model/CustomAuthenticationDetailsSource.java b/zlt-uaa/src/main/java/com/central/oauth/model/CustomAuthenticationDetailsSource.java deleted file mode 100644 index 77e36ea4e..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/model/CustomAuthenticationDetailsSource.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.central.oauth.model; - -import com.central.common.constant.SecurityConstants; -import com.central.oauth2.common.token.CustomWebAuthenticationDetails; -import org.springframework.security.authentication.AuthenticationDetailsSource; -import org.springframework.stereotype.Component; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -/** - * 表单登录的认证信息对象 - * - * @author zlt - * @version 1.0 - * @date 2021/7/21 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Component -public class CustomAuthenticationDetailsSource implements AuthenticationDetailsSource { - @Override - public CustomWebAuthenticationDetails buildDetails(HttpServletRequest context) { - String remoteAddress = context.getRemoteAddr(); - HttpSession session = context.getSession(false); - String sessionId = session != null ? session.getId() : null; - String accountType = context.getParameter(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME); - return new CustomWebAuthenticationDetails(remoteAddress, sessionId, accountType); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/openid/OpenIdAuthenticationProvider.java b/zlt-uaa/src/main/java/com/central/oauth/openid/OpenIdAuthenticationProvider.java deleted file mode 100644 index 4a4623d8f..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/openid/OpenIdAuthenticationProvider.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.central.oauth.openid; - -import com.central.oauth.service.impl.UserDetailServiceFactory; -import com.central.oauth2.common.token.OpenIdAuthenticationToken; -import lombok.Getter; -import lombok.Setter; -import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.authentication.InternalAuthenticationServiceException; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; - -/** - * @author zlt - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Setter -@Getter -public class OpenIdAuthenticationProvider implements AuthenticationProvider { - private UserDetailServiceFactory userDetailsServiceFactory; - - @Override - public Authentication authenticate(Authentication authentication) { - OpenIdAuthenticationToken authenticationToken = (OpenIdAuthenticationToken) authentication; - String openId = (String) authenticationToken.getPrincipal(); - UserDetails user = userDetailsServiceFactory.getService(authenticationToken).loadUserByUserId(openId); - if (user == null) { - throw new InternalAuthenticationServiceException("openId错误"); - } - OpenIdAuthenticationToken authenticationResult = new OpenIdAuthenticationToken(user, user.getAuthorities()); - authenticationResult.setDetails(authenticationToken.getDetails()); - return authenticationResult; - } - - @Override - public boolean supports(Class authentication) { - return OpenIdAuthenticationToken.class.isAssignableFrom(authentication); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/openid/OpenIdAuthenticationSecurityConfig.java b/zlt-uaa/src/main/java/com/central/oauth/openid/OpenIdAuthenticationSecurityConfig.java deleted file mode 100644 index f5ef56cba..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/openid/OpenIdAuthenticationSecurityConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.central.oauth.openid; - -import com.central.oauth.service.impl.UserDetailServiceFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.config.annotation.SecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.web.DefaultSecurityFilterChain; -import org.springframework.stereotype.Component; - -/** - * openId的相关处理配置 - * - * @author zlt - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Component -public class OpenIdAuthenticationSecurityConfig extends SecurityConfigurerAdapter { - @Autowired - private UserDetailServiceFactory userDetailsServiceFactory; - - @Override - public void configure(HttpSecurity http) { - //openId provider - OpenIdAuthenticationProvider provider = new OpenIdAuthenticationProvider(); - provider.setUserDetailsServiceFactory(userDetailsServiceFactory); - http.authenticationProvider(provider); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/password/PasswordAuthenticationProvider.java b/zlt-uaa/src/main/java/com/central/oauth/password/PasswordAuthenticationProvider.java deleted file mode 100644 index 7fbdd579a..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/password/PasswordAuthenticationProvider.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.central.oauth.password; - -import com.central.oauth.service.impl.UserDetailServiceFactory; -import lombok.Getter; -import lombok.Setter; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.InternalAuthenticationServiceException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsPasswordService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.factory.PasswordEncoderFactories; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.util.Assert; - -/** - * 扩展用户名密码provider - * - * @author zlt - * @version 1.0 - * @date 2021/7/24 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Setter -@Getter -public class PasswordAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { - private UserDetailServiceFactory userDetailsServiceFactory; - - private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword"; - - private PasswordEncoder passwordEncoder; - - /** - * The password used to perform - * {@link PasswordEncoder#matches(CharSequence, String)} on when the user is - * not found to avoid SEC-2056. This is necessary, because some - * {@link PasswordEncoder} implementations will short circuit if the password is not - * in a valid format. - */ - private volatile String userNotFoundEncodedPassword; - - private UserDetailsPasswordService userDetailsPasswordService; - - public PasswordAuthenticationProvider() { - setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder()); - } - - // ~ Methods - // ======================================================================================================== - - @Override - @SuppressWarnings("deprecation") - protected void additionalAuthenticationChecks(UserDetails userDetails, - UsernamePasswordAuthenticationToken authentication) - throws AuthenticationException { - if (authentication.getCredentials() == null) { - logger.debug("Authentication failed: no credentials provided"); - - throw new BadCredentialsException(messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.badCredentials", - "Bad credentials")); - } - - String presentedPassword = authentication.getCredentials().toString(); - - if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) { - logger.debug("Authentication failed: password does not match stored value"); - - throw new BadCredentialsException(messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.badCredentials", - "Bad credentials")); - } - } - - @Override - protected void doAfterPropertiesSet() { - Assert.notNull(this.userDetailsServiceFactory, "A UserDetailsService must be set"); - } - - @Override - protected final UserDetails retrieveUser(String username, - UsernamePasswordAuthenticationToken authentication) - throws AuthenticationException { - prepareTimingAttackProtection(); - try { - UserDetails loadedUser = userDetailsServiceFactory.getService(authentication).loadUserByUsername(username); - if (loadedUser == null) { - throw new InternalAuthenticationServiceException( - "UserDetailsService returned null, which is an interface contract violation"); - } - return loadedUser; - } - catch (UsernameNotFoundException ex) { - mitigateAgainstTimingAttack(authentication); - throw ex; - } - catch (InternalAuthenticationServiceException ex) { - throw ex; - } - catch (Exception ex) { - throw new InternalAuthenticationServiceException(ex.getMessage(), ex); - } - } - - @Override - protected Authentication createSuccessAuthentication(Object principal, - Authentication authentication, UserDetails user) { - boolean upgradeEncoding = this.userDetailsPasswordService != null - && this.passwordEncoder.upgradeEncoding(user.getPassword()); - if (upgradeEncoding) { - String presentedPassword = authentication.getCredentials().toString(); - String newPassword = this.passwordEncoder.encode(presentedPassword); - user = this.userDetailsPasswordService.updatePassword(user, newPassword); - } - return super.createSuccessAuthentication(principal, authentication, user); - } - - private void prepareTimingAttackProtection() { - if (this.userNotFoundEncodedPassword == null) { - this.userNotFoundEncodedPassword = this.passwordEncoder.encode(USER_NOT_FOUND_PASSWORD); - } - } - - private void mitigateAgainstTimingAttack(UsernamePasswordAuthenticationToken authentication) { - if (authentication.getCredentials() != null) { - String presentedPassword = authentication.getCredentials().toString(); - this.passwordEncoder.matches(presentedPassword, this.userNotFoundEncodedPassword); - } - } - - /** - * Sets the PasswordEncoder instance to be used to encode and validate passwords. If - * not set, the password will be compared using {@link PasswordEncoderFactories#createDelegatingPasswordEncoder()} - * - * @param passwordEncoder must be an instance of one of the {@code PasswordEncoder} - * types. - */ - public void setPasswordEncoder(PasswordEncoder passwordEncoder) { - Assert.notNull(passwordEncoder, "passwordEncoder cannot be null"); - this.passwordEncoder = passwordEncoder; - this.userNotFoundEncodedPassword = null; - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java b/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java index eed136a1b..490bc0c78 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java @@ -1,29 +1,29 @@ -package com.central.oauth.service; - -import com.central.common.model.PageResult; -import com.central.common.model.Result; -import com.central.common.service.ISuperService; -import com.central.oauth.model.Client; - -import java.util.Map; - -/** - * @author zlt - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public interface IClientService extends ISuperService { - Result saveClient(Client clientDto) throws Exception; - - /** - * 查询应用列表 - * @param params - * @param isPage 是否分页 - */ - PageResult listClient(Map params, boolean isPage); - - void delClient(long id); - - Client loadClientByClientId(String clientId); -} +package com.central.oauth.service; + +import com.central.common.model.PageResult; +import com.central.common.model.Result; +import com.central.common.service.ISuperService; +import com.central.oauth.model.Client; + +import java.util.Map; + +/** + * @author zlt + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public interface IClientService extends ISuperService { + Result saveClient(Client clientDto) throws Exception; + + /** + * 查询应用列表 + * @param params + * @param isPage 是否分页 + */ + PageResult listClient(Map params, boolean isPage); + + void delClient(long id); + + Client loadClientByClientId(String clientId); +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java b/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java index 75ee0c6c0..e013cf7be 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java @@ -1,40 +1,38 @@ -package com.central.oauth.service; - -import com.central.common.model.Result; - -import javax.servlet.http.HttpServletRequest; - -/** - * @author zlt - * @date 2018/12/10 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public interface IValidateCodeService { - /** - * 保存图形验证码 - * @param deviceId 前端唯一标识 - * @param imageCode 验证码 - */ - void saveImageCode(String deviceId, String imageCode); - - Result sendSmsCode(String mobile); - - /** - * 获取验证码 - * @param deviceId 前端唯一标识/手机号 - */ - String getCode(String deviceId); - - /** - * 删除验证码 - * @param deviceId 前端唯一标识/手机号 - */ - void remove(String deviceId); - - /** - * 验证验证码 - */ - void validate(String deviceId, String validCode); -} +package com.central.oauth.service; + +import com.central.common.model.Result; + +/** + * @author zlt + * @date 2018/12/10 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public interface IValidateCodeService { + /** + * 保存图形验证码 + * @param deviceId 前端唯一标识 + * @param imageCode 验证码 + */ + void saveImageCode(String deviceId, String imageCode); + + Result sendSmsCode(String mobile); + + /** + * 获取验证码 + * @param deviceId 前端唯一标识/手机号 + */ + String getCode(String deviceId); + + /** + * 删除验证码 + * @param deviceId 前端唯一标识/手机号 + */ + void remove(String deviceId); + + /** + * 验证验证码 + */ + void validate(String deviceId, String validCode); +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/CustomTokenServices.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/CustomTokenServices.java deleted file mode 100644 index 6ce79c313..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/CustomTokenServices.java +++ /dev/null @@ -1,258 +0,0 @@ -package com.central.oauth.service.impl; - -import com.central.common.constant.SecurityConstants; -import com.central.oauth2.common.properties.AuthProperties; -import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.oauth2.common.*; -import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; -import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.TokenRequest; -import org.springframework.security.oauth2.provider.token.DefaultTokenServices; -import org.springframework.security.oauth2.provider.token.TokenEnhancer; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Date; -import java.util.Set; -import java.util.UUID; - -/** - * 重写 DefaultTokenServices,实现登录同应用同账号互踢 - * - * @author zlt - * @date 2021/1/28 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class CustomTokenServices extends DefaultTokenServices { - private TokenStore tokenStore; - private TokenEnhancer accessTokenEnhancer; - private AuthenticationManager authenticationManager; - private boolean supportRefreshToken = false; - private boolean reuseRefreshToken = true; - - /** - * 是否登录同应用同账号互踢 - */ - private final AuthProperties authProperties; - - public CustomTokenServices(AuthProperties auth) { - this.authProperties = auth; - } - - @Override - @Transactional - public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException { - OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication); - OAuth2RefreshToken refreshToken = null; - if (existingAccessToken != null) { - if (authProperties.getIsSingleLogin()) { - if (existingAccessToken.getRefreshToken() != null) { - tokenStore.removeRefreshToken(existingAccessToken.getRefreshToken()); - } - tokenStore.removeAccessToken(existingAccessToken); - } else if (existingAccessToken.isExpired()) { - if (existingAccessToken.getRefreshToken() != null) { - refreshToken = existingAccessToken.getRefreshToken(); - // The token store could remove the refresh token when the - // access token is removed, but we want to - // be sure... - tokenStore.removeRefreshToken(refreshToken); - } - tokenStore.removeAccessToken(existingAccessToken); - } else if (authProperties.getIsShareToken()) { - // oidc每次授权都刷新id_token - existingAccessToken = refreshIdToken(existingAccessToken, authentication); - // Re-store the access token in case the authentication has changed - tokenStore.storeAccessToken(existingAccessToken, authentication); - return existingAccessToken; - } - } - - // Only create a new refresh token if there wasn't an existing one - // associated with an expired access token. - // Clients might be holding existing refresh tokens, so we re-use it in - // the case that the old access token - // expired. - if (refreshToken == null) { - refreshToken = createRefreshToken(authentication); - } - // But the refresh token itself might need to be re-issued if it has - // expired. - else if (refreshToken instanceof ExpiringOAuth2RefreshToken) { - ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken; - if (System.currentTimeMillis() > expiring.getExpiration().getTime()) { - refreshToken = createRefreshToken(authentication); - } - } - - OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken); - tokenStore.storeAccessToken(accessToken, authentication); - // In case it was modified - refreshToken = accessToken.getRefreshToken(); - if (refreshToken != null) { - tokenStore.storeRefreshToken(refreshToken, authentication); - } - return accessToken; - - } - - /** - * oidc每次授权都刷新id_token - * @param token 已存在的token - * @param authentication 认证信息 - */ - private OAuth2AccessToken refreshIdToken(OAuth2AccessToken token, OAuth2Authentication authentication) { - Set responseTypes = authentication.getOAuth2Request().getResponseTypes(); - if (accessTokenEnhancer != null && responseTypes.contains(SecurityConstants.ID_TOKEN)) { - return accessTokenEnhancer.enhance(token, authentication); - } - return token; - } - - private OAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) { - if (!isSupportRefreshToken(authentication.getOAuth2Request())) { - return null; - } - int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request()); - String value = UUID.randomUUID().toString(); - if (validitySeconds > 0) { - return new DefaultExpiringOAuth2RefreshToken(value, new Date(System.currentTimeMillis() - + (validitySeconds * 1000L))); - } - return new DefaultOAuth2RefreshToken(value); - } - - private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) { - DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); - int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request()); - if (validitySeconds > 0) { - token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); - } - token.setRefreshToken(refreshToken); - token.setScope(authentication.getOAuth2Request().getScope()); - - return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token; - } - - @Override - @Transactional(noRollbackFor={InvalidTokenException.class, InvalidGrantException.class}) - public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest) - throws AuthenticationException { - if (!supportRefreshToken) { - throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue); - } - - OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refreshTokenValue); - if (refreshToken == null) { - throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue); - } - - OAuth2Authentication authentication = tokenStore.readAuthenticationForRefreshToken(refreshToken); - if (this.authenticationManager != null && !authentication.isClientOnly()) { - AbstractAuthenticationToken userAuthentication = (AbstractAuthenticationToken)authentication.getUserAuthentication(); - Object usesrDetails = userAuthentication.getDetails(); - // The client has already been authenticated, but the user authentication might be old now, so give it a - // chance to re-authenticate. - Authentication user = new PreAuthenticatedAuthenticationToken(userAuthentication, "", authentication.getAuthorities()); - user = authenticationManager.authenticate(user); - //保存账号类型 - ((PreAuthenticatedAuthenticationToken)user).setDetails(usesrDetails); - Object details = authentication.getDetails(); - authentication = new OAuth2Authentication(authentication.getOAuth2Request(), user); - authentication.setDetails(details); - } - String clientId = authentication.getOAuth2Request().getClientId(); - if (clientId == null || !clientId.equals(tokenRequest.getClientId())) { - throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue); - } - - // clear out any access tokens already associated with the refresh - // token. - tokenStore.removeAccessTokenUsingRefreshToken(refreshToken); - - if (isExpired(refreshToken)) { - tokenStore.removeRefreshToken(refreshToken); - throw new InvalidTokenException("Invalid refresh token (expired): " + refreshToken); - } - - authentication = createRefreshedAuthentication(authentication, tokenRequest); - if (!reuseRefreshToken) { - tokenStore.removeRefreshToken(refreshToken); - refreshToken = createRefreshToken(authentication); - } - - OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken); - tokenStore.storeAccessToken(accessToken, authentication); - if (!reuseRefreshToken) { - tokenStore.storeRefreshToken(accessToken.getRefreshToken(), authentication); - } - return accessToken; - } - - private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, TokenRequest request) { - OAuth2Authentication narrowed; - Set scope = request.getScope(); - OAuth2Request clientAuth = authentication.getOAuth2Request().refresh(request); - if (scope != null && !scope.isEmpty()) { - Set originalScope = clientAuth.getScope(); - if (originalScope == null || !originalScope.containsAll(scope)) { - throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope - + ".", originalScope); - } - else { - clientAuth = clientAuth.narrowScope(scope); - } - } - narrowed = new OAuth2Authentication(clientAuth, authentication.getUserAuthentication()); - return narrowed; - } - - @Override - public void setTokenStore(TokenStore tokenStore) { - this.tokenStore = tokenStore; - super.setTokenStore(tokenStore); - } - - @Override - public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) { - this.accessTokenEnhancer = accessTokenEnhancer; - super.setTokenEnhancer(accessTokenEnhancer); - } - - @Override - public void setAuthenticationManager(AuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - super.setAuthenticationManager(authenticationManager); - } - - /** - * Whether to support the refresh token. - * - * @param supportRefreshToken Whether to support the refresh token. - */ - @Override - public void setSupportRefreshToken(boolean supportRefreshToken) { - this.supportRefreshToken = supportRefreshToken; - super.setSupportRefreshToken(supportRefreshToken); - } - - /** - * Whether to reuse refresh tokens (until expired). - * - * @param reuseRefreshToken Whether to reuse refresh tokens (until expired). - */ - @Override - public void setReuseRefreshToken(boolean reuseRefreshToken) { - this.reuseRefreshToken = reuseRefreshToken; - super.setReuseRefreshToken(reuseRefreshToken); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisAuthorizationCodeServices.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisAuthorizationCodeServices.java deleted file mode 100644 index 59a2409f7..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisAuthorizationCodeServices.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.central.oauth.service.impl; - -import com.central.common.redis.template.RedisRepository; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.serializer.RedisSerializer; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices; -import org.springframework.stereotype.Service; - -import java.util.concurrent.TimeUnit; - -/** - * JdbcAuthorizationCodeServices替换 - * - * @author zlt - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Service -public class RedisAuthorizationCodeServices extends RandomValueAuthorizationCodeServices { - private final RedisRepository redisRepository; - private final RedisSerializer valueSerializer; - - public RedisAuthorizationCodeServices(RedisRepository redisRepository) { - this.redisRepository = redisRepository; - this.valueSerializer = RedisSerializer.java(); - } - - /** - * 替换JdbcAuthorizationCodeServices的存储策略 - * 将存储code到redis,并设置过期时间,10分钟 - */ - @Override - protected void store(String code, OAuth2Authentication authentication) { - redisRepository.setExpire(redisKey(code), authentication, 10, TimeUnit.MINUTES, valueSerializer); - } - - @Override - protected OAuth2Authentication remove(final String code) { - String codeKey = redisKey(code); - OAuth2Authentication token = (OAuth2Authentication) redisRepository.get(codeKey, valueSerializer); - redisRepository.del(codeKey); - return token; - } - - /** - * redis中 code key的前缀 - * - * @param code - * @return - */ - private String redisKey(String code) { - return "oauth:code:" + code; - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisClientDetailsService.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisClientDetailsService.java deleted file mode 100644 index 456b91bd7..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisClientDetailsService.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.central.oauth.service.impl; - -import com.central.common.constant.SecurityConstants; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.security.oauth2.common.exceptions.InvalidClientException; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.NoSuchClientException; -import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; - -import javax.sql.DataSource; -import java.util.List; - -/** - * @author zlt - * @version 创建时间:2017年11月12日 上午22:57:51 - * 类说明 - * 将oauth_client_details表数据缓存到redis,这里做个缓存优化 - * layui模块中有对oauth_client_details的crud, 注意同步redis的数据 - * 注意对oauth_client_details清楚redis db部分数据的清空 - */ -@Slf4j -@Service -public class RedisClientDetailsService extends JdbcClientDetailsService { - private RedisTemplate redisTemplate; - - public RedisClientDetailsService(DataSource dataSource, RedisTemplate redisTemplate) { - super(dataSource); - this.redisTemplate = redisTemplate; - } - - @Override - public ClientDetails loadClientByClientId(String clientId) { - // 先从redis获取 - ClientDetails clientDetails = (ClientDetails) redisTemplate.opsForValue().get(clientRedisKey(clientId)); - if (clientDetails == null) { - clientDetails = cacheAndGetClient(clientId); - } - return clientDetails; - } - - /** - * 缓存client并返回client - * @param clientId - * @return - */ - private ClientDetails cacheAndGetClient(String clientId) { - // 从数据库读取 - ClientDetails clientDetails = null; - try { - clientDetails = super.loadClientByClientId(clientId); - if (clientDetails != null) { - // 写入redis缓存 - redisTemplate.opsForValue().set(clientRedisKey(clientId), clientDetails); - log.info("缓存clientId:{},{}", clientId, clientDetails); - } - } catch (NoSuchClientException e) { - log.error("clientId:{},{}", clientId, clientId); - } catch (InvalidClientException e) { - log.error("cacheAndGetClient-invalidClient:{}", clientId, e); - } - return clientDetails; - } - - @Override - public void updateClientDetails(ClientDetails clientDetails) { - super.updateClientDetails(clientDetails); - cacheAndGetClient(clientDetails.getClientId()); - } - - @Override - public void updateClientSecret(String clientId, String secret) { - super.updateClientSecret(clientId, secret); - cacheAndGetClient(clientId); - } - - @Override - public void removeClientDetails(String clientId) { - super.removeClientDetails(clientId); - removeRedisCache(clientId); - } - - /** - * 删除redis缓存 - * - * @param clientId - */ - private void removeRedisCache(String clientId) { - redisTemplate.delete(clientRedisKey(clientId)); - } - - /** - * 将oauth_client_details全表刷入redis - */ - public void loadAllClientToCache() { - List list = super.listClientDetails(); - if (CollectionUtils.isEmpty(list)) { - log.error("oauth_client_details表数据为空,请检查"); - return; - } - - list.forEach(client -> redisTemplate.opsForValue().set(clientRedisKey(client.getClientId()), client)); - } - - private String clientRedisKey(String clientId) { - return SecurityConstants.CACHE_CLIENT_KEY + ":" + clientId; - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java deleted file mode 100644 index 45fe56a5a..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.central.oauth.service.impl; - -import cn.hutool.core.util.PageUtil; -import cn.hutool.core.util.StrUtil; -import com.central.common.constant.SecurityConstants; -import com.central.common.model.PageResult; -import com.central.common.redis.template.RedisRepository; -import com.central.oauth.model.TokenVo; -import com.central.oauth.service.ITokensService; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.serializer.RedisSerializer; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * token管理服务(redis token) - * - * @author zlt - * @date 2019/7/12 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -@Service -public class RedisTokensServiceImpl implements ITokensService { - @Autowired - private RedisRepository redisRepository; - - @Override - public PageResult listTokens(Map params, String clientId) { - Integer page = MapUtils.getInteger(params, "page"); - Integer limit = MapUtils.getInteger(params, "limit"); - int[] startEnds = PageUtil.transToStartEnd(page-1, limit); - //根据请求参数生成redis的key - String redisKey = getRedisKey(params, clientId); - long size = redisRepository.length(redisKey); - List result = new ArrayList<>(limit); - RedisSerializer valueSerializer = RedisSerializer.java(); - //查询token集合 - List tokenObjs = redisRepository.getList(redisKey, startEnds[0], startEnds[1]-1, valueSerializer); - if (tokenObjs != null) { - for (Object obj : tokenObjs) { - DefaultOAuth2AccessToken accessToken = (DefaultOAuth2AccessToken)obj; - //构造token对象 - TokenVo tokenVo = new TokenVo(); - tokenVo.setTokenValue(accessToken.getValue()); - tokenVo.setExpiration(accessToken.getExpiration()); - - //获取用户信息 - Object authObj = redisRepository.get(SecurityConstants.REDIS_TOKEN_AUTH + accessToken.getValue(), valueSerializer); - OAuth2Authentication authentication = (OAuth2Authentication)authObj; - if (authentication != null) { - OAuth2Request request = authentication.getOAuth2Request(); - tokenVo.setUsername(authentication.getName()); - tokenVo.setClientId(request.getClientId()); - tokenVo.setGrantType(request.getGrantType()); - } - - Map additionalInformation = accessToken.getAdditionalInformation(); - String accountType = (String)additionalInformation.get(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME); - tokenVo.setAccountType(accountType); - - result.add(tokenVo); - } - } - return PageResult.builder().data(result).code(0).count(size).build(); - } - - /** - * 根据请求参数生成redis的key - */ - private String getRedisKey(Map params, String clientId) { - String result; - String username = MapUtils.getString(params, "username"); - if (StrUtil.isNotEmpty(username)) { - result = SecurityConstants.REDIS_UNAME_TO_ACCESS + clientId + ":" + username; - } else { - result = SecurityConstants.REDIS_CLIENT_ID_TO_ACCESS + clientId; - } - return result; - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UnifiedLogoutService.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/UnifiedLogoutService.java deleted file mode 100644 index 8fe2bf360..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UnifiedLogoutService.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.central.oauth.service.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; -import com.central.oauth.utils.UsernameHolder; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Lazy; -import org.springframework.core.task.TaskExecutor; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.token.DefaultTokenServices; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - -import javax.annotation.Resource; -import java.util.*; - -/** - * 统一登出服务 - * - * @author zlt - * @version 1.0 - * @date 2021/10/21 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -@Service -public class UnifiedLogoutService { - private final static String LOGOUT_NOTIFY_URL_KEY = "LOGOUT_NOTIFY_URL_LIST"; - - @Resource - private RestTemplate restTemplate; - - @Resource - private TaskExecutor taskExecutor; - - @Resource - private RedisClientDetailsService redisClientDetailsService; - - @Resource - private TokenStore tokenStore; - - @Lazy - @Resource - private DefaultTokenServices tokenServices; - - public void allLogout() { - Set urls = this.getLogoutNotifyUrl(); - for (String url : urls) { - taskExecutor.execute(() -> { - try { - restTemplate.getForObject(url, Void.class); - } catch (Exception e) { - log.warn(e.getMessage()); - } - }); - } - } - - /** - * 获取登出需要通知的地址集合 - */ - private Set getLogoutNotifyUrl() { - String username = UsernameHolder.getContext(); - Set logoutNotifyUrls = new HashSet<>(); - try { - List clientDetails = redisClientDetailsService.listClientDetails(); - Map informationMap; - for (ClientDetails client : clientDetails) { - informationMap = client.getAdditionalInformation(); - String urls = (String)informationMap.get(LOGOUT_NOTIFY_URL_KEY); - if (StrUtil.isNotEmpty(urls)) { - Collection tokens = tokenStore.findTokensByClientIdAndUserName(client.getClientId(), username); - if (CollUtil.isNotEmpty(tokens)) { - //注销所有该用户名下的token - tokens.forEach(t -> tokenServices.revokeToken(t.getValue())); - String tokenStr = getTokenValueStr(tokens); - logoutNotifyUrls.addAll(generateNotifyUrls(urls.split(","), tokenStr)); - } - } - } - } finally { - UsernameHolder.clearContext(); - } - return logoutNotifyUrls; - } - - private String getTokenValueStr(Collection tokens) { - if (CollUtil.isNotEmpty(tokens)) { - return StrUtil.join( ",", tokens); - } - return null; - } - - private Set generateNotifyUrls(String[] urls, String tokenStr) { - Set urlSet = new HashSet(urls.length); - for (String url : urls) { - StringBuilder urlBuilder = new StringBuilder(url); - if (url.contains("?")) { - urlBuilder.append("&"); - } else { - urlBuilder.append("?"); - } - urlBuilder.append("tokens=").append(tokenStr); - urlSet.add(urlBuilder.toString()); - } - return urlSet; - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceFactory.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceFactory.java deleted file mode 100644 index c8d61c3f2..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.central.oauth.service.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; -import com.central.common.constant.SecurityConstants; -import com.central.oauth.service.ZltUserDetailsService; -import com.central.oauth2.common.util.AuthUtils; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.authentication.InternalAuthenticationServiceException; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; - -/** - * 用户service工厂 - * - * @author zlt - * @version 1.0 - * @date 2021/7/24 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -@Service -public class UserDetailServiceFactory { - private static final String ERROR_MSG = "找不到账号类型为 {} 的实现类"; - - @Resource - private List userDetailsServices; - - public ZltUserDetailsService getService(Authentication authentication) { - String accountType = AuthUtils.getAccountType(authentication); - return this.getService(accountType); - } - - public ZltUserDetailsService getService(String accountType) { - if (StrUtil.isEmpty(accountType)) { - accountType = SecurityConstants.DEF_ACCOUNT_TYPE; - } - log.info("UserDetailServiceFactory.getService:{}", accountType); - if (CollUtil.isNotEmpty(userDetailsServices)) { - for (ZltUserDetailsService userService : userDetailsServices) { - if (userService.supports(accountType)) { - return userService; - } - } - } - throw new InternalAuthenticationServiceException(StrUtil.format(ERROR_MSG, accountType)); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailsByNameServiceFactoryWrapper.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailsByNameServiceFactoryWrapper.java deleted file mode 100644 index 39f02f2b0..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailsByNameServiceFactoryWrapper.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.central.oauth.service.impl; - -import com.central.oauth.service.ZltUserDetailsService; -import lombok.Setter; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.*; -import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; -import org.springframework.util.Assert; - -/** - * 重写 UserDetailsByNameServiceWrapper 支持多帐户类型 - * - * @author zlt - * @version 1.0 - * @date 2021/7/24 - * @see UserDetailsByNameServiceWrapper - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class UserDetailsByNameServiceFactoryWrapper implements - AuthenticationUserDetailsService, InitializingBean { - @Setter - private UserDetailServiceFactory userDetailServiceFactory; - - public UserDetailsByNameServiceFactoryWrapper() { - - } - - public UserDetailsByNameServiceFactoryWrapper(final UserDetailServiceFactory userDetailServiceFactory) { - Assert.notNull(userDetailServiceFactory, "userDetailServiceFactory cannot be null."); - this.userDetailServiceFactory = userDetailServiceFactory; - } - - /** - * Check whether all required properties have been set. - * - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() { - Assert.notNull(this.userDetailServiceFactory, "UserDetailServiceFactory must be set"); - } - - /** - * Get the UserDetails object from the wrapped UserDetailsService implementation - */ - @Override - public UserDetails loadUserDetails(T authentication) throws UsernameNotFoundException { - ZltUserDetailsService userDetailsService; - if (authentication instanceof PreAuthenticatedAuthenticationToken) { - userDetailsService = this.userDetailServiceFactory.getService((Authentication)authentication.getPrincipal()); - } else { - userDetailsService = this.userDetailServiceFactory.getService(authentication); - } - return userDetailsService.loadUserByUsername(authentication.getName()); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/tenant/OauthAuthorizeAspect.java b/zlt-uaa/src/main/java/com/central/oauth/tenant/OauthAuthorizeAspect.java deleted file mode 100644 index 8dec50424..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/tenant/OauthAuthorizeAspect.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.central.oauth.tenant; - -import com.central.common.context.TenantContextHolder; -import com.central.common.model.LoginAppUser; -import com.central.oauth.service.impl.UserDetailServiceFactory; -import com.central.oauth2.common.token.TenantUsernamePasswordAuthenticationToken; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.stereotype.Component; - -import java.security.Principal; -import java.util.Map; - -/** - * /oauth/authorize拦截器 - * 解决不同租户单点登录时角色没变化 - * - * @author zlt - * @date 2020/6/10 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -@Component -@Aspect -public class OauthAuthorizeAspect { - private final UserDetailServiceFactory userDetailsServiceFactory; - - public OauthAuthorizeAspect(UserDetailServiceFactory userDetailsServiceFactory) { - this.userDetailsServiceFactory = userDetailsServiceFactory; - } - - @Around("execution(* org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(..))") - public Object doAroundMethod(ProceedingJoinPoint joinPoint) throws Throwable { - Object[] args = joinPoint.getArgs(); - Map parameters = (Map) args[1]; - Principal principal = (Principal) args[3]; - if (principal instanceof TenantUsernamePasswordAuthenticationToken) { - TenantUsernamePasswordAuthenticationToken tenantToken = (TenantUsernamePasswordAuthenticationToken)principal; - String clientId = tenantToken.getClientId(); - String requestClientId = parameters.get(OAuth2Utils.CLIENT_ID); - //判断是否不同租户单点登录 - if (!requestClientId.equals(clientId)) { - Object details = tenantToken.getDetails(); - try { - TenantContextHolder.setTenant(requestClientId); - //重新查询对应该租户的角色等信息 - LoginAppUser user = (LoginAppUser)userDetailsServiceFactory.getService(tenantToken) - .loadUserByUsername(tenantToken.getName()); - tenantToken = new TenantUsernamePasswordAuthenticationToken(user, tenantToken.getCredentials(), user.getAuthorities(), requestClientId); - tenantToken.setDetails(details); - args[3] = tenantToken; - } finally { - TenantContextHolder.clear(); - } - } - } - return joinPoint.proceed(args); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/tenant/TenantAuthenticationProvider.java b/zlt-uaa/src/main/java/com/central/oauth/tenant/TenantAuthenticationProvider.java deleted file mode 100644 index c76d0ddcf..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/tenant/TenantAuthenticationProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.central.oauth.tenant; - -import com.central.oauth.password.PasswordAuthenticationProvider; -import com.central.oauth2.common.token.TenantUsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; - -/** - * 增加租户id,解决不同租户单点登录时角色没变化 - * - * @author zlt - * @date 2020/6/10 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class TenantAuthenticationProvider extends PasswordAuthenticationProvider { - @Override - protected Authentication createSuccessAuthentication(Object principal, - Authentication authentication, UserDetails user) { - TenantUsernamePasswordAuthenticationToken authenticationToken = (TenantUsernamePasswordAuthenticationToken) authentication; - TenantUsernamePasswordAuthenticationToken result = new TenantUsernamePasswordAuthenticationToken( - principal, authentication.getCredentials(), user.getAuthorities(), authenticationToken.getClientId()); - result.setDetails(authenticationToken.getDetails()); - return result; - } - - @Override - public boolean supports(Class authentication) { - return TenantUsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/tenant/TenantAuthenticationSecurityConfig.java b/zlt-uaa/src/main/java/com/central/oauth/tenant/TenantAuthenticationSecurityConfig.java deleted file mode 100644 index 1d00c9a90..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/tenant/TenantAuthenticationSecurityConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.central.oauth.tenant; - -import com.central.oauth.service.impl.UserDetailServiceFactory; -import org.springframework.security.config.annotation.SecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.DefaultSecurityFilterChain; -import org.springframework.stereotype.Component; - -/** - * @author zlt - * @date 2020/6/10 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Component -public class TenantAuthenticationSecurityConfig extends SecurityConfigurerAdapter { - private final UserDetailServiceFactory userDetailsServiceFactory; - - private final PasswordEncoder passwordEncoder; - - public TenantAuthenticationSecurityConfig(UserDetailServiceFactory userDetailsServiceFactory, PasswordEncoder passwordEncoder) { - this.userDetailsServiceFactory = userDetailsServiceFactory; - this.passwordEncoder = passwordEncoder; - } - - @Override - public void configure(HttpSecurity http) { - TenantAuthenticationProvider provider = new TenantAuthenticationProvider(); - provider.setUserDetailsServiceFactory(userDetailsServiceFactory); - provider.setPasswordEncoder(passwordEncoder); - http.authenticationProvider(provider); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/tenant/TenantUsernamePasswordAuthenticationFilter.java b/zlt-uaa/src/main/java/com/central/oauth/tenant/TenantUsernamePasswordAuthenticationFilter.java deleted file mode 100644 index 2b6779d99..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/tenant/TenantUsernamePasswordAuthenticationFilter.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.central.oauth.tenant; - -import com.central.common.context.TenantContextHolder; -import com.central.oauth2.common.token.TenantUsernamePasswordAuthenticationToken; -import lombok.Setter; -import org.springframework.security.authentication.AuthenticationServiceException; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * 替换 UsernamePasswordAuthenticationFilter 增加租户id - * - * @author zlt - * @date 2020/6/10 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Setter -public class TenantUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { - private boolean postOnly = true; - - public TenantUsernamePasswordAuthenticationFilter () { - super(); - } - - @Override - public Authentication attemptAuthentication(HttpServletRequest request, - HttpServletResponse response) throws AuthenticationException { - if (postOnly && !request.getMethod().equals("POST")) { - throw new AuthenticationServiceException( - "Authentication method not supported: " + request.getMethod()); - } - - String username = obtainUsername(request); - String password = obtainPassword(request); - String clientId = TenantContextHolder.getTenant(); - - if (username == null) { - username = ""; - } - - if (password == null) { - password = ""; - } - - username = username.trim(); - - TenantUsernamePasswordAuthenticationToken authRequest = new TenantUsernamePasswordAuthenticationToken(username, password, clientId); - - setDetails(request, authRequest); - - return getAuthenticationManager().authenticate(authRequest); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/utils/OidcIdTokenBuilder.java b/zlt-uaa/src/main/java/com/central/oauth/utils/OidcIdTokenBuilder.java deleted file mode 100644 index f38694bb9..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/utils/OidcIdTokenBuilder.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.central.oauth.utils; - -import com.central.common.utils.JsonUtil; -import com.central.oauth2.common.util.JwtUtils; -import lombok.Getter; -import org.springframework.cloud.bootstrap.encrypt.KeyProperties; -import org.springframework.util.Assert; - -import java.util.*; - -import static com.central.oauth2.common.constants.IdTokenClaimNames.*; - -/** - * Oidc协议的IdToken - * - * @author zlt - * @version 1.0 - * @date 2021/4/21 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Getter -public class OidcIdTokenBuilder { - private final Map claims; - private final KeyProperties keyProperties; - - private OidcIdTokenBuilder(KeyProperties keyProperties) { - this.claims = new LinkedHashMap<>(); - this.keyProperties = keyProperties; - } - - public static OidcIdTokenBuilder builder(KeyProperties keyProperties) { - Assert.notNull(keyProperties, "keyProperties required"); - return new OidcIdTokenBuilder(keyProperties); - } - - /** - * Use this claim in the resulting {@link OidcIdTokenBuilder} - * - * @param name The claim name - * @param value The claim value - */ - public OidcIdTokenBuilder claim(String name, Object value) { - this.claims.put(name, value); - return this; - } - - /** - * Use this audience in the resulting {@link OidcIdTokenBuilder} - * - * @param audience The audience to use - */ - public OidcIdTokenBuilder audience(String audience) { - return claim(AUD, audience); - } - - /** - * Use this expiration in the resulting {@link OidcIdTokenBuilder} - * - * @param expiresAt The expiration to use - */ - public OidcIdTokenBuilder expiresAt(long expiresAt) { - return this.claim(EXP, expiresAt); - } - - /** - * Use this issued-at timestamp in the resulting {@link OidcIdTokenBuilder} - * - * @param issuedAt The issued-at timestamp to use - */ - public OidcIdTokenBuilder issuedAt(long issuedAt) { - return this.claim(IAT, issuedAt); - } - - /** - * Use this issuer in the resulting {@link OidcIdTokenBuilder} - * - * @param issuer The issuer to use - */ - public OidcIdTokenBuilder issuer(String issuer) { - return this.claim(ISS, issuer); - } - - /** - * Use this nonce in the resulting {@link OidcIdTokenBuilder} - * - * @param nonce The nonce to use - */ - public OidcIdTokenBuilder nonce(String nonce) { - return this.claim(NONCE, nonce); - } - - /** - * Use this subject in the resulting {@link OidcIdTokenBuilder} - * - * @param subject The subject to use - */ - public OidcIdTokenBuilder subject(String subject) { - return this.claim(SUB, subject); - } - - /** - * 赋值用户姓名 - */ - public OidcIdTokenBuilder name(String name) { - return this.claim(NAME, name); - } - - /** - * 赋值用户登录名 - */ - public OidcIdTokenBuilder loginName(String loginName) { - return this.claim(L_NAME, loginName); - } - - /** - * 赋值用户头像 - */ - public OidcIdTokenBuilder picture(String picture) { - return this.claim(PIC, picture); - } - - /** - * Build the {@link OidcIdTokenBuilder} - * - * @return The constructed {@link OidcIdTokenBuilder} - */ - public String build() { - return JwtUtils.encodeStr(JsonUtil.toJSONString(claims), keyProperties); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/utils/UsernameHolder.java b/zlt-uaa/src/main/java/com/central/oauth/utils/UsernameHolder.java deleted file mode 100644 index 1543818c1..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/utils/UsernameHolder.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.central.oauth.utils; - -/** - * @author zlt - * @version 1.0 - * @date 2021/10/22 - *

- * Blog: https://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class UsernameHolder { - private static final ThreadLocal contextHolder = new ThreadLocal(); - - public static String getContext() { - return contextHolder.get(); - } - - public static void setContext(String username) { - contextHolder.set(username); - } - - public static void clearContext() { - contextHolder.remove(); - } -} diff --git a/zlt-uaa/src/main/resources/application.yml b/zlt-uaa/src/main/resources/application.yml index 7b83922f3..c4910e53b 100644 --- a/zlt-uaa/src/main/resources/application.yml +++ b/zlt-uaa/src/main/resources/application.yml @@ -43,4 +43,21 @@ zlt: enabled: false includeSqls: # 应用列表 - - com.central.oauth.mapper.ClientMapper.findList \ No newline at end of file + - com.central.oauth.mapper.ClientMapper.findList + +springdoc: + swagger-ui: + path: /doc.html + api-docs: + path: /v3/api-docs + group-configs: + - group: 'uaa' + paths-to-match: '/**' + packages-to-scan: com.central.oauth.controller + default-flat-param-object: true + +knife4j: + enable: true + setting: + language: zh_cn + swagger-model-name: 认证中心接口文档 \ No newline at end of file diff --git a/zlt-uaa/src/test/java/com/central/oauth2/common/util/JwtUtilsTest.java b/zlt-uaa/src/test/java/com/central/oauth2/common/util/JwtUtilsTest.java index 881e05fb5..d6dcfb2f3 100644 --- a/zlt-uaa/src/test/java/com/central/oauth2/common/util/JwtUtilsTest.java +++ b/zlt-uaa/src/test/java/com/central/oauth2/common/util/JwtUtilsTest.java @@ -1,9 +1,9 @@ package com.central.oauth2.common.util; -import com.fasterxml.jackson.databind.JsonNode; +/*import com.fasterxml.jackson.databind.JsonNode; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit4.SpringRunner;*/ /** * 测试工具类 @@ -11,6 +11,7 @@ * @author zlt * @date 2019/7/16 */ +/* @RunWith(SpringRunner.class) public class JwtUtilsTest { @Test @@ -24,3 +25,4 @@ public void test() { System.out.println(isValid); } } +*/ diff --git a/zlt-web/react-web/pom.xml b/zlt-web/react-web/pom.xml index e99c2268c..7ddd2aab2 100644 --- a/zlt-web/react-web/pom.xml +++ b/zlt-web/react-web/pom.xml @@ -16,12 +16,12 @@ v16.13.2 v1.22.19 - + - - com.github.whvcse - easy-captcha - ${easyCaptcha.version} - cn.hutool @@ -275,21 +260,6 @@ commons-configuration2 ${commons-configuration2.version} - - com.codingapi.txlcn - txlcn-tm - ${txlcn.version} - - - com.codingapi.txlcn - txlcn-tc - ${txlcn.version} - - - com.codingapi.txlcn - txlcn-txmsg-netty - ${txlcn.version} - io.shardingsphere sharding-jdbc-spring-boot-starter @@ -330,11 +300,6 @@ commons-io ${commons-io.version} - - javax.servlet - javax.servlet-api - ${servlet-api.version} - org.springframework.data spring-data-elasticsearch @@ -405,6 +370,11 @@ jackson-databind ${jackson-databind.version} + + org.springframework.security + spring-security-oauth2-authorization-server + ${spring.authorization.version} + org.springframework.cloud spring-cloud-starter-oauth2 @@ -415,11 +385,6 @@ aws-java-sdk-s3 ${aws-java-sdk-s3.version} - - org.springframework.cloud - spring-cloud-starter-netflix-zuul - ${zuul.version} - commons-configuration commons-configuration @@ -467,13 +432,13 @@ httpclient5 ${httpclient.version} - + diff --git a/zlt-business/code-generator/pom.xml b/zlt-business/code-generator/pom.xml index d7f26bc20..9710d51fd 100644 --- a/zlt-business/code-generator/pom.xml +++ b/zlt-business/code-generator/pom.xml @@ -26,8 +26,8 @@ zlt-db-spring-boot-starter - com.zlt - zlt-swagger2-spring-boot-starter + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter com.alibaba.cloud diff --git a/zlt-business/code-generator/src/main/java/com/central/generator/controller/SysGeneratorController.java b/zlt-business/code-generator/src/main/java/com/central/generator/controller/SysGeneratorController.java index f4c1641e0..a3217ded3 100644 --- a/zlt-business/code-generator/src/main/java/com/central/generator/controller/SysGeneratorController.java +++ b/zlt-business/code-generator/src/main/java/com/central/generator/controller/SysGeneratorController.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.util.Map; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; import com.central.common.model.PageResult; @@ -11,13 +12,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; -import io.swagger.annotations.Api; - /** * @Author: zlt */ @RestController -@Api(tags = "代码生成器") +@Tag(name = "代码生成器") @RequestMapping("/generator") public class SysGeneratorController { @Autowired diff --git a/zlt-business/code-generator/src/main/resources/application.yml b/zlt-business/code-generator/src/main/resources/application.yml index 167e7a65f..db1a0bc2f 100644 --- a/zlt-business/code-generator/src/main/resources/application.yml +++ b/zlt-business/code-generator/src/main/resources/application.yml @@ -8,4 +8,23 @@ spring: mybatis-plus: mapper-locations: classpath:/mapper/*Mapper.xml #实体扫描,多个package用逗号或者分号分隔 - typeAliasesPackage: com.central.generator.model \ No newline at end of file + typeAliasesPackage: com.central.generator.model + +springdoc: + swagger-ui: + path: /swagger-ui.html + tags-sorter: alpha + operations-sorter: alpha + api-docs: + path: /v3/api-docs + group-configs: + - group: 'code' + paths-to-match: '/**' + packages-to-scan: com.central.generator.controller + default-flat-param-object: true + +knife4j: + enable: true + setting: + language: zh_cn + swagger-model-name: 代码生成器接口文档 \ No newline at end of file diff --git a/zlt-business/code-generator/src/main/resources/template/Controller.java.vm b/zlt-business/code-generator/src/main/resources/template/Controller.java.vm index dad9d717c..76554431c 100644 --- a/zlt-business/code-generator/src/main/resources/template/Controller.java.vm +++ b/zlt-business/code-generator/src/main/resources/template/Controller.java.vm @@ -2,12 +2,13 @@ package ${package}.${moduleName}.controller; import java.util.Map; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; import lombok.extern.slf4j.Slf4j; import ${package}.${moduleName}.model.${className}; @@ -24,18 +25,18 @@ import com.central.common.model.Result; @Slf4j @RestController @RequestMapping("/${pathName}") -@Api(tags = "${comments}") +@Tag(name = "${comments}") +@RequiredArgsConstructor public class ${className}Controller { - @Autowired - private I${className}Service ${classname}Service; + private final I${className}Service ${classname}Service; /** * 列表 */ - @ApiOperation(value = "查询列表") - @ApiImplicitParams({ - @ApiImplicitParam(name = "page", value = "分页起始位置", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "limit", value = "分页结束位置", required = true, dataType = "Integer") + @Operation(summary = "查询列表") + @Parameters({ + @Parameter(name = "page",description = "分页起始位置",required = true,in=ParameterIn.QUERY), + @Parameter(name = "limit",description = "分页结束位置",required = true,in=ParameterIn.QUERY) }) @GetMapping public PageResult list(@RequestParam Map params) { @@ -45,7 +46,7 @@ public class ${className}Controller { /** * 查询 */ - @ApiOperation(value = "查询") + @Operation(summary = "查询") @GetMapping("/{${pk.attrname}}") public Result findUserById(@PathVariable Long ${pk.attrname}) { ${className} model = ${classname}Service.getById(${pk.attrname}); @@ -55,7 +56,7 @@ public class ${className}Controller { /** * 新增or更新 */ - @ApiOperation(value = "保存") + @Operation(summary = "保存") @PostMapping public Result save(@RequestBody ${className} ${classname}) { ${classname}Service.saveOrUpdate(${classname}); @@ -65,7 +66,8 @@ public class ${className}Controller { /** * 删除 */ - @ApiOperation(value = "删除") + @Operation(summary = "删除") + @Parameter(name = "id", description = "id", in = ParameterIn.PATH, required = true) @DeleteMapping("/{id}") public Result delete(@PathVariable Long ${pk.attrname}) { ${classname}Service.removeById(${pk.attrname}); diff --git a/zlt-business/file-center/pom.xml b/zlt-business/file-center/pom.xml index 1aa61ef87..24b9cc549 100644 --- a/zlt-business/file-center/pom.xml +++ b/zlt-business/file-center/pom.xml @@ -55,8 +55,8 @@ - com.zlt - zlt-swagger2-spring-boot-starter + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter diff --git a/zlt-business/file-center/src/main/resources/application.yml b/zlt-business/file-center/src/main/resources/application.yml index 839effbe1..a0ee2d8d2 100644 --- a/zlt-business/file-center/src/main/resources/application.yml +++ b/zlt-business/file-center/src/main/resources/application.yml @@ -13,6 +13,25 @@ mybatis-plus: db-config: id-type: INPUT +springdoc: + swagger-ui: + path: /swagger-ui.html + tags-sorter: alpha + operations-sorter: alpha + api-docs: + path: /v3/api-docs + group-configs: + - group: 'file' + paths-to-match: '/**' + packages-to-scan: com.central.file.controller + default-flat-param-object: true + +knife4j: + enable: true + setting: + language: zh_cn + swagger-model-name: 文件中心接口文档 + zlt: file-server: type: s3 @@ -23,12 +42,6 @@ zlt: accessKeySecret: ${zlt.s3.accessKeySecret} endpoint: ${zlt.s3.endpoint} bucketName: ${zlt.s3.bucketName} - swagger: - enabled: true - title: 文件中心 - description: 文件中心接口文档 - version: 1.0 - base-package: com.central.file.controller #多租户配置 tenant: enable: true diff --git a/zlt-business/search-center/search-server/pom.xml b/zlt-business/search-center/search-server/pom.xml index caac10f44..169d653ff 100644 --- a/zlt-business/search-center/search-server/pom.xml +++ b/zlt-business/search-center/search-server/pom.xml @@ -51,10 +51,9 @@ - com.zlt - zlt-swagger2-spring-boot-starter + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter - org.springframework.boot spring-boot-starter-actuator diff --git a/zlt-business/search-center/search-server/src/main/java/com/central/admin/controller/IndexController.java b/zlt-business/search-center/search-server/src/main/java/com/central/admin/controller/IndexController.java index 6104be2d4..b2eb23bec 100644 --- a/zlt-business/search-center/search-server/src/main/java/com/central/admin/controller/IndexController.java +++ b/zlt-business/search-center/search-server/src/main/java/com/central/admin/controller/IndexController.java @@ -5,7 +5,7 @@ import com.central.admin.service.IIndexService; import com.central.common.model.PageResult; import com.central.common.model.Result; -import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -20,7 +20,7 @@ */ @Slf4j @RestController -@Api(tags = "索引管理api") +@Tag(name = "索引管理api") @RequestMapping("/admin") public class IndexController { @Autowired diff --git a/zlt-business/search-center/search-server/src/main/java/com/central/search/controller/AggregationController.java b/zlt-business/search-center/search-server/src/main/java/com/central/search/controller/AggregationController.java index 01f3bc19a..0e73421c9 100644 --- a/zlt-business/search-center/search-server/src/main/java/com/central/search/controller/AggregationController.java +++ b/zlt-business/search-center/search-server/src/main/java/com/central/search/controller/AggregationController.java @@ -1,7 +1,7 @@ package com.central.search.controller; import com.central.search.service.IAggregationService; -import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; @@ -16,7 +16,7 @@ */ @Slf4j @RestController -@Api(tags = "搜索模块api") +@Tag(name = "搜索模块api") @RequestMapping("/agg") public class AggregationController { private final IAggregationService aggregationService; diff --git a/zlt-business/search-center/search-server/src/main/java/com/central/search/controller/SearchController.java b/zlt-business/search-center/search-server/src/main/java/com/central/search/controller/SearchController.java index 6a7f30a58..3eaf17140 100644 --- a/zlt-business/search-center/search-server/src/main/java/com/central/search/controller/SearchController.java +++ b/zlt-business/search-center/search-server/src/main/java/com/central/search/controller/SearchController.java @@ -5,9 +5,9 @@ import com.central.search.model.SearchDto; import com.central.search.service.ISearchService; import com.fasterxml.jackson.databind.JsonNode; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.*; -import io.swagger.annotations.Api; import lombok.extern.slf4j.Slf4j; import java.io.IOException; @@ -19,7 +19,7 @@ */ @Slf4j @RestController -@Api(tags = "搜索模块api") +@Tag(name = "搜索模块api") @RequestMapping("/search") public class SearchController { private final ISearchService searchService; diff --git a/zlt-business/search-center/search-server/src/main/resources/application.yml b/zlt-business/search-center/search-server/src/main/resources/application.yml index e7502fd30..8a1c3e802 100644 --- a/zlt-business/search-center/search-server/src/main/resources/application.yml +++ b/zlt-business/search-center/search-server/src/main/resources/application.yml @@ -4,12 +4,25 @@ spring: username: ${zlt.elasticsearch.username} password: ${zlt.elasticsearch.password} +springdoc: + swagger-ui: + path: /swagger-ui.html + tags-sorter: alpha + operations-sorter: alpha + api-docs: + path: /v3/api-docs + group-configs: + - group: 'search' + paths-to-match: '/**' + packages-to-scan: com.central.search.controller + default-flat-param-object: true + +knife4j: + enable: true + setting: + language: zh_cn + swagger-model-name: 搜索中心接口文档 + zlt: indices: - show: sys-log-*,mysql-slowlog-*,sys_user,point-log-*,audit-log-* - swagger: - enabled: true - title: 搜索中心 - description: 搜索中心接口文档 - version: 1.0 - base-package: com.central.search.controller \ No newline at end of file + show: sys-log-*,mysql-slowlog-*,sys_user,point-log-*,audit-log-* \ No newline at end of file diff --git a/zlt-business/user-center/pom.xml b/zlt-business/user-center/pom.xml index 28f97a693..c87dd05eb 100644 --- a/zlt-business/user-center/pom.xml +++ b/zlt-business/user-center/pom.xml @@ -40,8 +40,8 @@ - com.zlt - zlt-swagger2-spring-boot-starter + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter com.zlt diff --git a/zlt-business/user-center/src/main/java/com/central/user/controller/SysMenuController.java b/zlt-business/user-center/src/main/java/com/central/user/controller/SysMenuController.java index eaf16e991..dfe8727c3 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/controller/SysMenuController.java +++ b/zlt-business/user-center/src/main/java/com/central/user/controller/SysMenuController.java @@ -10,6 +10,8 @@ import com.central.common.constant.CommonConstant; import com.central.common.context.LoginUserContextHolder; import com.central.common.model.*; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -18,14 +20,11 @@ import com.central.user.service.ISysMenuService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; - /** * @author 作者 owen E-mail: 624191343@qq.com */ @RestController -@Api(tags = "菜单模块api") +@Tag(name = "菜单模块api") @Slf4j @RequestMapping("/menus") public class SysMenuController { @@ -61,7 +60,7 @@ public static List treeBuilder(List sysMenus) { * * @param id */ - @ApiOperation(value = "删除菜单") + @Operation(summary = "删除菜单") @DeleteMapping("/{id}") public Result delete(@PathVariable Long id) { try { @@ -73,7 +72,7 @@ public Result delete(@PathVariable Long id) { } } - @ApiOperation(value = "根据roleId获取对应的菜单") + @Operation(summary = "根据roleId获取对应的菜单") @GetMapping("/{roleId}/menus") public List> findMenusByRoleId(@PathVariable Long roleId) { Set roleIds = new HashSet<>(); @@ -101,7 +100,7 @@ public List> findMenusByRoleId(@PathVariable Long roleId) { return authTrees; } - @ApiOperation(value = "根据roleCodes获取对应的权限") + @Operation(summary = "根据roleCodes获取对应的权限") @SuppressWarnings("unchecked") @Cacheable(value = "menu", key ="#roleCodes") @GetMapping("/{roleCodes}") @@ -117,21 +116,21 @@ public List findMenuByRoles(@PathVariable String roleCodes) { /** * 给角色分配菜单 */ - @ApiOperation(value = "角色分配菜单") + @Operation(summary = "角色分配菜单") @PostMapping("/granted") public Result setMenuToRole(@RequestBody SysMenu sysMenu) { menuService.setMenuToRole(sysMenu.getRoleId(), sysMenu.getMenuIds()); return Result.succeed("操作成功"); } - @ApiOperation(value = "查询所有菜单") + @Operation(summary = "查询所有菜单") @GetMapping("/findAlls") public PageResult findAlls() { List list = menuService.findAll(); return PageResult.builder().data(list).code(0).count((long) list.size()).build(); } - @ApiOperation(value = "获取菜单以及顶级菜单") + @Operation(summary = "获取菜单以及顶级菜单") @GetMapping("/findOnes") public PageResult findOnes() { List list = menuService.findOnes(); @@ -144,7 +143,7 @@ public PageResult findOnes() { * @param menu * @return */ - @ApiOperation(value = "新增菜单") + @Operation(summary = "新增菜单") @PostMapping("saveOrUpdate") public Result saveOrUpdate(@RequestBody SysMenu menu) { try { @@ -165,7 +164,7 @@ public Result saveOrUpdate(@RequestBody SysMenu menu) { * @return */ @GetMapping("/current") - @ApiOperation(value = "查询当前用户菜单") + @Operation(summary = "查询当前用户菜单") public List findMyMenu(@LoginUser SysUser user) { List roles = user.getRoles(); if (CollectionUtil.isEmpty(roles)) { diff --git a/zlt-business/user-center/src/main/java/com/central/user/controller/SysRoleController.java b/zlt-business/user-center/src/main/java/com/central/user/controller/SysRoleController.java index 80de7d235..d13512148 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/controller/SysRoleController.java +++ b/zlt-business/user-center/src/main/java/com/central/user/controller/SysRoleController.java @@ -3,6 +3,8 @@ import java.util.List; import java.util.Map; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.DeleteMapping; @@ -18,16 +20,13 @@ import com.central.common.model.SysRole; import com.central.user.service.ISysRoleService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; - /** * @author 作者 owen E-mail: 624191343@qq.com * 角色管理 */ @Slf4j @RestController -@Api(tags = "角色模块api") +@Tag(name = "角色模块api") public class SysRoleController { @Autowired private ISysRoleService sysRoleService; @@ -37,7 +36,7 @@ public class SysRoleController { * @param params * @return */ - @ApiOperation(value = "后台管理查询角色") + @Operation(summary = "后台管理查询角色") @GetMapping("/roles") public PageResult findRoles(@RequestParam Map params) { return sysRoleService.findRoles(params); @@ -47,7 +46,7 @@ public PageResult findRoles(@RequestParam Map params) { * 用户管理查询所有角色 * @return */ - @ApiOperation(value = "后台管理查询角色") + @Operation(summary = "后台管理查询角色") @GetMapping("/allRoles") public Result> findAll() { List result = sysRoleService.findAll(); @@ -71,7 +70,7 @@ public Result saveOrUpdate(@RequestBody SysRole sysRole) throws Exception { * * @param id */ - @ApiOperation(value = "后台管理删除角色") + @Operation(summary = "后台管理删除角色") @DeleteMapping("/roles/{id}") public Result deleteRole(@PathVariable Long id) { try { diff --git a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java index 12eeace98..fc53459f2 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java +++ b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java @@ -18,6 +18,11 @@ import com.central.search.model.SearchDto; import com.central.user.model.SysUserExcel; import com.fasterxml.jackson.databind.JsonNode; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; import org.apache.commons.collections4.MapUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; @@ -27,10 +32,6 @@ import com.central.user.service.ISysUserService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.multipart.MultipartFile; @@ -42,7 +43,7 @@ */ @Slf4j @RestController -@Api(tags = "用户模块api") +@Tag(name = "用户模块api") public class SysUserController { private static final String ADMIN_CHANGE_MSG = "超级管理员不给予修改"; @@ -62,7 +63,7 @@ public class SysUserController { * * @return */ - @ApiOperation(value = "根据access_token当前登录用户") + @Operation(summary = "根据access_token当前登录用户") @GetMapping("/users/current") public Result getLoginAppUser(@LoginUser(isFull = true) SysUser user) { return Result.succeed(appUserService.getLoginAppUser(user)); @@ -72,7 +73,7 @@ public Result getLoginAppUser(@LoginUser(isFull = true) SysUser us * 查询用户实体对象SysUser */ @GetMapping(value = "/users/name/{username}") - @ApiOperation(value = "根据用户名查询用户实体") + @Operation(summary = "根据用户名查询用户实体") @Cacheable(value = "user", key = "#username") public SysUser selectByUsername(@PathVariable String username) { return appUserService.selectByUsername(username); @@ -82,7 +83,7 @@ public SysUser selectByUsername(@PathVariable String username) { * 查询用户登录对象LoginAppUser */ @GetMapping(value = "/users-anon/login", params = "username") - @ApiOperation(value = "根据用户名查询用户") + @Operation(summary = "根据用户名查询用户") public LoginAppUser findByUsername(String username) { return appUserService.findByUsername(username); } @@ -93,7 +94,7 @@ public LoginAppUser findByUsername(String username) { * @param mobile 手机号 */ @GetMapping(value = "/users-anon/mobile", params = "mobile") - @ApiOperation(value = "根据手机号查询用户") + @Operation(summary = "根据手机号查询用户") public SysUser findByMobile(String mobile) { return appUserService.findByMobile(mobile); } @@ -104,7 +105,7 @@ public SysUser findByMobile(String mobile) { * @param openId openId */ @GetMapping(value = "/users-anon/openId", params = "openId") - @ApiOperation(value = "根据OpenId查询用户") + @Operation(summary = "根据OpenId查询用户") public SysUser findByOpenId(String openId) { return appUserService.findByOpenId(openId); } @@ -154,10 +155,10 @@ public List findRolesByUserId(@PathVariable Long id) { * @param params * @return */ - @ApiOperation(value = "用户查询列表") - @ApiImplicitParams({ - @ApiImplicitParam(name = "page", value = "分页起始位置", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "limit", value = "分页结束位置", required = true, dataType = "Integer") + @Operation(summary = "用户查询列表") + @Parameters({ + @Parameter(name = "page",description = "分页起始位置",required = true,in=ParameterIn.QUERY), + @Parameter(name = "limit",description = "分页结束位置",required = true,in= ParameterIn.QUERY) }) @GetMapping("/users") public PageResult findUsers(@RequestParam Map params) { @@ -170,11 +171,11 @@ public PageResult findUsers(@RequestParam Map params) { * @param params * @return */ - @ApiOperation(value = "修改用户状态") + @Operation(summary = "修改用户状态") @GetMapping("/users/updateEnabled") - @ApiImplicitParams({ - @ApiImplicitParam(name = "id", value = "用户id", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "enabled", value = "是否启用", required = true, dataType = "Boolean") + @Parameters({ + @Parameter(name = "id",description = "用户id",required = true,in=ParameterIn.QUERY), + @Parameter(name = "enabled",description = "是否启用",required = true,in= ParameterIn.QUERY) }) public Result updateEnabled(@RequestParam Map params) { Long id = MapUtils.getLong(params, "id"); @@ -273,11 +274,11 @@ public Result importExcl(@RequestParam("file") MultipartFile excl) throws Except return Result.succeed("导入数据成功,一共【"+rowNum+"】行"); } - @ApiOperation(value = "用户全文搜索列表") - @ApiImplicitParams({ - @ApiImplicitParam(name = "page", value = "分页起始位置", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "limit", value = "分页结束位置", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "queryStr", value = "搜索关键字", dataType = "String") + @Operation(summary = "用户全文搜索列表") + @Parameters({ + @Parameter(name = "page",description = "分页起始位置",required = true,in=ParameterIn.QUERY), + @Parameter(name = "limit",description = "分页结束位置",required = true,in= ParameterIn.QUERY), + @Parameter(name = "queryStr",description = "搜索关键字",in= ParameterIn.QUERY) }) @GetMapping("/users/search") public PageResult search(SearchDto searchDto) { @@ -292,7 +293,7 @@ public PageResult search(SearchDto searchDto) { * @return */ @GetMapping(value = "/users/roleUser/{username}") - @ApiOperation(value = "查询用户-带角色信息") + @Operation(summary = "查询用户-带角色信息") @Cacheable(value = "userRoles", key = "#username") public SysUser selectRoleUser(@PathVariable("username") String username){ SysUser sysUser = selectByUsername(username); diff --git a/zlt-business/user-center/src/main/resources/application.yml b/zlt-business/user-center/src/main/resources/application.yml index b5a9296a8..123f260de 100644 --- a/zlt-business/user-center/src/main/resources/application.yml +++ b/zlt-business/user-center/src/main/resources/application.yml @@ -13,13 +13,26 @@ mybatis-plus: db-config: id-type: auto +springdoc: + swagger-ui: + path: /swagger-ui.html + tags-sorter: alpha + operations-sorter: alpha + api-docs: + path: /v3/api-docs + group-configs: + - group: 'user' + paths-to-match: '/**' + packages-to-scan: com.central.user.controller + default-flat-param-object: true + +knife4j: + enable: true + setting: + language: zh_cn + swagger-model-name: 用户中心接口文档 + zlt: - swagger: - enabled: true - title: 用户中心 - description: 用户中心接口文档 - version: 1.0 - base-package: com.central.user.controller cache-manager: configs: - key: menu diff --git a/zlt-commons/pom.xml b/zlt-commons/pom.xml index 2df132834..fbea07e1e 100644 --- a/zlt-commons/pom.xml +++ b/zlt-commons/pom.xml @@ -14,7 +14,6 @@ zlt-redis-spring-boot-starter zlt-common-spring-boot-starter zlt-db-spring-boot-starter - zlt-swagger2-spring-boot-starter zlt-log-spring-boot-starter zlt-loadbalancer-spring-boot-starter zlt-auth-client-spring-boot-starter diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml b/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml index a303d2e9f..f2fedfc59 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml @@ -13,8 +13,8 @@ 认证客户端通用组件 - org.springframework.cloud - spring-cloud-starter-oauth2 + org.springframework.security + spring-security-oauth2-authorization-server com.zlt @@ -42,9 +42,5 @@ tomcat-embed-websocket true - - javax.servlet - javax.servlet-api - diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java deleted file mode 100644 index f84bbe858..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.central.oauth2.common.config; - -import com.central.oauth2.common.properties.SecurityProperties; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Import; -import org.springframework.http.HttpMethod; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; -import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; -import org.springframework.security.oauth2.provider.authentication.TokenExtractor; -import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; -import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.web.AuthenticationEntryPoint; - -import javax.annotation.Resource; - -/** - * @author zlt - */ -@Import(DefaultSecurityHandlerConfig.class) -public class DefaultResourceServerConf extends ResourceServerConfigurerAdapter { - @Autowired - private TokenStore tokenStore; - - @Resource - private AuthenticationEntryPoint authenticationEntryPoint; - - @Resource - private OAuth2WebSecurityExpressionHandler expressionHandler; - - @Resource - private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; - - @Autowired - private SecurityProperties securityProperties; - - @Resource - private TokenExtractor tokenExtractor; - - @Override - public void configure(ResourceServerSecurityConfigurer resources) { - resources.tokenStore(tokenStore) - .stateless(true) - .authenticationEntryPoint(authenticationEntryPoint) - .expressionHandler(expressionHandler) - .accessDeniedHandler(oAuth2AccessDeniedHandler) - .tokenExtractor(tokenExtractor); - } - - @Override - public void configure(HttpSecurity http) throws Exception { - AuthorizeHttpRequestsConfigurer.AuthorizedUrl authorizedUrl = setHttp(http) - .authorizeHttpRequests() - .requestMatchers(securityProperties.getIgnore().getUrls()).permitAll() - .requestMatchers(HttpMethod.OPTIONS).permitAll() - .anyRequest(); - setAuthenticate(authorizedUrl); - - http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) - .and() - .httpBasic().disable() - .headers() - .frameOptions().disable() - .and() - .csrf().disable(); - } - - /** - * url权限控制,默认是认证就通过,可以重写实现个性化 - * @param authorizedUrl - */ - public HttpSecurity setAuthenticate(AuthorizeHttpRequestsConfigurer.AuthorizedUrl authorizedUrl) { - return authorizedUrl.authenticated().and(); - } - - /** - * 留给子类重写扩展功能 - * @param http - */ - public HttpSecurity setHttp(HttpSecurity http) { - return http; - } -} \ No newline at end of file diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultSecurityHandlerConfig.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultSecurityHandlerConfig.java deleted file mode 100644 index d12d9cadb..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultSecurityHandlerConfig.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.central.oauth2.common.config; - -import com.central.common.utils.ResponseUtil; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; -import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; -import org.springframework.security.web.AuthenticationEntryPoint; - -import javax.annotation.Resource; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * @author zlt - */ -public class DefaultSecurityHandlerConfig { - @Resource - private ObjectMapper objectMapper; - - /** - * 未登录,返回401 - * - * @return - */ - @Bean - public AuthenticationEntryPoint authenticationEntryPoint() { - return (request, response, authException) -> ResponseUtil.responseFailed(objectMapper, response, authException.getMessage()); - } - - @Bean - public OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler(ApplicationContext applicationContext) { - OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler(); - expressionHandler.setApplicationContext(applicationContext); - return expressionHandler; - } - - /** - * 处理spring security oauth 处理失败返回消息格式 - */ - @Bean - public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler() { - return new OAuth2AccessDeniedHandler() { - - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException) throws IOException { - ResponseUtil.responseFailed(objectMapper, response, authException.getMessage()); - } - }; - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/constants/IdTokenClaimNames.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/constants/IdTokenClaimNames.java deleted file mode 100644 index 5c1840de4..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/constants/IdTokenClaimNames.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.central.oauth2.common.constants; - -/** - * id_token属性名常量 - * - * @author zlt - * @version 1.0 - * @date 2021/4/23 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class IdTokenClaimNames { - /** - * {@code iss} - the Issuer identifier - */ - public final static String ISS = "iss"; - - /** - * {@code sub} - the Subject identifier - */ - public final static String SUB = "sub"; - - /** - * {@code aud} - the Audience(s) that the ID Token is intended for - */ - public final static String AUD = "aud"; - - /** - * {@code exp} - the Expiration time on or after which the ID Token MUST NOT be accepted - */ - public final static String EXP = "exp"; - - /** - * {@code iat} - the time at which the ID Token was issued - */ - public final static String IAT = "iat"; - - /** - * {@code auth_time} - the time when the End-User authentication occurred - */ - public final static String AUTH_TIME = "auth_time"; - - /** - * {@code nonce} - a {@code String} value used to associate a Client session with an ID Token, - * and to mitigate replay attacks. - */ - public final static String NONCE = "nonce"; - - /** - * {@code acr} - the Authentication Context Class Reference - */ - public final static String ACR = "acr"; - - /** - * {@code amr} - the Authentication Methods References - */ - public final static String AMR = "amr"; - - /** - * {@code azp} - the Authorized party to which the ID Token was issued - */ - public final static String AZP = "azp"; - - /** - * {@code at_hash} - the Access Token hash value - */ - public final static String AT_HASH = "at_hash"; - - /** - * {@code c_hash} - the Authorization Code hash value - */ - public final static String C_HASH = "c_hash"; - - /** - * {@code name} - 用户姓名 - */ - public final static String NAME = "name"; - - /** - * {@code login_name} - 登录名 - */ - public final static String L_NAME = "login_name"; - - /** - * {@code picture} - 头像照片 - */ - public final static String PIC = "picture"; -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/converter/CustomUserAuthenticationConverter.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/converter/CustomUserAuthenticationConverter.java deleted file mode 100644 index fbc865810..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/converter/CustomUserAuthenticationConverter.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.central.oauth2.common.converter; - -import com.central.common.model.LoginAppUser; -import com.central.common.model.SysUser; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter; -import org.springframework.util.StringUtils; - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * 优化自org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter - * jwt返回的principal改为返回SysUser,增加扩展字段 - * - * @author zlt - * @date 2019/8/5 - */ -public class CustomUserAuthenticationConverter implements UserAuthenticationConverter { - private Collection defaultAuthorities; - - private UserDetailsService userDetailsService; - - /** - * Optional {@link UserDetailsService} to use when extracting an {@link Authentication} from the incoming map. - * - * @param userDetailsService the userDetailsService to set - */ - public void setUserDetailsService(UserDetailsService userDetailsService) { - this.userDetailsService = userDetailsService; - } - - /** - * Default value for authorities if an Authentication is being created and the input has no data for authorities. - * Note that unless this property is set, the default Authentication created by {@link #extractAuthentication(Map)} - * will be unauthenticated. - * - * @param defaultAuthorities the defaultAuthorities to set. Default null. - */ - public void setDefaultAuthorities(String[] defaultAuthorities) { - this.defaultAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils - .arrayToCommaDelimitedString(defaultAuthorities)); - } - - @Override - public Map convertUserAuthentication(Authentication authentication) { - Map response = new LinkedHashMap(); - response.put(USERNAME, authentication.getName()); - if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) { - response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities())); - } - return response; - } - - @Override - public Authentication extractAuthentication(Map map) { - if (map.containsKey(USERNAME)) { - Object principal = map.get(USERNAME); - Collection authorities = getAuthorities(map); - if (userDetailsService != null) { - UserDetails user = userDetailsService.loadUserByUsername((String) map.get(USERNAME)); - authorities = user.getAuthorities(); - principal = user; - } else { - Integer id = (Integer)map.get("id"); - LoginAppUser user = new LoginAppUser(); - user.setUsername((String)principal); - user.setId(Long.valueOf(id)); - principal = user; - } - return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities); - } - return null; - } - - private Collection getAuthorities(Map map) { - if (!map.containsKey(AUTHORITIES)) { - return defaultAuthorities; - } - Object authorities = map.get(AUTHORITIES); - if (authorities instanceof String) { - return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities); - } - if (authorities instanceof Collection) { - return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils - .collectionToCommaDelimitedString((Collection) authorities)); - } - throw new IllegalArgumentException("Authorities must be either a String or a Collection"); - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/exception/CustomOAuth2AuthenticationException.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/exception/CustomOAuth2AuthenticationException.java new file mode 100644 index 000000000..585ecc539 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/exception/CustomOAuth2AuthenticationException.java @@ -0,0 +1,17 @@ +package com.central.oauth2.common.exception; + +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2Error; + +/** + * @author: zlt + * @date: 2023/11/16 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class CustomOAuth2AuthenticationException extends OAuth2AuthenticationException { + public CustomOAuth2AuthenticationException(String msg) { + super(new OAuth2Error(msg), msg); + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/CustomBearerTokenExtractor.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/CustomBearerTokenExtractor.java deleted file mode 100644 index 1346be294..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/CustomBearerTokenExtractor.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.central.oauth2.common.service.impl; - -import com.central.oauth2.common.properties.SecurityProperties; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor; -import org.springframework.stereotype.Component; -import org.springframework.util.AntPathMatcher; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; - -/** - * 自定义 TokenExtractor - * - * @author zlt - * @version 1.0 - * @date 2022/6/4 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@ConditionalOnClass(HttpServletRequest.class) -@Component -public class CustomBearerTokenExtractor extends BearerTokenExtractor { - @Resource - private SecurityProperties securityProperties; - - private final AntPathMatcher antPathMatcher = new AntPathMatcher(); - - /** - * 解决只要请求携带access_token,排除鉴权的url依然会被拦截 - */ - @Override - public Authentication extract(HttpServletRequest request) { - //判断当前请求为排除鉴权的url时,直接返回null - for (String url : securityProperties.getIgnore().getUrls()) { - if (antPathMatcher.match(url, request.getRequestURI())) { - return null; - } - } - return super.extract(request); - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/CustomBearerTokenResolver.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/CustomBearerTokenResolver.java new file mode 100644 index 000000000..833d1ca26 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/CustomBearerTokenResolver.java @@ -0,0 +1,112 @@ +package com.central.oauth2.common.service.impl; + +import com.central.oauth2.common.properties.PermitProperties; +import com.central.oauth2.common.properties.SecurityProperties; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.server.resource.BearerTokenError; +import org.springframework.security.oauth2.server.resource.BearerTokenErrors; +import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver; +import org.springframework.stereotype.Component; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; +import org.springframework.util.StringUtils; + +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author: zlt + * @date: 2023/11/8 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@ConditionalOnClass(HttpServletRequest.class) +@Component +public class CustomBearerTokenResolver implements BearerTokenResolver { + private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?[a-zA-Z0-9-:._~+/]+=*)$", + Pattern.CASE_INSENSITIVE); + + private final boolean allowFormEncodedBodyParameter = false; + + private final boolean allowUriQueryParameter = true; + + private final String bearerTokenHeaderName = HttpHeaders.AUTHORIZATION; + + private final PathMatcher pathMatcher = new AntPathMatcher(); + + private final PermitProperties permitProperties; + + public CustomBearerTokenResolver(SecurityProperties securityProperties) { + this.permitProperties = securityProperties.getIgnore(); + } + + @Override + public String resolve(HttpServletRequest request) { + boolean match = Arrays.stream(permitProperties.getUrls()) + .anyMatch(url -> pathMatcher.match(url, request.getRequestURI())); + + if (match) { + return null; + } + + final String authorizationHeaderToken = resolveFromAuthorizationHeader(request); + final String parameterToken = isParameterTokenSupportedForRequest(request) + ? resolveFromRequestParameters(request) : null; + if (authorizationHeaderToken != null) { + if (parameterToken != null) { + final BearerTokenError error = BearerTokenErrors + .invalidRequest("Found multiple bearer tokens in the request"); + throw new OAuth2AuthenticationException(error); + } + return authorizationHeaderToken; + } + if (parameterToken != null && isParameterTokenEnabledForRequest(request)) { + return parameterToken; + } + return null; + } + + private String resolveFromAuthorizationHeader(HttpServletRequest request) { + String authorization = request.getHeader(this.bearerTokenHeaderName); + if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) { + return null; + } + Matcher matcher = authorizationPattern.matcher(authorization); + if (!matcher.matches()) { + BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed"); + throw new OAuth2AuthenticationException(error); + } + return matcher.group("token"); + } + + private static String resolveFromRequestParameters(HttpServletRequest request) { + String[] values = request.getParameterValues("access_token"); + if (values == null || values.length == 0) { + return null; + } + if (values.length == 1) { + return values[0]; + } + BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request"); + throw new OAuth2AuthenticationException(error); + } + + private boolean isParameterTokenSupportedForRequest(final HttpServletRequest request) { + return (("POST".equals(request.getMethod()) + && MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType())) + || "GET".equals(request.getMethod())); + } + + private boolean isParameterTokenEnabledForRequest(final HttpServletRequest request) { + return ((this.allowFormEncodedBodyParameter && "POST".equals(request.getMethod()) + && MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType())) + || (this.allowUriQueryParameter && "GET".equals(request.getMethod()))); + } + +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/DefaultPermissionServiceImpl.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/DefaultPermissionServiceImpl.java deleted file mode 100644 index 1724a0920..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/DefaultPermissionServiceImpl.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.central.oauth2.common.service.impl; - -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.util.StrUtil; -import com.central.common.constant.CommonConstant; -import com.central.common.context.TenantContextHolder; -import com.central.common.model.SysMenu; -import com.central.oauth2.common.properties.SecurityProperties; -import com.central.oauth2.common.util.AuthUtils; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpMethod; -import org.springframework.security.authentication.AnonymousAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.util.AntPathMatcher; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * 请求权限判断service - * - * @author zlt - * @date 2018/10/28 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -public abstract class DefaultPermissionServiceImpl { - - @Autowired - private SecurityProperties securityProperties; - - private final AntPathMatcher antPathMatcher = new AntPathMatcher(); - - /** - * 查询当前用户拥有的资源权限 - * @param roleCodes 角色code列表,多个以','隔开 - * @return - */ - public abstract List findMenuByRoleCodes(String roleCodes); - - public boolean hasPermission(Authentication authentication, String requestMethod, String requestURI) { - // 前端跨域OPTIONS请求预检放行 也可通过前端配置代理实现 - if (HttpMethod.OPTIONS.name().equalsIgnoreCase(requestMethod)) { - return true; - } - if (!(authentication instanceof AnonymousAuthenticationToken)) { - //判断是否开启url权限验证 - if (!securityProperties.getAuth().getUrlPermission().getEnable()) { - return true; - } - //超级管理员admin不需认证 - String username = AuthUtils.getUsername(authentication); - if (CommonConstant.ADMIN_USER_NAME.equals(username)) { - return true; - } - - OAuth2Authentication auth2Authentication = (OAuth2Authentication)authentication; - //判断应用黑白名单 - if (!isNeedAuth(auth2Authentication.getOAuth2Request().getClientId())) { - return true; - } - - //判断不进行url权限认证的api,所有已登录用户都能访问的url - for (String path : securityProperties.getAuth().getUrlPermission().getIgnoreUrls()) { - if (antPathMatcher.match(path, requestURI)) { - return true; - } - } - - List grantedAuthorityList = (List) authentication.getAuthorities(); - if (CollectionUtil.isEmpty(grantedAuthorityList)) { - log.warn("角色列表为空:{}", authentication.getPrincipal()); - return false; - } - - //保存租户信息 - String clientId = auth2Authentication.getOAuth2Request().getClientId(); - TenantContextHolder.setTenant(clientId); - - String roleCodes = grantedAuthorityList.stream().map(SimpleGrantedAuthority::getAuthority).collect(Collectors.joining(", ")); - List menuList = findMenuByRoleCodes(roleCodes); - for (SysMenu menu : menuList) { - if (StringUtils.isNotEmpty(menu.getUrl()) && antPathMatcher.match(menu.getUrl(), requestURI)) { - if (StrUtil.isNotEmpty(menu.getPathMethod())) { - return requestMethod.equalsIgnoreCase(menu.getPathMethod()); - } else { - return true; - } - } - } - } - - return false; - } - - /** - * 判断应用是否满足白名单和黑名单的过滤逻辑 - * @param clientId 应用id - * @return true(需要认证),false(不需要认证) - */ - private boolean isNeedAuth(String clientId) { - boolean result = true; - //白名单 - List includeClientIds = securityProperties.getAuth().getUrlPermission().getIncludeClientIds(); - //黑名单 - List exclusiveClientIds = securityProperties.getAuth().getUrlPermission().getExclusiveClientIds(); - if (includeClientIds.size() > 0) { - result = includeClientIds.contains(clientId); - } else if(exclusiveClientIds.size() > 0) { - result = !exclusiveClientIds.contains(clientId); - } - return result; - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/AuthDbTokenStore.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/AuthDbTokenStore.java deleted file mode 100644 index 1d0b1ec9d..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/AuthDbTokenStore.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.central.oauth2.common.store; - -import org.springframework.beans.factory.annotation.Autowired; -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.TokenStore; -import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; - -import javax.sql.DataSource; - -/** - * 认证服务器使用数据库存取令牌 - * - * @author zlt - * @date 2018/7/24 16:23 - */ -@Configuration -@ConditionalOnProperty(prefix = "zlt.oauth2.token.store", name = "type", havingValue = "db") -public class AuthDbTokenStore { - @Autowired - private DataSource dataSource; - - @Bean - public TokenStore tokenStore(){ - return new JdbcTokenStore(dataSource); - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/AuthJwtTokenStore.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/AuthJwtTokenStore.java deleted file mode 100644 index a61a90f7d..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/AuthJwtTokenStore.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.central.oauth2.common.store; - -import com.central.common.model.SysUser; -import com.central.oauth2.common.converter.CustomUserAuthenticationConverter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.bootstrap.encrypt.KeyProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; -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; -import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory; - -import javax.annotation.Resource; -import java.security.KeyPair; -import java.util.HashMap; -import java.util.Map; - -/** - * 认证服务器使用 JWT RSA 非对称加密令牌 - * - * @author zlt - * @date 2018/7/24 16:21 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Configuration -@ConditionalOnProperty(prefix = "zlt.oauth2.token.store", name = "type", havingValue = "authJwt") -public class AuthJwtTokenStore { - @Resource - private KeyProperties keyProperties; - - @Bean - public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) { - return new JwtTokenStore(jwtAccessTokenConverter); - } - - @Bean - @Order(2) - public JwtAccessTokenConverter jwtAccessTokenConverter() { - final JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); - KeyPair keyPair = new KeyStoreKeyFactory - (keyProperties.getKeyStore().getLocation(), keyProperties.getKeyStore().getSecret().toCharArray()) - .getKeyPair(keyProperties.getKeyStore().getAlias()); - converter.setKeyPair(keyPair); - DefaultAccessTokenConverter tokenConverter = (DefaultAccessTokenConverter)converter.getAccessTokenConverter(); - tokenConverter.setUserTokenConverter(new CustomUserAuthenticationConverter()); - return converter; - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/AuthRedisTokenStore.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/AuthRedisTokenStore.java deleted file mode 100644 index 124df21f0..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/AuthRedisTokenStore.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.central.oauth2.common.store; - -import com.central.oauth2.common.properties.SecurityProperties; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.serializer.RedisSerializer; -import org.springframework.security.oauth2.provider.token.TokenStore; - -/** - * 认证服务器使用Redis存取令牌 - * 注意: 需要配置redis参数 - * - * @author zlt - * @date 2018/7/25 9:36 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Configuration -@ConditionalOnProperty(prefix = "zlt.oauth2.token.store", name = "type", havingValue = "redis", matchIfMissing = true) -public class AuthRedisTokenStore { - @Bean - public TokenStore tokenStore(RedisConnectionFactory connectionFactory, SecurityProperties securityProperties, RedisSerializer redisValueSerializer) { - return new CustomRedisTokenStore(connectionFactory, securityProperties, redisValueSerializer); - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/CustomRedisTokenStore.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/CustomRedisTokenStore.java deleted file mode 100644 index f07ddb0d1..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/CustomRedisTokenStore.java +++ /dev/null @@ -1,543 +0,0 @@ -package com.central.oauth2.common.store; - -import com.central.common.constant.SecurityConstants; -import com.central.oauth2.common.properties.SecurityProperties; -import org.springframework.data.redis.connection.RedisConnection; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.serializer.RedisSerializer; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.OAuth2RefreshToken; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator; -import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy; -import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; -import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy; -import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -/** - * 优化自Spring Security的RedisTokenStore - * 1. 支持redis所有集群模式包括cluster模式 - * 2. 使用pipeline减少连接次数,提升性能 - * 3. 自动续签token(可配置是否开启) - * - * @author zlt - * @date 2019/7/7 - */ -public class CustomRedisTokenStore implements TokenStore { - private static final String ACCESS = "access:"; - private static final String ACCESS_BAK = "access_bak:"; - private static final String AUTH_TO_ACCESS = "auth_to_access:"; - private static final String REFRESH_AUTH = "refresh_auth:"; - private static final String ACCESS_TO_REFRESH = "access_to_refresh:"; - private static final String REFRESH = "refresh:"; - private static final String REFRESH_TO_ACCESS = "refresh_to_access:"; - - private static final boolean springDataRedis_2_0 = ClassUtils.isPresent( - "org.springframework.data.redis.connection.RedisStandaloneConfiguration", - RedisTokenStore.class.getClassLoader()); - - private final RedisConnectionFactory connectionFactory; - private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator(); - private RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy(); - - private String prefix = ""; - - private Method redisConnectionSet_2_0; - - /** - * 认证配置 - */ - private SecurityProperties securityProperties; - - /** - * 业务redis的value序列化 - */ - private RedisSerializer redisValueSerializer; - - public CustomRedisTokenStore(RedisConnectionFactory connectionFactory, SecurityProperties securityProperties, RedisSerializer redisValueSerializer) { - this.connectionFactory = connectionFactory; - this.securityProperties = securityProperties; - this.redisValueSerializer = redisValueSerializer; - if (springDataRedis_2_0) { - this.loadRedisConnectionMethods_2_0(); - } - } - - public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) { - this.authenticationKeyGenerator = authenticationKeyGenerator; - } - - public void setSerializationStrategy(RedisTokenStoreSerializationStrategy serializationStrategy) { - this.serializationStrategy = serializationStrategy; - } - - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - private void loadRedisConnectionMethods_2_0() { - this.redisConnectionSet_2_0 = ReflectionUtils.findMethod( - RedisConnection.class, "set", byte[].class, byte[].class); - } - - private RedisConnection getConnection() { - return connectionFactory.getConnection(); - } - - private byte[] serialize(Object object) { - return serializationStrategy.serialize(object); - } - - private byte[] serializeKey(String object) { - return serialize(prefix + object); - } - - private OAuth2AccessToken deserializeAccessToken(byte[] bytes) { - return serializationStrategy.deserialize(bytes, OAuth2AccessToken.class); - } - - private OAuth2Authentication deserializeAuthentication(byte[] bytes) { - return serializationStrategy.deserialize(bytes, OAuth2Authentication.class); - } - - private OAuth2RefreshToken deserializeRefreshToken(byte[] bytes) { - return serializationStrategy.deserialize(bytes, OAuth2RefreshToken.class); - } - - private ClientDetails deserializeClientDetails(byte[] bytes) { - return (ClientDetails) redisValueSerializer.deserialize(bytes); - } - - private byte[] serialize(String string) { - return serializationStrategy.serialize(string); - } - - private String deserializeString(byte[] bytes) { - return serializationStrategy.deserializeString(bytes); - } - - @Override - public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { - String key = authenticationKeyGenerator.extractKey(authentication); - byte[] serializedKey = serializeKey(AUTH_TO_ACCESS + key); - byte[] bytes; - RedisConnection conn = getConnection(); - try { - bytes = conn.get(serializedKey); - } finally { - conn.close(); - } - OAuth2AccessToken accessToken = deserializeAccessToken(bytes); - if (accessToken != null) { - OAuth2Authentication storedAuthentication = readAuthentication(accessToken.getValue()); - if ((storedAuthentication == null || !key.equals(authenticationKeyGenerator.extractKey(storedAuthentication)))) { - // Keep the stores consistent (maybe the same user is - // represented by this authentication but the details have - // changed) - storeAccessToken(accessToken, authentication); - } - - } - return accessToken; - } - - @Override - public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { - OAuth2Authentication auth2Authentication = readAuthentication(token.getValue()); - //是否开启token续签 - boolean isRenew = securityProperties.getAuth().getRenew().getEnable(); - if (isRenew && auth2Authentication != null) { - OAuth2Request clientAuth = auth2Authentication.getOAuth2Request(); - //判断当前应用是否需要自动续签 - if (checkRenewClientId(clientAuth.getClientId())) { - //获取过期时长 - int validitySeconds = getAccessTokenValiditySeconds(clientAuth.getClientId()); - if (validitySeconds > 0) { - double expiresRatio = token.getExpiresIn() / (double) validitySeconds; - //判断是否需要续签,当前剩余时间小于过期时长的50%则续签 - if (expiresRatio <= securityProperties.getAuth().getRenew().getTimeRatio()) { - //更新AccessToken过期时间 - DefaultOAuth2AccessToken oAuth2AccessToken = (DefaultOAuth2AccessToken) token; - oAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); - storeAccessToken(oAuth2AccessToken, auth2Authentication, true); - } - } - } - } - return auth2Authentication; - } - - /** - * 判断应用自动续签是否满足白名单和黑名单的过滤逻辑 - * - * @param clientId 应用id - * @return 是否满足 - */ - private boolean checkRenewClientId(String clientId) { - boolean result = true; - //白名单 - List includeClientIds = securityProperties.getAuth().getRenew().getIncludeClientIds(); - //黑名单 - List exclusiveClientIds = securityProperties.getAuth().getRenew().getExclusiveClientIds(); - if (includeClientIds.size() > 0) { - result = includeClientIds.contains(clientId); - } else if (exclusiveClientIds.size() > 0) { - result = !exclusiveClientIds.contains(clientId); - } - return result; - } - - /** - * 获取token的总有效时长 - * - * @param clientId 应用id - */ - private int getAccessTokenValiditySeconds(String clientId) { - RedisConnection conn = getConnection(); - byte[] bytes; - try { - bytes = conn.get(serializeKey(SecurityConstants.CACHE_CLIENT_KEY + ":" + clientId)); - } finally { - conn.close(); - } - if (bytes != null) { - ClientDetails clientDetails = deserializeClientDetails(bytes); - if (clientDetails.getAccessTokenValiditySeconds() != null) { - return clientDetails.getAccessTokenValiditySeconds(); - } - } - - //返回默认值 - return SecurityConstants.ACCESS_TOKEN_VALIDITY_SECONDS; - } - - @Override - public OAuth2Authentication readAuthentication(String token) { - byte[] bytes; - RedisConnection conn = getConnection(); - try { - bytes = conn.get(serializeKey(SecurityConstants.REDIS_TOKEN_AUTH + token)); - } finally { - conn.close(); - } - return deserializeAuthentication(bytes); - } - - @Override - public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { - return readAuthenticationForRefreshToken(token.getValue()); - } - - public OAuth2Authentication readAuthenticationForRefreshToken(String token) { - RedisConnection conn = getConnection(); - try { - byte[] bytes = conn.get(serializeKey(REFRESH_AUTH + token)); - return deserializeAuthentication(bytes); - } finally { - conn.close(); - } - } - - @Override - public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { - storeAccessToken(token, authentication, false); - } - - /** - * 存储token - * - * @param isRenew 是否续签 - */ - private void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication, boolean isRenew) { - byte[] serializedAccessToken = serialize(token); - byte[] serializedAuth = serialize(authentication); - byte[] accessKey = serializeKey(ACCESS + token.getValue()); - byte[] accessBakKey = serializeKey(ACCESS_BAK + token.getValue()); - byte[] authKey = serializeKey(SecurityConstants.REDIS_TOKEN_AUTH + token.getValue()); - byte[] authToAccessKey = serializeKey(AUTH_TO_ACCESS + authenticationKeyGenerator.extractKey(authentication)); - byte[] approvalKey = serializeKey(SecurityConstants.REDIS_UNAME_TO_ACCESS + getApprovalKey(authentication)); - byte[] clientId = serializeKey(SecurityConstants.REDIS_CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId()); - - RedisConnection conn = getConnection(); - try { - byte[] oldAccessToken = conn.get(accessKey); - //如果token已存在,并且不是续签的话直接返回 - if (!isRenew && oldAccessToken != null) { - return; - } - - conn.openPipeline(); - if (springDataRedis_2_0) { - try { - this.redisConnectionSet_2_0.invoke(conn, accessKey, serializedAccessToken); - this.redisConnectionSet_2_0.invoke(conn, accessBakKey, serializedAccessToken); - this.redisConnectionSet_2_0.invoke(conn, authKey, serializedAuth); - this.redisConnectionSet_2_0.invoke(conn, authToAccessKey, serializedAccessToken); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } else { - conn.set(accessKey, serializedAccessToken); - conn.set(accessBakKey, serializedAccessToken); - conn.set(authKey, serializedAuth); - conn.set(authToAccessKey, serializedAccessToken); - } - //如果是续签token,需要先删除集合里旧的值 - if (oldAccessToken != null) { - if (!authentication.isClientOnly()) { - conn.lRem(approvalKey, 1, oldAccessToken); - } - conn.lRem(clientId, 1, oldAccessToken); - } - if (!authentication.isClientOnly()) { - conn.rPush(approvalKey, serializedAccessToken); - } - conn.rPush(clientId, serializedAccessToken); - if (token.getExpiration() != null) { - int seconds = token.getExpiresIn(); - conn.expire(accessKey, seconds); - conn.expire(accessBakKey, seconds + 60); - conn.expire(authKey, seconds); - conn.expire(authToAccessKey, seconds); - conn.expire(clientId, seconds); - conn.expire(approvalKey, seconds); - } - OAuth2RefreshToken refreshToken = token.getRefreshToken(); - if (refreshToken != null && refreshToken.getValue() != null) { - byte[] refresh = serialize(token.getRefreshToken().getValue()); - byte[] auth = serialize(token.getValue()); - byte[] refreshToAccessKey = serializeKey(REFRESH_TO_ACCESS + token.getRefreshToken().getValue()); - byte[] accessToRefreshKey = serializeKey(ACCESS_TO_REFRESH + token.getValue()); - if (springDataRedis_2_0) { - try { - this.redisConnectionSet_2_0.invoke(conn, refreshToAccessKey, auth); - this.redisConnectionSet_2_0.invoke(conn, accessToRefreshKey, refresh); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } else { - conn.set(refreshToAccessKey, auth); - conn.set(accessToRefreshKey, refresh); - } - expireRefreshToken(refreshToken, conn, refreshToAccessKey, accessToRefreshKey); - } - conn.closePipeline(); - } finally { - conn.close(); - } - } - - private static String getApprovalKey(OAuth2Authentication authentication) { - String userName = authentication.getUserAuthentication() == null ? "" - : authentication.getUserAuthentication().getName(); - return getApprovalKey(authentication.getOAuth2Request().getClientId(), userName); - } - - private static String getApprovalKey(String clientId, String userName) { - return clientId + (userName == null ? "" : ":" + userName); - } - - @Override - public void removeAccessToken(OAuth2AccessToken accessToken) { - removeAccessToken(accessToken.getValue()); - } - - @Override - public OAuth2AccessToken readAccessToken(String tokenValue) { - byte[] key = serializeKey(ACCESS + tokenValue); - byte[] bytes; - RedisConnection conn = getConnection(); - try { - bytes = conn.get(key); - } finally { - conn.close(); - } - return deserializeAccessToken(bytes); - } - - public void removeAccessToken(String tokenValue) { - byte[] accessKey = serializeKey(ACCESS + tokenValue); - byte[] accessBakKey = serializeKey(ACCESS_BAK + tokenValue); - byte[] authKey = serializeKey(SecurityConstants.REDIS_TOKEN_AUTH + tokenValue); - byte[] accessToRefreshKey = serializeKey(ACCESS_TO_REFRESH + tokenValue); - RedisConnection conn = getConnection(); - try { - byte[] access = conn.get(accessKey); - byte[] auth = conn.get(authKey); - conn.openPipeline(); - conn.del(accessKey); - conn.del(accessBakKey); - conn.del(accessToRefreshKey); - // Don't remove the refresh token - it's up to the caller to do that - conn.del(authKey); - conn.closePipeline(); - - OAuth2Authentication authentication = deserializeAuthentication(auth); - if (authentication != null) { - String key = authenticationKeyGenerator.extractKey(authentication); - byte[] authToAccessKey = serializeKey(AUTH_TO_ACCESS + key); - byte[] unameKey = serializeKey(SecurityConstants.REDIS_UNAME_TO_ACCESS + getApprovalKey(authentication)); - byte[] clientId = serializeKey(SecurityConstants.REDIS_CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId()); - conn.openPipeline(); - conn.del(authToAccessKey); - conn.lRem(unameKey, 1, access); - conn.lRem(clientId, 1, access); - conn.del(serialize(ACCESS + key)); - conn.closePipeline(); - } - } finally { - conn.close(); - } - } - - @Override - public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { - byte[] refreshKey = serializeKey(REFRESH + refreshToken.getValue()); - byte[] refreshAuthKey = serializeKey(REFRESH_AUTH + refreshToken.getValue()); - byte[] serializedRefreshToken = serialize(refreshToken); - RedisConnection conn = getConnection(); - try { - conn.openPipeline(); - if (springDataRedis_2_0) { - try { - this.redisConnectionSet_2_0.invoke(conn, refreshKey, serializedRefreshToken); - this.redisConnectionSet_2_0.invoke(conn, refreshAuthKey, serialize(authentication)); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } else { - conn.set(refreshKey, serializedRefreshToken); - conn.set(refreshAuthKey, serialize(authentication)); - } - expireRefreshToken(refreshToken, conn, refreshKey, refreshAuthKey); - conn.closePipeline(); - } finally { - conn.close(); - } - } - - private void expireRefreshToken(OAuth2RefreshToken refreshToken, RedisConnection conn, byte[] refreshKey, byte[] refreshAuthKey) { - if (refreshToken instanceof ExpiringOAuth2RefreshToken) { - ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken; - Date expiration = expiringRefreshToken.getExpiration(); - if (expiration != null) { - int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L) - .intValue(); - conn.expire(refreshKey, seconds); - conn.expire(refreshAuthKey, seconds); - } - } - } - - @Override - public OAuth2RefreshToken readRefreshToken(String tokenValue) { - byte[] key = serializeKey(REFRESH + tokenValue); - byte[] bytes; - RedisConnection conn = getConnection(); - try { - bytes = conn.get(key); - } finally { - conn.close(); - } - return deserializeRefreshToken(bytes); - } - - @Override - public void removeRefreshToken(OAuth2RefreshToken refreshToken) { - removeRefreshToken(refreshToken.getValue()); - } - - public void removeRefreshToken(String tokenValue) { - byte[] refreshKey = serializeKey(REFRESH + tokenValue); - byte[] refreshAuthKey = serializeKey(REFRESH_AUTH + tokenValue); - byte[] refresh2AccessKey = serializeKey(REFRESH_TO_ACCESS + tokenValue); - byte[] access2RefreshKey = serializeKey(ACCESS_TO_REFRESH + tokenValue); - RedisConnection conn = getConnection(); - try { - conn.openPipeline(); - conn.del(refreshKey); - conn.del(refreshAuthKey); - conn.del(refresh2AccessKey); - conn.del(access2RefreshKey); - conn.closePipeline(); - } finally { - conn.close(); - } - } - - @Override - public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { - removeAccessTokenUsingRefreshToken(refreshToken.getValue()); - } - - private void removeAccessTokenUsingRefreshToken(String refreshToken) { - byte[] key = serializeKey(REFRESH_TO_ACCESS + refreshToken); - RedisConnection conn = getConnection(); - byte[] bytes = null; - try { - bytes = conn.get(key); - conn.del(key); - } finally { - conn.close(); - } - if (bytes == null) { - return; - } - String accessToken = deserializeString(bytes); - if (accessToken != null) { - removeAccessToken(accessToken); - } - } - - @Override - public Collection findTokensByClientIdAndUserName(String clientId, String userName) { - byte[] approvalKey = serializeKey(SecurityConstants.REDIS_UNAME_TO_ACCESS + getApprovalKey(clientId, userName)); - List byteList; - RedisConnection conn = getConnection(); - try { - byteList = conn.lRange(approvalKey, 0, -1); - } finally { - conn.close(); - } - return getTokenCollections(byteList); - } - - @Override - public Collection findTokensByClientId(String clientId) { - byte[] key = serializeKey(SecurityConstants.REDIS_CLIENT_ID_TO_ACCESS + clientId); - List byteList; - RedisConnection conn = getConnection(); - try { - byteList = conn.lRange(key, 0, -1); - } finally { - conn.close(); - } - return getTokenCollections(byteList); - } - - private Collection getTokenCollections(List byteList) { - if (byteList == null || byteList.size() == 0) { - return Collections.emptySet(); - } - List accessTokens = new ArrayList<>(byteList.size()); - for (byte[] bytes : byteList) { - OAuth2AccessToken accessToken = deserializeAccessToken(bytes); - accessTokens.add(accessToken); - } - return Collections.unmodifiableCollection(accessTokens); - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/ResJwtTokenStore.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/ResJwtTokenStore.java deleted file mode 100644 index c76556962..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/ResJwtTokenStore.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.central.oauth2.common.store; - -import cn.hutool.core.util.StrUtil; -import com.central.common.constant.SecurityConstants; -import com.central.oauth2.common.converter.CustomUserAuthenticationConverter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; -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; -import org.springframework.web.client.RestTemplate; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Base64; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * 资源服务器 TokenStore 配置类,使用 JWT RSA 非对称加密 - * - * @author zlt - * @date 2018/8/20 9:25 - */ -@Configuration -@ConditionalOnProperty(prefix = "zlt.oauth2.token.store", name = "type", havingValue = "resJwt") -public class ResJwtTokenStore { - @Autowired - private ResourceServerProperties resource; - - @Bean - public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) { - return new JwtTokenStore(jwtAccessTokenConverter); - } - - @Bean - public JwtAccessTokenConverter jwtAccessTokenConverter() { - JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); - converter.setVerifierKey(getPubKey()); - DefaultAccessTokenConverter tokenConverter = (DefaultAccessTokenConverter)converter.getAccessTokenConverter(); - tokenConverter.setUserTokenConverter(new CustomUserAuthenticationConverter()); - return converter; - } - - /** - * 获取非对称加密公钥 Key - * @return 公钥 Key - */ - private String getPubKey() { - Resource res = new ClassPathResource(SecurityConstants.RSA_PUBLIC_KEY); - try (BufferedReader br = new BufferedReader(new InputStreamReader(res.getInputStream()))) { - return br.lines().collect(Collectors.joining("\n")); - } catch (IOException ioe) { - return getKeyFromAuthorizationServer(); - } - } - - /** - * 通过访问授权服务器获取非对称加密公钥 Key - * @return 公钥 Key - */ - private String getKeyFromAuthorizationServer() { - if (StrUtil.isNotEmpty(this.resource.getJwt().getKeyUri())) { - final HttpHeaders headers = new HttpHeaders(); - final String username = this.resource.getClientId(); - final String password = this.resource.getClientSecret(); - if (username != null && password != null) { - final byte[] token = Base64.getEncoder().encode((username + ":" + password).getBytes()); - headers.add("Authorization", "Basic " + new String(token)); - } - final HttpEntity request = new HttpEntity<>(headers); - final String url = this.resource.getJwt().getKeyUri(); - return (String) new RestTemplate() - .exchange(url, HttpMethod.GET, request, Map.class).getBody() - .get("value"); - } - return null; - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/BaseAuthenticationToken.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/BaseAuthenticationToken.java new file mode 100644 index 000000000..5c5b96fcc --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/BaseAuthenticationToken.java @@ -0,0 +1,66 @@ +package com.central.oauth2.common.token; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.lang.Nullable; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.server.authorization.util.SpringAuthorizationServerVersion; + +import java.io.Serial; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +/** + * @author: zlt + * @date: 2023/11/15 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Getter +@Setter +public class BaseAuthenticationToken extends AbstractAuthenticationToken { + @Serial + private static final long serialVersionUID = SpringAuthorizationServerVersion.SERIAL_VERSION_UID; + private final AuthorizationGrantType grantType; + private Authentication clientPrincipal; + private Map additionalParameters; + private Set scopes; + + public BaseAuthenticationToken(AuthorizationGrantType authorizationGrantType) { + super(null); + this.grantType = authorizationGrantType; + } + + public BaseAuthenticationToken(AuthorizationGrantType authorizationGrantType, Set scopes + , Authentication clientPrincipal, @Nullable Map additionalParameters) { + super(null); + this.grantType = authorizationGrantType; + this.scopes = Collections.unmodifiableSet(scopes != null ? scopes : Collections.emptySet()); + this.clientPrincipal = clientPrincipal; + this.additionalParameters = additionalParameters; + } + + public BaseAuthenticationToken(Collection authorities) { + super(authorities); + this.grantType = null; + this.clientPrincipal = null; + this.additionalParameters = null; + this.scopes = null; + } + + @Override + public Object getPrincipal() { + return this.clientPrincipal; + } + + @Override + public Object getCredentials() { + return ""; + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/CustomAccessToken.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/CustomAccessToken.java new file mode 100644 index 000000000..0c53f6b24 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/CustomAccessToken.java @@ -0,0 +1,19 @@ +package com.central.oauth2.common.token; + +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; + +import java.util.Map; + +/** + * @author: zlt + * @date: 2023/11/20 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class CustomAccessToken extends OAuth2Authorization.Token { + protected CustomAccessToken(OAuth2AccessToken token, Map metadata) { + super(token, metadata); + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java index df836dd21..4ef3d8a1e 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java @@ -1,22 +1,24 @@ package com.central.oauth2.common.util; +import cn.hutool.extra.spring.SpringUtil; import com.central.common.constant.CommonConstant; import com.central.common.constant.SecurityConstants; import com.central.common.context.LoginUserContextHolder; import com.central.common.model.SysUser; -import com.central.common.utils.SpringUtil; -import com.central.oauth2.common.token.CustomWebAuthenticationDetails; +import com.central.oauth2.common.exception.CustomOAuth2AuthenticationException; +import com.central.oauth2.common.token.BaseAuthenticationToken; import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; -import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import jakarta.servlet.http.HttpServletRequest; +import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; + import java.nio.charset.StandardCharsets; import java.util.*; @@ -45,7 +47,7 @@ private AuthUtils() { public static String extractToken(HttpServletRequest request) { String token = extractHeaderToken(request); if (token == null) { - token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN); + token = request.getParameter(OAuth2ParameterNames.ACCESS_TOKEN); if (token == null) { log.debug("Token not found in request parameters. Not an OAuth2 request."); } @@ -62,8 +64,8 @@ private static String extractHeaderToken(HttpServletRequest request) { Enumeration headers = request.getHeaders(CommonConstant.TOKEN_HEADER); while (headers.hasMoreElements()) { String value = headers.nextElement(); - if ((value.startsWith(OAuth2AccessToken.BEARER_TYPE))) { - String authHeaderValue = value.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim(); + if ((value.startsWith(OAuth2AccessToken.TokenType.BEARER.getValue()))) { + String authHeaderValue = value.substring(OAuth2AccessToken.TokenType.BEARER.getValue().length()).trim(); int commaIndex = authHeaderValue.indexOf(','); if (commaIndex > 0) { authHeaderValue = authHeaderValue.substring(0, commaIndex); @@ -83,19 +85,20 @@ public static SysUser checkAccessToken(HttpServletRequest request) { } public static SysUser checkAccessToken(String accessTokenValue) { - TokenStore tokenStore = SpringUtil.getBean(TokenStore.class); - OAuth2AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue); - if (accessToken == null || accessToken.getValue() == null) { - throw new InvalidTokenException("Invalid access token: " + accessTokenValue); - } else if (accessToken.isExpired()) { - tokenStore.removeAccessToken(accessToken); - throw new InvalidTokenException("Access token expired: " + accessTokenValue); + OAuth2AuthorizationService tokenService = SpringUtil.getBean(OAuth2AuthorizationService.class); + OAuth2Authorization oAuth2Authorization = tokenService.findByToken(accessTokenValue, OAuth2TokenType.ACCESS_TOKEN); + if (oAuth2Authorization == null || oAuth2Authorization.getAccessToken() == null) { + throw new CustomOAuth2AuthenticationException("Invalid access token: " + accessTokenValue); + } else if (oAuth2Authorization.getAccessToken().isExpired()) { + tokenService.remove(oAuth2Authorization); + throw new CustomOAuth2AuthenticationException("Access token expired: " + accessTokenValue); } - OAuth2Authentication result = tokenStore.readAuthentication(accessToken); + /*OAuth2Authentication result = tokenStore.readAuthentication(accessToken); if (result == null) { - throw new InvalidTokenException("Invalid access token: " + accessTokenValue); - } - return setContext(result); + throw new OAuth2AuthenticationException("Invalid access token: " + accessTokenValue); + }*/ + // TODO 如何生成 Authentication 对象 + return setContext(null); } /** @@ -114,11 +117,20 @@ public static SysUser setContext(Authentication authentication) { public static String[] extractClient(HttpServletRequest request) { String header = request.getHeader("Authorization"); if (header == null || !header.startsWith(BASIC_)) { - throw new UnapprovedClientAuthenticationException("请求头中client信息为空"); + throw new CustomOAuth2AuthenticationException("The client information in the request header is empty"); } return extractHeaderClient(header); } + public static String extractClientId(HttpServletRequest request) { + String header = request.getHeader("Authorization"); + if (header == null || !header.startsWith(BASIC_)) { + throw new CustomOAuth2AuthenticationException("The client information in the request header is empty"); + } + String[] clientArr = extractHeaderClient(header); + return clientArr[0]; + } + /** * 从header 请求中的clientId:clientSecret * @@ -130,7 +142,7 @@ public static String[] extractHeaderClient(String header) { String clientStr = new String(decoded, StandardCharsets.UTF_8); String[] clientArr = clientStr.split(":"); if (clientArr.length != 2) { - throw new RuntimeException("Invalid basic authentication token"); + throw new CustomOAuth2AuthenticationException("Invalid basic authentication token"); } return clientArr; } @@ -170,17 +182,8 @@ public static SysUser getUser(Authentication authentication) { public static String getAccountType(Authentication authentication) { String accountType = null; if (authentication != null) { - Object details = authentication.getDetails(); - if (details != null) { - if (details instanceof CustomWebAuthenticationDetails) { - CustomWebAuthenticationDetails detailsObj = (CustomWebAuthenticationDetails) details; - accountType = detailsObj.getAccountType(); - } else { - Map detailsMap = (Map) details; - if (detailsMap != null) { - accountType = detailsMap.get(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME); - } - } + if (authentication instanceof BaseAuthenticationToken authenticationToken) { + accountType = (String)authenticationToken.getAdditionalParameters().get(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME); } } return accountType; diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/JwtUtils.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/JwtUtils.java deleted file mode 100644 index e56274050..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/JwtUtils.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.central.oauth2.common.util; - -import com.central.common.constant.SecurityConstants; -import com.central.common.utils.JsonUtil; -import com.central.common.utils.RsaUtils; -import com.fasterxml.jackson.databind.JsonNode; -import org.springframework.cloud.bootstrap.encrypt.KeyProperties; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.security.jwt.Jwt; -import org.springframework.security.jwt.JwtHelper; -import org.springframework.security.jwt.crypto.sign.RsaSigner; -import org.springframework.security.jwt.crypto.sign.RsaVerifier; -import org.springframework.security.jwt.crypto.sign.SignatureVerifier; -import org.springframework.security.jwt.crypto.sign.Signer; -import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.util.stream.Collectors; - -/** - * jwt工具类 - * - * @author zlt - * @date 2019/7/21 - */ -public class JwtUtils { - private static final String PUBKEY_START = "-----BEGIN PUBLIC KEY-----"; - private static final String PUBKEY_END = "-----END PUBLIC KEY-----"; - - /** - * 通过classpath获取公钥值 - */ - public static RSAPublicKey getPubKeyObj() { - Resource res = new ClassPathResource(SecurityConstants.RSA_PUBLIC_KEY); - try (BufferedReader br = new BufferedReader(new InputStreamReader(res.getInputStream()))) { - String pubKey = br.lines().collect(Collectors.joining("\n")); - pubKey = pubKey.substring(PUBKEY_START.length(), pubKey.indexOf(PUBKEY_END)); - return RsaUtils.getPublicKey(pubKey); - } catch (Exception ioe) { - ioe.printStackTrace(); - } - return null; - } - - /** - * {"exp":1563256084,"user_name":"admin","authorities":["ADMIN"],"jti":"4ce02f54-3d1c-4461-8af1-73f0841a35df","client_id":"webApp","scope":["app"]} - * @param jwtToken token值 - * @param rsaPublicKey 公钥 - * @return - */ - public static JsonNode decodeAndVerify(String jwtToken, RSAPublicKey rsaPublicKey) { - SignatureVerifier rsaVerifier = new RsaVerifier(rsaPublicKey); - Jwt jwt = JwtHelper.decodeAndVerify(jwtToken, rsaVerifier); - return JsonUtil.parse(jwt.getClaims()); - } - - /** - * {"exp":1563256084,"user_name":"admin","authorities":["ADMIN"],"jti":"4ce02f54-3d1c-4461-8af1-73f0841a35df","client_id":"webApp","scope":["app"]} - * @param jwtToken token值 - * @return - */ - public static JsonNode decodeAndVerify(String jwtToken) { - return decodeAndVerify(jwtToken, getPubKeyObj()); - } - - /** - * 判断jwt是否过期 - * @param claims jwt内容 - * @param currTime 当前时间 - * @return 未过期:true,已过期:false - */ - public static boolean checkExp(JsonNode claims, long currTime) { - long exp = claims.get("exp").asLong(); - if (exp < currTime) { - return false; - } - return true; - } - - /** - * 判断jwt是否过期 - * @param claims jwt内容 - * @return 未过期:true,已过期:false - */ - public static boolean checkExp(JsonNode claims) { - return checkExp(claims, System.currentTimeMillis()); - } - - public static Jwt encode(CharSequence content, KeyProperties keyProperties) { - KeyPair keyPair = new KeyStoreKeyFactory( - keyProperties.getKeyStore().getLocation(), - keyProperties.getKeyStore().getSecret().toCharArray()) - .getKeyPair(keyProperties.getKeyStore().getAlias()); - PrivateKey privateKey = keyPair.getPrivate(); - Signer rsaSigner = new RsaSigner((RSAPrivateKey) privateKey); - return JwtHelper.encode(content, rsaSigner); - } - - public static String encodeStr(CharSequence content, KeyProperties keyProperties) { - return encode(content, keyProperties).getEncoded(); - } -} diff --git a/zlt-commons/zlt-common-core/pom.xml b/zlt-commons/zlt-common-core/pom.xml index 1f7166685..746451ba1 100644 --- a/zlt-commons/zlt-common-core/pom.xml +++ b/zlt-commons/zlt-common-core/pom.xml @@ -27,11 +27,6 @@ cn.hutool hutool-all - - javax.servlet - javax.servlet-api - true - com.fasterxml.jackson.core jackson-annotations diff --git a/zlt-commons/zlt-loadbalancer-spring-boot-starter/pom.xml b/zlt-commons/zlt-loadbalancer-spring-boot-starter/pom.xml index f0390a899..ae003e72b 100644 --- a/zlt-commons/zlt-loadbalancer-spring-boot-starter/pom.xml +++ b/zlt-commons/zlt-loadbalancer-spring-boot-starter/pom.xml @@ -33,12 +33,6 @@ org.apache.httpcomponents.client5 httpclient5 - - javax.servlet - javax.servlet-api - true - - org.springframework.boot spring-boot-configuration-processor diff --git a/zlt-commons/zlt-swagger2-spring-boot-starter/pom.xml b/zlt-commons/zlt-swagger2-spring-boot-starter/pom.xml deleted file mode 100644 index 0a992c22d..000000000 --- a/zlt-commons/zlt-swagger2-spring-boot-starter/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - com.zlt - zlt-commons - 5.6.0 - - 4.0.0 - jar - zlt-swagger2-spring-boot-starter - swagger通用组件 - - - org.springframework.boot - spring-boot-starter - - - com.github.xiaoymin - knife4j-micro-spring-boot-starter - - - org.springframework.boot - spring-boot-configuration-processor - true - - - diff --git a/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerAutoConfiguration.java b/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerAutoConfiguration.java deleted file mode 100644 index e52f12cb9..000000000 --- a/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerAutoConfiguration.java +++ /dev/null @@ -1,271 +0,0 @@ -package com.central.common.swagger2; - -import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.collect.Lists; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -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.context.annotation.Import; -import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.ParameterBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.schema.ModelRef; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.ApiKey; -import springfox.documentation.service.AuthorizationScope; -import springfox.documentation.service.Contact; -import springfox.documentation.service.Parameter; -import springfox.documentation.service.SecurityReference; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spi.service.contexts.SecurityContext; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * @author zlt - * @date 2018/11/18 9:22 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Configuration -@EnableSwagger2 -@EnableKnife4j -@Import(BeanValidatorPluginsConfiguration.class) -public class SwaggerAutoConfiguration implements BeanFactoryAware { - private static final String AUTH_KEY = "Authorization"; - - private BeanFactory beanFactory; - - @Bean - @ConditionalOnMissingBean - public SwaggerProperties swaggerProperties() { - return new SwaggerProperties(); - } - - /*@Bean - @ConditionalOnMissingBean - @ConditionalOnProperty(name = "zlt.swagger.enabled", matchIfMissing = true) - public List createRestApi(SwaggerProperties swaggerProperties) { - ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory; - List docketList = new LinkedList<>(); - - // 没有分组 - if (swaggerProperties.getDocket().size() == 0) { - final Docket docket = createDocket(swaggerProperties); - configurableBeanFactory.registerSingleton("defaultDocket", docket); - docketList.add(docket); - return docketList; - } - - // 分组创建 - for (String groupName : swaggerProperties.getDocket().keySet()) { - SwaggerProperties.DocketInfo docketInfo = swaggerProperties.getDocket().get(groupName); - - ApiInfo apiInfo = new ApiInfoBuilder() - .title(docketInfo.getTitle().isEmpty() ? swaggerProperties.getTitle() : docketInfo.getTitle()) - .description(docketInfo.getDescription().isEmpty() ? swaggerProperties.getDescription() : docketInfo.getDescription()) - .version(docketInfo.getVersion().isEmpty() ? swaggerProperties.getVersion() : docketInfo.getVersion()) - .license(docketInfo.getLicense().isEmpty() ? swaggerProperties.getLicense() : docketInfo.getLicense()) - .licenseUrl(docketInfo.getLicenseUrl().isEmpty() ? swaggerProperties.getLicenseUrl() : docketInfo.getLicenseUrl()) - .contact( - new Contact( - docketInfo.getContact().getName().isEmpty() ? swaggerProperties.getContact().getName() : docketInfo.getContact().getName(), - docketInfo.getContact().getUrl().isEmpty() ? swaggerProperties.getContact().getUrl() : docketInfo.getContact().getUrl(), - docketInfo.getContact().getEmail().isEmpty() ? swaggerProperties.getContact().getEmail() : docketInfo.getContact().getEmail() - ) - ) - .termsOfServiceUrl(docketInfo.getTermsOfServiceUrl().isEmpty() ? swaggerProperties.getTermsOfServiceUrl() : docketInfo.getTermsOfServiceUrl()) - .build(); - - // base-path处理 - // 当没有配置任何path的时候,解析/** - if (docketInfo.getBasePath().isEmpty()) { - docketInfo.getBasePath().add("/**"); - } - List> basePath = new ArrayList<>(docketInfo.getBasePath().size()); - for (String path : docketInfo.getBasePath()) { - basePath.add(PathSelectors.ant(path)); - } - - // exclude-path处理 - List> excludePath = new ArrayList<>(docketInfo.getExcludePath().size()); - for (String path : docketInfo.getExcludePath()) { - excludePath.add(PathSelectors.ant(path)); - } - - Docket docket = new Docket(DocumentationType.SWAGGER_2) - .host(swaggerProperties.getHost()) - .apiInfo(apiInfo) - .globalOperationParameters(assemblyGlobalOperationParameters(swaggerProperties.getGlobalOperationParameters(), - docketInfo.getGlobalOperationParameters())) - .groupName(groupName) - .select() - .apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage())) - .paths( - Predicates.and( - Predicates.not(Predicates.or(excludePath)), - Predicates.or(basePath) - ) - ) - .build() - .securitySchemes(securitySchemes()) - .securityContexts(securityContexts()); - - configurableBeanFactory.registerSingleton(groupName, docket); - docketList.add(docket); - } - return docketList; - }*/ - - /** - * 创建 Docket对象 - * - * @param swaggerProperties swagger配置 - * @return Docket - */ - /*private Docket createDocket(final SwaggerProperties swaggerProperties) { - ApiInfo apiInfo = new ApiInfoBuilder() - .title(swaggerProperties.getTitle()) - .description(swaggerProperties.getDescription()) - .version(swaggerProperties.getVersion()) - .license(swaggerProperties.getLicense()) - .licenseUrl(swaggerProperties.getLicenseUrl()) - .contact(new Contact(swaggerProperties.getContact().getName(), - swaggerProperties.getContact().getUrl(), - swaggerProperties.getContact().getEmail())) - .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl()) - .build(); - - // base-path处理 - // 当没有配置任何path的时候,解析/** - if (swaggerProperties.getBasePath().isEmpty()) { - swaggerProperties.getBasePath().add("/**"); - } - List> basePath = new ArrayList<>(); - for (String path : swaggerProperties.getBasePath()) { - basePath.add(PathSelectors.ant(path)); - } - - // exclude-path处理 - List> excludePath = new ArrayList<>(); - for (String path : swaggerProperties.getExcludePath()) { - excludePath.add(PathSelectors.ant(path)); - } - - return new Docket(DocumentationType.SWAGGER_2) - .host(swaggerProperties.getHost()) - .apiInfo(apiInfo) - .globalOperationParameters(buildGlobalOperationParametersFromSwaggerProperties( - swaggerProperties.getGlobalOperationParameters())) - .select() - .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage())) - .paths( - Predicates.and( - Predicates.not(Predicates.or(excludePath)), - Predicates.or(basePath) - ) - ) - .build() - .securitySchemes(securitySchemes()) - .securityContexts(securityContexts()); - }*/ - - @Override - public void setBeanFactory(BeanFactory beanFactory) { - this.beanFactory = beanFactory; - } - - private List securityContexts() { - List contexts = new ArrayList<>(1); - SecurityContext securityContext = SecurityContext.builder() - .securityReferences(defaultAuth()) - //.forPaths(PathSelectors.regex("^(?!auth).*$")) - .build(); - contexts.add(securityContext); - return contexts; - } - - private List defaultAuth() { - AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); - AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; - authorizationScopes[0] = authorizationScope; - List references = new ArrayList<>(1); - references.add(new SecurityReference(AUTH_KEY, authorizationScopes)); - return references; - } - - private List securitySchemes() { - List apiKeys = new ArrayList<>(1); - ApiKey apiKey = new ApiKey(AUTH_KEY, AUTH_KEY, "header"); - apiKeys.add(apiKey); - return apiKeys; - } - - private List buildGlobalOperationParametersFromSwaggerProperties( - List globalOperationParameters) { - List parameters = Lists.newArrayList(); - - if (Objects.isNull(globalOperationParameters)) { - return parameters; - } - for (SwaggerProperties.GlobalOperationParameter globalOperationParameter : globalOperationParameters) { - parameters.add(new ParameterBuilder() - .name(globalOperationParameter.getName()) - .description(globalOperationParameter.getDescription()) - .modelRef(new ModelRef(globalOperationParameter.getModelRef())) - .parameterType(globalOperationParameter.getParameterType()) - .required(Boolean.parseBoolean(globalOperationParameter.getRequired())) - .build()); - } - return parameters; - } - - /** - * 局部参数按照name覆盖局部参数 - * - * @param globalOperationParameters - * @param docketOperationParameters - * @return - */ - private List assemblyGlobalOperationParameters( - List globalOperationParameters, - List docketOperationParameters) { - - if (Objects.isNull(docketOperationParameters) || docketOperationParameters.isEmpty()) { - return buildGlobalOperationParametersFromSwaggerProperties(globalOperationParameters); - } - - Set docketNames = docketOperationParameters.stream() - .map(SwaggerProperties.GlobalOperationParameter::getName) - .collect(Collectors.toSet()); - - List resultOperationParameters = Lists.newArrayList(); - - if (Objects.nonNull(globalOperationParameters)) { - for (SwaggerProperties.GlobalOperationParameter parameter : globalOperationParameters) { - if (!docketNames.contains(parameter.getName())) { - resultOperationParameters.add(parameter); - } - } - } - - resultOperationParameters.addAll(docketOperationParameters); - return buildGlobalOperationParametersFromSwaggerProperties(resultOperationParameters); - } -} diff --git a/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerProperties.java b/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerProperties.java deleted file mode 100644 index 9bba37dca..000000000 --- a/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/java/com/central/common/swagger2/SwaggerProperties.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.central.common.swagger2; - -import lombok.Data; -import lombok.Getter; -import lombok.Setter; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * swagger2 属性配置 - * - * @author zlt - * @date 2018/11/18 9:17 - */ -@Data -@ConfigurationProperties("zlt.swagger") -@Component -public class SwaggerProperties { - /**是否开启swagger**/ - private Boolean enabled; - /**标题**/ - private String title = ""; - /**描述**/ - private String description = ""; - /**版本**/ - private String version = ""; - /**许可证**/ - private String license = ""; - /**许可证URL**/ - private String licenseUrl = ""; - /**服务条款URL**/ - private String termsOfServiceUrl = ""; - /**联系人**/ - private Contact contact = new Contact(); - - /**swagger会解析的包路径**/ - private String basePackage = ""; - - /**swagger会解析的url规则**/ - private List basePath = new ArrayList<>(); - /**在basePath基础上需要排除的url规则**/ - private List excludePath = new ArrayList<>(); - - /**分组文档**/ - private Map docket = new LinkedHashMap<>(); - - /**host信息**/ - private String host = ""; - - /**全局参数配置**/ - private List globalOperationParameters; - - @Setter - @Getter - public static class GlobalOperationParameter{ - /**参数名**/ - private String name; - - /**描述信息**/ - private String description; - - /**指定参数类型**/ - private String modelRef; - - /**参数放在哪个地方:header,query,path,body.form**/ - private String parameterType; - - /**参数是否必须传**/ - private String required; - } - - @Data - public static class DocketInfo { - /**标题**/ - private String title = ""; - /**描述**/ - private String description = ""; - /**版本**/ - private String version = ""; - /**许可证**/ - private String license = ""; - /**许可证URL**/ - private String licenseUrl = ""; - /**服务条款URL**/ - private String termsOfServiceUrl = ""; - - private Contact contact = new Contact(); - - /**swagger会解析的包路径**/ - private String basePackage = ""; - - /**swagger会解析的url规则**/ - private List basePath = new ArrayList<>(); - /**在basePath基础上需要排除的url规则**/ - private List excludePath = new ArrayList<>(); - - private List globalOperationParameters; - } - - @Data - public static class Contact { - /**联系人**/ - private String name = ""; - /**联系人url**/ - private String url = ""; - /**联系人email**/ - private String email = ""; - } -} diff --git a/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index ae9b3414e..000000000 --- a/zlt-commons/zlt-swagger2-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.common.swagger2.SwaggerAutoConfiguration \ No newline at end of file diff --git a/zlt-demo/resources-server-demo/src/main/java/org/zlt/config/MyResourceConfig.java b/zlt-demo/resources-server-demo/src/main/java/org/zlt/config/MyResourceConfig.java index 1d1af95de..482aef1e2 100644 --- a/zlt-demo/resources-server-demo/src/main/java/org/zlt/config/MyResourceConfig.java +++ b/zlt-demo/resources-server-demo/src/main/java/org/zlt/config/MyResourceConfig.java @@ -1,8 +1,7 @@ package org.zlt.config; -import com.central.oauth2.common.config.DefaultResourceServerConf; import org.springframework.context.annotation.Configuration; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; +//import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; /** * security资源服务器配置 @@ -14,7 +13,7 @@ * Blog: http://zlt2000.gitee.io * Github: https://github.com/zlt2000 */ -@Configuration +/*@Configuration @EnableResourceServer public class MyResourceConfig extends DefaultResourceServerConf { -} +}*/ diff --git a/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SecurityConfig.java b/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SecurityConfig.java index 99d1bd45a..838e54b7f 100644 --- a/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SecurityConfig.java +++ b/zlt-demo/sso-demo/ss-sso/src/main/java/com/sso/demo/config/SecurityConfig.java @@ -31,14 +31,14 @@ public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http.authorizeHttpRequests().anyRequest().authenticated() + /*http.authorizeHttpRequests().anyRequest().authenticated() .and() .csrf().disable() .logout() .logoutSuccessHandler(ssoLogoutSuccessHandler); if (StrUtil.isNotEmpty(loginPath)) { http.formLogin().loginProcessingUrl(loginPath); - } + }*/ return http.build(); } } \ No newline at end of file diff --git a/zlt-demo/websocket-demo/src/main/java/org/zlt/config/MyResourceConfig.java b/zlt-demo/websocket-demo/src/main/java/org/zlt/config/MyResourceConfig.java index 8c00d0355..6a4ac97ac 100644 --- a/zlt-demo/websocket-demo/src/main/java/org/zlt/config/MyResourceConfig.java +++ b/zlt-demo/websocket-demo/src/main/java/org/zlt/config/MyResourceConfig.java @@ -1,8 +1,6 @@ package org.zlt.config; -import com.central.oauth2.common.config.DefaultResourceServerConf; import org.springframework.context.annotation.Configuration; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; /** * security资源服务器配置 @@ -14,7 +12,9 @@ * Blog: http://zlt2000.gitee.io * Github: https://github.com/zlt2000 */ +/* @Configuration @EnableResourceServer public class MyResourceConfig extends DefaultResourceServerConf { } +*/ diff --git a/zlt-doc/sql/oauth-center.sql b/zlt-doc/sql/oauth-center.sql index 627de1d89..8211ce8f3 100644 --- a/zlt-doc/sql/oauth-center.sql +++ b/zlt-doc/sql/oauth-center.sql @@ -22,8 +22,7 @@ CREATE TABLE `oauth_client_details` ( `create_time` datetime(0) NULL DEFAULT NULL, `update_time` datetime(0) NULL DEFAULT NULL, `client_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '应用名称', - `support_id_token` tinyint(1) DEFAULT 1 COMMENT '是否支持id_token', - `id_token_validity` int(11) DEFAULT 60 COMMENT 'id_token有效期', + `token_format` varchar(10) not null DEFAULT 'reference' COMMENT 'token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt))', `creator_id` int(11) COMMENT '创建人id', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; @@ -31,6 +30,6 @@ CREATE TABLE `oauth_client_details` ( -- ---------------------------- -- Records of oauth_client_details -- ---------------------------- -INSERT INTO `oauth_client_details` VALUES (1, 'webApp', NULL, '$2a$10$06msMGYRH8nrm4iVnKFNKOoddB8wOwymVhbUzw/d3ZixD7Nq8ot72', 'webApp', 'app', 'authorization_code,password,refresh_token,client_credentials,implicit,password_code,openId,mobile_password', 'http://127.0.0.1:8082/callback.html', NULL, 3600, NULL, '{"LOGOUT_NOTIFY_URL_LIST":"http://127.0.0.1:8082/logoutNotify"}', 'true', NULL, NULL, 'pc端', 1, 60, 1); -INSERT INTO `oauth_client_details` VALUES (2, 'app', NULL, '$2a$10$i3F515wEDiB4Gvj9ym9Prui0dasRttEUQ9ink4Wpgb4zEDCAlV8zO', 'app', 'app', 'authorization_code,password,refresh_token', 'http://127.0.0.1:8081/callback.html', NULL, 3600, NULL, '{"LOGOUT_NOTIFY_URL_LIST":"http://127.0.0.1:8081/logoutNotify"}', 'true', NULL, NULL, '移动端', 1, 60, 1); -INSERT INTO `oauth_client_details` VALUES (3, 'zlt', NULL, '$2a$10$/o.wuORzVcXaezmYVzwYMuoY7qeWXBALwQmkskXD/7C6rqfCyPrna', 'zlt', 'all', 'authorization_code,password,refresh_token,client_credentials', 'http://127.0.0.1:8080/singleLogin', NULL, 3600, 28800, '{}', 'true', '2018-12-27 00:50:30', '2018-12-27 00:50:30', '第三方应用', 1, 60, 1); \ No newline at end of file +INSERT INTO `oauth_client_details` VALUES (1, 'webApp', NULL, '$2a$10$06msMGYRH8nrm4iVnKFNKOoddB8wOwymVhbUzw/d3ZixD7Nq8ot72', 'webApp', 'app', 'authorization_code,password,refresh_token,client_credentials,implicit,password_code,openId,mobile_password', 'http://127.0.0.1:8082/callback.html', NULL, 3600, NULL, '{"LOGOUT_NOTIFY_URL_LIST":"http://127.0.0.1:8082/logoutNotify"}', 'true', NULL, NULL, 'pc端', 'reference', 1); +INSERT INTO `oauth_client_details` VALUES (2, 'app', NULL, '$2a$10$i3F515wEDiB4Gvj9ym9Prui0dasRttEUQ9ink4Wpgb4zEDCAlV8zO', 'app', 'app', 'authorization_code,password,refresh_token', 'http://127.0.0.1:8081/callback.html', NULL, 3600, NULL, '{"LOGOUT_NOTIFY_URL_LIST":"http://127.0.0.1:8081/logoutNotify"}', 'true', NULL, NULL, '移动端', 'reference', 1); +INSERT INTO `oauth_client_details` VALUES (3, 'zlt', NULL, '$2a$10$/o.wuORzVcXaezmYVzwYMuoY7qeWXBALwQmkskXD/7C6rqfCyPrna', 'zlt', 'all', 'authorization_code,password,refresh_token,client_credentials', 'http://127.0.0.1:8080/singleLogin', NULL, 3600, 28800, '{}', 'true', '2018-12-27 00:50:30', '2018-12-27 00:50:30', '第三方应用', 'reference', 1); \ No newline at end of file diff --git "a/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v6.0.0.sql" "b/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v6.0.0.sql" new file mode 100644 index 000000000..4085eef7a --- /dev/null +++ "b/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v6.0.0.sql" @@ -0,0 +1,5 @@ +------------更新语句 +Use `oauth-center`; +alter table oauth_client_details add token_format varchar(10) not null DEFAULT 'reference' COMMENT 'token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt))'; +alter table oauth_client_details drop column support_id_token; +alter table oauth_client_details drop column id_token_validity; \ No newline at end of file diff --git a/zlt-gateway/sc-gateway/pom.xml b/zlt-gateway/sc-gateway/pom.xml index 88c12ce5d..a1300774f 100644 --- a/zlt-gateway/sc-gateway/pom.xml +++ b/zlt-gateway/sc-gateway/pom.xml @@ -76,7 +76,6 @@ com.github.xiaoymin knife4j-gateway-spring-boot-starter - 4.2.0 diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/CustomAuthenticationManager.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/CustomAuthenticationManager.java deleted file mode 100644 index d42637083..000000000 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/CustomAuthenticationManager.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.central.gateway.auth; - -import org.springframework.security.authentication.ReactiveAuthenticationManager; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken; -import reactor.core.publisher.Mono; - -/** - * @author zlt - * @date 2019/10/6 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class CustomAuthenticationManager implements ReactiveAuthenticationManager { - private TokenStore tokenStore; - - public CustomAuthenticationManager(TokenStore tokenStore) { - this.tokenStore = tokenStore; - } - - @Override - public Mono authenticate(Authentication authentication) { - return Mono.justOrEmpty(authentication) - .filter(a -> a instanceof BearerTokenAuthenticationToken) - .cast(BearerTokenAuthenticationToken.class) - .map(BearerTokenAuthenticationToken::getToken) - .flatMap((accessTokenValue -> { - OAuth2AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue); - if (accessToken == null) { - return Mono.error(new InvalidTokenException("Invalid access token: " + accessTokenValue)); - } else if (accessToken.isExpired()) { - tokenStore.removeAccessToken(accessToken); - return Mono.error(new InvalidTokenException("Access token expired: " + accessTokenValue)); - } - - OAuth2Authentication result = tokenStore.readAuthentication(accessToken); - if (result == null) { - return Mono.error(new InvalidTokenException("Invalid access token: " + accessTokenValue)); - } - return Mono.just(result); - })) - .cast(Authentication.class); - } -} diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/CustomServerWebExchangeMatchers.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/CustomServerWebExchangeMatchers.java deleted file mode 100644 index a74201d82..000000000 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/CustomServerWebExchangeMatchers.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.central.gateway.auth; - -import com.central.oauth2.common.properties.SecurityProperties; -import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher; -import org.springframework.util.AntPathMatcher; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; - -/** - * 自定义 ServerWebExchangeMatcher - * 解决只要请求携带access_token,排除鉴权的url依然会被拦截 - * - * @author zlt - * @version 1.0 - * @date 2022/6/10 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class CustomServerWebExchangeMatchers implements ServerWebExchangeMatcher { - private final SecurityProperties securityProperties; - - private final AntPathMatcher antPathMatcher = new AntPathMatcher(); - - public CustomServerWebExchangeMatchers(SecurityProperties securityProperties) { - this.securityProperties = securityProperties; - } - - @Override - public Mono matches(ServerWebExchange exchange) { - for (String url : securityProperties.getIgnore().getUrls()) { - if (antPathMatcher.match(url, exchange.getRequest().getURI().getPath())) { - return MatchResult.notMatch(); - } - } - return MatchResult.match(); - } -} diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/JsonAccessDeniedHandler.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/JsonAccessDeniedHandler.java deleted file mode 100644 index 9223ede21..000000000 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/JsonAccessDeniedHandler.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.central.gateway.auth; - -import com.central.common.utils.WebfluxResponseUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; - -/** - * 403拒绝访问异常处理,转换为JSON - * - * @author zlt - * @date 2019/10/7 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -public class JsonAccessDeniedHandler implements ServerAccessDeniedHandler { - @Override - public Mono handle(ServerWebExchange exchange, AccessDeniedException e) { - return WebfluxResponseUtil.responseFailed(exchange, HttpStatus.FORBIDDEN.value(), e.getMessage()); - } -} diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/JsonAuthenticationEntryPoint.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/JsonAuthenticationEntryPoint.java deleted file mode 100644 index 45627bad0..000000000 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/JsonAuthenticationEntryPoint.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.central.gateway.auth; - -import com.central.common.utils.WebfluxResponseUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.server.ServerAuthenticationEntryPoint; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; - -/** - * 401未授权异常处理,转换为JSON - * - * @author zlt - * @date 2019/10/7 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -public class JsonAuthenticationEntryPoint implements ServerAuthenticationEntryPoint { - @Override - public Mono commence(ServerWebExchange exchange, AuthenticationException e) { - return WebfluxResponseUtil.responseFailed(exchange, HttpStatus.UNAUTHORIZED.value(), e.getMessage()); - } -} diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/Oauth2AuthSuccessHandler.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/Oauth2AuthSuccessHandler.java deleted file mode 100644 index 88576fac8..000000000 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/Oauth2AuthSuccessHandler.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.central.gateway.auth; - -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.util.StrUtil; -import com.central.common.constant.SecurityConstants; -import com.central.common.model.SysUser; -import com.central.oauth2.common.util.AuthUtils; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.web.server.WebFilterExchange; -import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; - -/** - * 认证成功处理类 - * - * @author zlt - * @date 2019/10/7 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class Oauth2AuthSuccessHandler implements ServerAuthenticationSuccessHandler { - @Override - public Mono onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { - MultiValueMap headerValues = new LinkedMultiValueMap<>(4); - Object principal = authentication.getPrincipal(); - //客户端模式只返回一个clientId - if (principal instanceof SysUser) { - SysUser user = (SysUser)authentication.getPrincipal(); - headerValues.add(SecurityConstants.USER_ID_HEADER, String.valueOf(user.getId())); - headerValues.add(SecurityConstants.USER_HEADER, user.getUsername()); - } - OAuth2Authentication oauth2Authentication = (OAuth2Authentication)authentication; - String clientId = oauth2Authentication.getOAuth2Request().getClientId(); - headerValues.add(SecurityConstants.TENANT_HEADER, clientId); - headerValues.add(SecurityConstants.ROLE_HEADER, CollectionUtil.join(authentication.getAuthorities(), ",")); - String accountType = AuthUtils.getAccountType(oauth2Authentication.getUserAuthentication()); - if (StrUtil.isNotEmpty(accountType)) { - headerValues.add(SecurityConstants.ACCOUNT_TYPE_HEADER, accountType); - } - ServerWebExchange exchange = webFilterExchange.getExchange(); - ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate() - .headers(h -> h.addAll(headerValues)) - .build(); - - ServerWebExchange build = exchange.mutate().request(serverHttpRequest).build(); - return webFilterExchange.getChain().filter(build); - } -} diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/PermissionAuthManager.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/PermissionAuthManager.java deleted file mode 100644 index 0bd0af652..000000000 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/PermissionAuthManager.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.central.gateway.auth; - -import com.central.common.model.SysMenu; -import com.central.gateway.feign.AsynMenuService; -import com.central.oauth2.common.service.impl.DefaultPermissionServiceImpl; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.security.authorization.AuthorizationDecision; -import org.springframework.security.authorization.ReactiveAuthorizationManager; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.server.authorization.AuthorizationContext; -import org.springframework.stereotype.Component; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; - -import javax.annotation.Resource; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Future; - -/** - * url权限认证 - * - * @author zlt - * @date 2019/10/6 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -@Component -public class PermissionAuthManager extends DefaultPermissionServiceImpl implements ReactiveAuthorizationManager { - @Resource - private AsynMenuService asynMenuService; - - @Override - public Mono check(Mono authentication, AuthorizationContext authorizationContext) { - return authentication.map(auth -> { - ServerWebExchange exchange = authorizationContext.getExchange(); - ServerHttpRequest request = exchange.getRequest(); - boolean isPermission = super.hasPermission(auth, request.getMethodValue(), request.getURI().getPath()); - return new AuthorizationDecision(isPermission); - }).defaultIfEmpty(new AuthorizationDecision(false)); - } - - @Override - public List findMenuByRoleCodes(String roleCodes) { - Future> futureResult = asynMenuService.findByRoleCodes(roleCodes); - try { - return futureResult.get(); - } catch (Exception e) { - log.error("asynMenuService.findMenuByRoleCodes-error", e); - } - return Collections.emptyList(); - } -} \ No newline at end of file diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java deleted file mode 100644 index 34305a815..000000000 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.central.gateway.config; - -import com.central.gateway.auth.*; -import com.central.oauth2.common.properties.SecurityProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; -import org.springframework.security.authentication.ReactiveAuthenticationManager; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.config.web.server.SecurityWebFiltersOrder; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.oauth2.server.resource.web.server.authentication.ServerBearerTokenAuthenticationConverter; -import org.springframework.security.web.server.SecurityWebFilterChain; -import org.springframework.security.web.server.authentication.AuthenticationWebFilter; -import org.springframework.security.web.server.authentication.ServerAuthenticationEntryPointFailureHandler; - -/** - * 资源服务器配置 - * - * @author zlt - * @date 2019/10/5 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Configuration -@EnableWebFluxSecurity -public class ResourceServerConfiguration { - @Bean - public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http - , SecurityProperties securityProperties, TokenStore tokenStore, PermissionAuthManager permissionAuthManager) { - //认证处理器 - ReactiveAuthenticationManager customAuthenticationManager = new CustomAuthenticationManager(tokenStore); - JsonAuthenticationEntryPoint entryPoint = new JsonAuthenticationEntryPoint(); - //token转换器 - ServerBearerTokenAuthenticationConverter tokenAuthenticationConverter = new ServerBearerTokenAuthenticationConverter(); - tokenAuthenticationConverter.setAllowUriQueryParameter(true); - //oauth2认证过滤器 - AuthenticationWebFilter oauth2Filter = new AuthenticationWebFilter(customAuthenticationManager); - oauth2Filter.setServerAuthenticationConverter(tokenAuthenticationConverter); - oauth2Filter.setAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(entryPoint)); - oauth2Filter.setAuthenticationSuccessHandler(new Oauth2AuthSuccessHandler()); - oauth2Filter.setRequiresAuthenticationMatcher(new CustomServerWebExchangeMatchers(securityProperties)); - http.addFilterAt(oauth2Filter, SecurityWebFiltersOrder.AUTHENTICATION); - - ServerHttpSecurity.AuthorizeExchangeSpec authorizeExchange = http.authorizeExchange(); - if (securityProperties.getAuth().getHttpUrls().length > 0) { - authorizeExchange.pathMatchers(securityProperties.getAuth().getHttpUrls()).authenticated(); - } - if (securityProperties.getIgnore().getUrls().length > 0) { - authorizeExchange.pathMatchers(securityProperties.getIgnore().getUrls()).permitAll(); - } - authorizeExchange - .pathMatchers(HttpMethod.OPTIONS).permitAll() - .anyExchange() - .access(permissionAuthManager) - .and() - .exceptionHandling() - .accessDeniedHandler(new JsonAccessDeniedHandler()) - .authenticationEntryPoint(entryPoint) - .and() - .headers() - .frameOptions() - .disable() - .and() - .httpBasic().disable() - .csrf().disable(); - return http.build(); - } -} diff --git a/zlt-gateway/sc-gateway/src/main/resources/application.yml b/zlt-gateway/sc-gateway/src/main/resources/application.yml index f7f69bf3f..dbdfba45d 100644 --- a/zlt-gateway/sc-gateway/src/main/resources/application.yml +++ b/zlt-gateway/sc-gateway/src/main/resources/application.yml @@ -82,6 +82,12 @@ spring: # filter: # enabled: true +knife4j: + gateway: + enabled: true + discover: + excluded-services: ${spring.application.name} + zlt: swagger-agg: generate-routes: user,file diff --git a/zlt-monitor/log-center/pom.xml b/zlt-monitor/log-center/pom.xml index eb2d27bfb..45909e614 100644 --- a/zlt-monitor/log-center/pom.xml +++ b/zlt-monitor/log-center/pom.xml @@ -23,8 +23,8 @@ - com.zlt - zlt-swagger2-spring-boot-starter + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter com.zlt diff --git a/zlt-monitor/log-center/src/main/java/com/central/log/controller/AggregationController.java b/zlt-monitor/log-center/src/main/java/com/central/log/controller/AggregationController.java index 8dc77caa4..203f544e3 100644 --- a/zlt-monitor/log-center/src/main/java/com/central/log/controller/AggregationController.java +++ b/zlt-monitor/log-center/src/main/java/com/central/log/controller/AggregationController.java @@ -1,7 +1,8 @@ package com.central.log.controller; import com.central.search.client.service.IQueryService; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -14,12 +15,13 @@ * @author zlt * @date 2019/5/8 */ +@Tag(name = "访问统计") @RestController public class AggregationController { @Autowired private IQueryService queryService; - @ApiOperation(value = "访问统计") + @Operation(summary = "访问统计") @GetMapping(value = "/requestStat") public Map requestStatAgg() { return queryService.requestStatAgg("point-log-*","request-statistics"); diff --git a/zlt-monitor/log-center/src/main/java/com/central/log/controller/AuditLogController.java b/zlt-monitor/log-center/src/main/java/com/central/log/controller/AuditLogController.java index 5631aa13e..4d3bce748 100644 --- a/zlt-monitor/log-center/src/main/java/com/central/log/controller/AuditLogController.java +++ b/zlt-monitor/log-center/src/main/java/com/central/log/controller/AuditLogController.java @@ -4,9 +4,8 @@ import com.central.search.client.service.IQueryService; import com.central.search.model.SearchDto; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -19,6 +18,7 @@ * Blog: http://zlt2000.gitee.io * Github: https://github.com/zlt2000 */ +@Tag(name = "审计日志") @RestController public class AuditLogController { private final IQueryService queryService; @@ -27,12 +27,7 @@ public AuditLogController(IQueryService queryService) { this.queryService = queryService; } - @ApiOperation(value = "审计日志全文搜索列表") - @ApiImplicitParams({ - @ApiImplicitParam(name = "page", value = "分页起始位置", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "limit", value = "分页结束位置", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "queryStr", value = "搜索关键字", dataType = "String") - }) + @Operation(summary = "审计日志全文搜索列表") @GetMapping(value = "/auditLog") public PageResult getPage(SearchDto searchDto) { searchDto.setIsHighlighter(true); diff --git a/zlt-monitor/log-center/src/main/java/com/central/log/controller/SlowQueryLogController.java b/zlt-monitor/log-center/src/main/java/com/central/log/controller/SlowQueryLogController.java index 99d5a3f65..6ba0fae75 100644 --- a/zlt-monitor/log-center/src/main/java/com/central/log/controller/SlowQueryLogController.java +++ b/zlt-monitor/log-center/src/main/java/com/central/log/controller/SlowQueryLogController.java @@ -4,9 +4,8 @@ import com.central.search.client.service.IQueryService; import com.central.search.model.SearchDto; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -16,17 +15,13 @@ * * @author zlt */ +@Tag(name = "慢查询日志") @RestController public class SlowQueryLogController { @Autowired private IQueryService queryService; - @ApiOperation(value = "慢sql日志全文搜索列表") - @ApiImplicitParams({ - @ApiImplicitParam(name = "page", value = "分页起始位置", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "limit", value = "分页结束位置", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "queryStr", value = "搜索关键字", dataType = "String") - }) + @Operation(summary = "慢sql日志全文搜索列表") @GetMapping(value = "/slowQueryLog") public PageResult getPage(SearchDto searchDto) { searchDto.setIsHighlighter(true); diff --git a/zlt-monitor/log-center/src/main/java/com/central/log/controller/SysLogController.java b/zlt-monitor/log-center/src/main/java/com/central/log/controller/SysLogController.java index 1a483ee2c..6869e882a 100644 --- a/zlt-monitor/log-center/src/main/java/com/central/log/controller/SysLogController.java +++ b/zlt-monitor/log-center/src/main/java/com/central/log/controller/SysLogController.java @@ -6,9 +6,8 @@ import com.central.search.client.service.IQueryService; import com.central.search.model.SearchDto; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -20,6 +19,7 @@ * * @author zlt */ +@Tag(name = "系统日志") @RestController public class SysLogController { /** @@ -33,27 +33,13 @@ public class SysLogController { @Resource private TraceLogService traceLogService; - @ApiOperation(value = "系统日志全文搜索列表") - @ApiImplicitParams({ - @ApiImplicitParam(name = "page", value = "分页起始位置", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "limit", value = "分页结束位置", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "queryStr", value = "搜索关键字", dataType = "String"), - @ApiImplicitParam(name = "sortCol", value = "排序字段", dataType = "String"), - @ApiImplicitParam(name = "sortOrder", value = "排序顺序", dataType = "String"), - @ApiImplicitParam(name = "isHighlighter", value = "是否显示高亮", dataType = "String") - }) + @Operation(summary = "系统日志全文搜索列表") @GetMapping(value = "/sysLog") public PageResult sysLog(SearchDto searchDto) { return queryService.strQuery(SYS_LOG_INDEXNAME, searchDto); } - @ApiOperation(value = "系统日志链路列表") - @ApiImplicitParams({ - @ApiImplicitParam(name = "queryStr", value = "搜索关键字", dataType = "String"), - @ApiImplicitParam(name = "sortCol", value = "排序字段", dataType = "String"), - @ApiImplicitParam(name = "sortOrder", value = "排序顺序", dataType = "String"), - @ApiImplicitParam(name = "isHighlighter", value = "是否显示高亮", dataType = "String") - }) + @Operation(summary = "系统日志链路列表") @GetMapping(value = "/traceLog") public PageResult traceLog(SearchDto searchDto) { PageResult pageResult = queryService.strQuery(SYS_LOG_INDEXNAME, searchDto); diff --git a/zlt-uaa/pom.xml b/zlt-uaa/pom.xml index b21c593fa..5efd2379b 100644 --- a/zlt-uaa/pom.xml +++ b/zlt-uaa/pom.xml @@ -33,14 +33,9 @@ com.zlt zlt-loadbalancer-spring-boot-starter - com.github.xiaoymin knife4j-openapi3-jakarta-spring-boot-starter - 4.2.0 com.zlt @@ -67,11 +62,6 @@ commons-io commons-io - - - com.github.whvcse - easy-captcha - org.springframework.boot @@ -111,10 +101,6 @@ org.apache.tomcat.embed tomcat-embed-core - - javax.servlet - javax.servlet-api - diff --git a/zlt-uaa/src/main/java/com/central/oauth/controller/ValidateCodeController.java b/zlt-uaa/src/main/java/com/central/oauth/controller/ValidateCodeController.java index dd7170ceb..a387b76d7 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/controller/ValidateCodeController.java +++ b/zlt-uaa/src/main/java/com/central/oauth/controller/ValidateCodeController.java @@ -1,11 +1,11 @@ package com.central.oauth.controller; +import cn.hutool.captcha.CaptchaUtil; +import cn.hutool.captcha.LineCaptcha; import com.central.common.constant.SecurityConstants; import com.central.common.model.Result; import com.central.oauth.service.IValidateCodeService; -import com.wf.captcha.base.Captcha; -import com.wf.captcha.GifCaptcha; -import com.wf.captcha.utils.CaptchaUtil; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.util.Assert; @@ -13,7 +13,6 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.ResponseBody; -import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** @@ -33,17 +32,19 @@ public class ValidateCodeController { */ @GetMapping(SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX + "/{deviceId}") public void createCode(@PathVariable String deviceId, HttpServletResponse response) throws IOException { + Assert.notNull(deviceId, "机器码不能为空"); Assert.notNull(deviceId, "机器码不能为空"); // 设置请求头为输出图片类型 - CaptchaUtil.setHeader(response); - // 三个参数分别为宽、高、位数 - GifCaptcha gifCaptcha = new GifCaptcha(100, 35, 4); - // 设置类型:字母数字混合 - gifCaptcha.setCharType(Captcha.TYPE_DEFAULT); + response.setContentType("image/jpeg"); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setDateHeader("Expires", 0); + // 三个参数分别为宽、高、验证码字符数、干扰线宽度 + LineCaptcha captcha = CaptchaUtil.createLineCaptcha(100, 35, 4, 10); // 保存验证码 - validateCodeService.saveImageCode(deviceId, gifCaptcha.text().toLowerCase()); + validateCodeService.saveImageCode(deviceId, captcha.getCode().toLowerCase()); // 输出图片流 - gifCaptcha.out(response.getOutputStream()); + captcha.write(response.getOutputStream()); } /** diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java b/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java index 8003650fa..3f69a98b1 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java @@ -17,7 +17,7 @@ public interface IValidateCodeService { */ void saveImageCode(String deviceId, String imageCode); - Result sendSmsCode(String mobile); + Result sendSmsCode(String mobile); /** * 获取验证码 diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java index 08927bb25..04cce984c 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java @@ -54,7 +54,7 @@ public void saveImageCode(String deviceId, String imageCode) { * @return true、false */ @Override - public Result sendSmsCode(String mobile) { + public Result sendSmsCode(String mobile) { Object tempCode = redisRepository.get(buildKey(mobile)); if (tempCode != null) { log.error("用户:{}验证码未失效{}", mobile, tempCode); diff --git a/zlt-uaa/src/main/resources/application.yml b/zlt-uaa/src/main/resources/application.yml index c4910e53b..0952ae434 100644 --- a/zlt-uaa/src/main/resources/application.yml +++ b/zlt-uaa/src/main/resources/application.yml @@ -13,17 +13,30 @@ mybatis-plus: db-config: id-type: auto +springdoc: + swagger-ui: + path: /swagger-ui.html + tags-sorter: alpha + operations-sorter: alpha + api-docs: + path: /v3/api-docs + group-configs: + - group: 'uaa' + paths-to-match: '/**' + packages-to-scan: com.central.oauth.controller + default-flat-param-object: true + +knife4j: + enable: true + setting: + language: zh_cn + swagger-model-name: 认证中心接口文档 + zlt: oauth2: token: store: type: redis - swagger: - enabled: true - title: 认证中心 - description: 认证中心接口文档 - version: 1.0 - base-package: com.central.oauth.controller security: code: # 忽略验证码的应用编号 @@ -43,21 +56,4 @@ zlt: enabled: false includeSqls: # 应用列表 - - com.central.oauth.mapper.ClientMapper.findList - -springdoc: - swagger-ui: - path: /doc.html - api-docs: - path: /v3/api-docs - group-configs: - - group: 'uaa' - paths-to-match: '/**' - packages-to-scan: com.central.oauth.controller - default-flat-param-object: true - -knife4j: - enable: true - setting: - language: zh_cn - swagger-model-name: 认证中心接口文档 \ No newline at end of file + - com.central.oauth.mapper.ClientMapper.findList \ No newline at end of file From 7335dd8521a32bd2957636ff4e886ae4a0e7f707 Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Sat, 25 Nov 2023 10:17:54 +0800 Subject: [PATCH 07/23] =?UTF-8?q?feat:=20=E7=BD=91=E5=85=B3=E8=81=9A?= =?UTF-8?q?=E5=90=88swagger=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 2 +- .../src/main/resources/application.yml | 2 +- .../oss/properties/FileServerProperties.java | 1 - .../main/resources/META-INF/spring.factories | 2 -- ...oot.autoconfigure.AutoConfiguration.imports | 1 + zlt-gateway/sc-gateway/pom.xml | 12 ++++-------- .../error/JsonErrorWebExceptionHandler.java | 6 +++--- .../src/main/resources/application.yml | 18 ++++++++++++++---- 8 files changed, 24 insertions(+), 20 deletions(-) delete mode 100644 zlt-commons/zlt-oss-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 zlt-commons/zlt-oss-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/zlt-business/file-center/src/main/resources/application.yml b/zlt-business/file-center/src/main/resources/application.yml index a0ee2d8d2..b5741b6f0 100644 --- a/zlt-business/file-center/src/main/resources/application.yml +++ b/zlt-business/file-center/src/main/resources/application.yml @@ -21,7 +21,7 @@ springdoc: api-docs: path: /v3/api-docs group-configs: - - group: 'file' + - group: 'default' paths-to-match: '/**' packages-to-scan: com.central.file.controller default-flat-param-object: true diff --git a/zlt-business/user-center/src/main/resources/application.yml b/zlt-business/user-center/src/main/resources/application.yml index 123f260de..41885be37 100644 --- a/zlt-business/user-center/src/main/resources/application.yml +++ b/zlt-business/user-center/src/main/resources/application.yml @@ -21,7 +21,7 @@ springdoc: api-docs: path: /v3/api-docs group-configs: - - group: 'user' + - group: 'default' paths-to-match: '/**' packages-to-scan: com.central.user.controller default-flat-param-object: true diff --git a/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java b/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java index 0cea8a703..28288093f 100644 --- a/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java +++ b/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java @@ -15,7 +15,6 @@ @Setter @Getter @ConfigurationProperties(prefix = FileServerProperties.PREFIX) -@Component public class FileServerProperties { public static final String PREFIX = "zlt.file-server"; public static final String TYPE_FDFS = "fastdfs"; diff --git a/zlt-commons/zlt-oss-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-oss-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 43d799a7b..000000000 --- a/zlt-commons/zlt-oss-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.oss.config.OssAutoConfigure \ No newline at end of file diff --git a/zlt-commons/zlt-oss-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-oss-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..3abb13b2a --- /dev/null +++ b/zlt-commons/zlt-oss-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.central.oss.config.OssAutoConfigure diff --git a/zlt-gateway/sc-gateway/pom.xml b/zlt-gateway/sc-gateway/pom.xml index a1300774f..ccd5f63d9 100644 --- a/zlt-gateway/sc-gateway/pom.xml +++ b/zlt-gateway/sc-gateway/pom.xml @@ -54,10 +54,10 @@ - + org.springframework.cloud @@ -78,10 +78,10 @@ knife4j-gateway-spring-boot-starter - + com.baomidou mybatis-plus-extension @@ -94,10 +94,6 @@ eu.bitwalker UserAgentUtils - - org.springframework.security.oauth - spring-security-oauth2 - diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/JsonErrorWebExceptionHandler.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/JsonErrorWebExceptionHandler.java index 17ae7acc7..c22adee6c 100644 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/JsonErrorWebExceptionHandler.java +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/error/JsonErrorWebExceptionHandler.java @@ -7,7 +7,6 @@ import org.springframework.boot.web.reactive.error.ErrorAttributes; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpStatus; -import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.web.reactive.function.server.*; import java.util.HashMap; @@ -91,12 +90,13 @@ private Map responseError(ServerRequest request, Throwable error private int getHttpStatus(Throwable error) { int httpStatus; - if (error instanceof InvalidTokenException) { + /*if (error instanceof InvalidTokenException) { InvalidTokenException ex = (InvalidTokenException)error; httpStatus = ex.getHttpErrorCode(); } else { httpStatus = HttpStatus.INTERNAL_SERVER_ERROR.value(); - } + }*/ + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR.value(); return httpStatus; } } diff --git a/zlt-gateway/sc-gateway/src/main/resources/application.yml b/zlt-gateway/sc-gateway/src/main/resources/application.yml index dbdfba45d..b73d27b3b 100644 --- a/zlt-gateway/sc-gateway/src/main/resources/application.yml +++ b/zlt-gateway/sc-gateway/src/main/resources/application.yml @@ -85,12 +85,22 @@ spring: knife4j: gateway: enabled: true - discover: - excluded-services: ${spring.application.name} + strategy: manual + routes: + - name: 用户服务 + service-name: user-center + url: /api-user/v3/api-docs/default + context-path: /api-user + - name: 文件服务 + service-name: file-center + url: /api-file/v3/api-docs/default + context-path: /api-file + +# discover: +# version: openapi3 +# excluded-services: ${spring.application.name} zlt: - swagger-agg: - generate-routes: user,file oauth2: token: store: From cb77754ca24a6845aede47296a15a5a7a854797e Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Sat, 25 Nov 2023 10:40:12 +0800 Subject: [PATCH 08/23] =?UTF-8?q?feat:=20=E6=9B=BF=E6=8D=A2spring.factorie?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/META-INF/spring.factories | 2 -- ...gframework.boot.autoconfigure.AutoConfiguration.imports | 1 + .../common/feign/fallback/UserServiceFallbackFactory.java | 2 -- .../src/main/java/com/central/common/utils/SpringUtil.java | 2 -- .../src/main/resources/META-INF/spring.factories | 7 +------ ...gframework.boot.autoconfigure.AutoConfiguration.imports | 3 +++ .../src/main/resources/META-INF/spring.factories | 3 --- ...gframework.boot.autoconfigure.AutoConfiguration.imports | 2 ++ .../src/main/resources/META-INF/spring.factories | 3 --- ...gframework.boot.autoconfigure.AutoConfiguration.imports | 2 ++ .../src/main/resources/META-INF/spring.factories | 2 -- ...gframework.boot.autoconfigure.AutoConfiguration.imports | 1 + .../src/main/resources/META-INF/spring.factories | 3 --- ...gframework.boot.autoconfigure.AutoConfiguration.imports | 2 ++ .../src/main/resources/META-INF/spring.factories | 5 +---- ...gframework.boot.autoconfigure.AutoConfiguration.imports | 1 + .../java/com/central/common/redis/RedisAutoConfigure.java | 1 - .../src/main/resources/META-INF/spring.factories | 2 -- ...gframework.boot.autoconfigure.AutoConfiguration.imports | 1 + .../src/main/resources/META-INF/spring.factories | 2 -- ...gframework.boot.autoconfigure.AutoConfiguration.imports | 1 + .../src/main/resources/META-INF/spring.factories | 2 -- ...gframework.boot.autoconfigure.AutoConfiguration.imports | 1 + .../src/main/resources/META-INF/spring.factories | 2 -- ...gframework.boot.autoconfigure.AutoConfiguration.imports | 1 + 25 files changed, 18 insertions(+), 36 deletions(-) delete mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 zlt-commons/zlt-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 zlt-commons/zlt-common-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 zlt-commons/zlt-common-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 zlt-commons/zlt-db-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 zlt-commons/zlt-db-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 zlt-commons/zlt-log-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 zlt-commons/zlt-sentinel-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 zlt-commons/zlt-sentinel-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 zlt-demo/seata-demo/seata-common-starter/src/main/resources/META-INF/spring.factories create mode 100644 zlt-demo/seata-demo/seata-common-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 9862b1d39..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.oauth2.common.AuthClientAutoConfiguration \ No newline at end of file diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..5c03a0f69 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.central.oauth2.common.AuthClientAutoConfiguration \ No newline at end of file diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java index 12d5f7cea..4a249494f 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java @@ -6,7 +6,6 @@ import com.central.common.model.SysUser; import org.springframework.cloud.openfeign.FallbackFactory; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; import java.util.Collections; import java.util.List; @@ -18,7 +17,6 @@ * @date 2019/1/18 */ @Slf4j -@Component public class UserServiceFallbackFactory implements FallbackFactory { @Override public UserService create(Throwable throwable) { diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/SpringUtil.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/SpringUtil.java index 678fca784..9d909fe9f 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/SpringUtil.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/SpringUtil.java @@ -4,14 +4,12 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.core.annotation.Order; import org.springframework.core.env.Environment; -import org.springframework.stereotype.Component; /** * spring获取bean工具类 * * @author 作者 owen E-mail: 624191343@qq.com */ -@Component @Order(0) public class SpringUtil implements ApplicationContextAware { diff --git a/zlt-commons/zlt-common-core/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-common-core/src/main/resources/META-INF/spring.factories index 091a4a1e3..7c72414bd 100644 --- a/zlt-commons/zlt-common-core/src/main/resources/META-INF/spring.factories +++ b/zlt-commons/zlt-common-core/src/main/resources/META-INF/spring.factories @@ -1,7 +1,2 @@ org.springframework.context.ApplicationContextInitializer=\ -com.central.common.config.BannerInitializer - -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.common.feign.fallback.UserServiceFallbackFactory,\ -com.central.common.lock.LockAspect,\ -com.central.common.utils.SpringUtil \ No newline at end of file +com.central.common.config.BannerInitializer \ No newline at end of file diff --git a/zlt-commons/zlt-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..4b2316f26 --- /dev/null +++ b/zlt-commons/zlt-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,3 @@ +com.central.common.feign.fallback.UserServiceFallbackFactory +com.central.common.lock.LockAspect +com.central.common.utils.SpringUtil \ No newline at end of file diff --git a/zlt-commons/zlt-common-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-common-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index ffb5ffd99..000000000 --- a/zlt-commons/zlt-common-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.common.filter.TenantFilter, \ -com.central.common.filter.LoginUserFilter \ No newline at end of file diff --git a/zlt-commons/zlt-common-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-common-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..c6b3ecb8b --- /dev/null +++ b/zlt-commons/zlt-common-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +com.central.common.filter.TenantFilter +com.central.common.filter.LoginUserFilter \ No newline at end of file diff --git a/zlt-commons/zlt-db-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-db-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index a939175dd..000000000 --- a/zlt-commons/zlt-db-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.db.config.TenantAutoConfigure,\ -com.central.db.config.MybatisPlusAutoConfigure diff --git a/zlt-commons/zlt-db-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-db-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..fc4a53828 --- /dev/null +++ b/zlt-commons/zlt-db-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +com.central.db.config.TenantAutoConfigure +com.central.db.config.MybatisPlusAutoConfigure \ No newline at end of file diff --git a/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index fdaf2cf30..000000000 --- a/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.es.config.RestAutoConfigure \ No newline at end of file diff --git a/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..e6eeaa707 --- /dev/null +++ b/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.central.es.config.RestAutoConfigure \ No newline at end of file diff --git a/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 6154b24d4..000000000 --- a/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.common.lb.RestTemplateAutoConfigure,\ -com.central.common.lb.config.VerionIsolationAutoConfig \ No newline at end of file diff --git a/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..d58da65bd --- /dev/null +++ b/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +com.central.common.lb.RestTemplateAutoConfigure +com.central.common.lb.config.VerionIsolationAutoConfig \ No newline at end of file diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-log-spring-boot-starter/src/main/resources/META-INF/spring.factories index afcf8d5ad..6a817fe42 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -1,5 +1,2 @@ org.springframework.context.ApplicationContextInitializer=\ -com.central.log.config.TtlMDCAdapterInitializer - -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.log.LogAutoConfigure \ No newline at end of file +com.central.log.config.TtlMDCAdapterInitializer \ No newline at end of file diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-log-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..a350d8628 --- /dev/null +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.central.log.LogAutoConfigure \ No newline at end of file diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java index af2f27d57..edfa0d36d 100644 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java @@ -30,7 +30,6 @@ * Blog: http://zlt2000.gitee.io * Github: https://github.com/zlt2000 */ -@Configuration @ComponentScan @EnableConfigurationProperties({RedisProperties.class, CacheManagerProperties.class}) @EnableCaching diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 0aa42a0ea..000000000 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.common.redis.RedisAutoConfigure \ No newline at end of file diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..a936b4a24 --- /dev/null +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.central.common.redis.RedisAutoConfigure \ No newline at end of file diff --git a/zlt-commons/zlt-sentinel-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-sentinel-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 69f011606..000000000 --- a/zlt-commons/zlt-sentinel-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.sentinel.config.SentinelAutoConfigure diff --git a/zlt-commons/zlt-sentinel-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-sentinel-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..bce30fd80 --- /dev/null +++ b/zlt-commons/zlt-sentinel-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.central.sentinel.config.SentinelAutoConfigure \ No newline at end of file diff --git a/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 96f338c07..000000000 --- a/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.common.zookeeper.ZookeeperAutoConfiguration \ No newline at end of file diff --git a/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..3df4ac075 --- /dev/null +++ b/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.central.common.zookeeper.ZookeeperAutoConfiguration \ No newline at end of file diff --git a/zlt-demo/seata-demo/seata-common-starter/src/main/resources/META-INF/spring.factories b/zlt-demo/seata-demo/seata-common-starter/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 022c67d4d..000000000 --- a/zlt-demo/seata-demo/seata-common-starter/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.central.common.config.DataSourceProxyConfig diff --git a/zlt-demo/seata-demo/seata-common-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-demo/seata-demo/seata-common-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..bcb004500 --- /dev/null +++ b/zlt-demo/seata-demo/seata-common-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.central.common.config.DataSourceProxyConfig \ No newline at end of file From c91f01aea1e72de276884674f962910add4d745e Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Sat, 25 Nov 2023 10:57:08 +0800 Subject: [PATCH 09/23] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9property?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/central/admin/properties/IndexProperties.java | 2 -- .../central/oauth2/common/properties/SecurityProperties.java | 2 -- .../central/oauth2/common/properties/TokenStoreProperties.java | 2 -- .../java/com/central/common/properties/DataScopeProperties.java | 2 -- .../java/com/central/common/properties/TenantProperties.java | 2 -- .../central/db/properties/MybatisPlusAutoFillProperties.java | 2 -- .../com/central/es/properties/RestClientPoolProperties.java | 2 -- .../com/central/common/lb/config/RestTemplateProperties.java | 2 -- .../java/com/central/log/properties/AuditLogProperties.java | 2 -- .../main/java/com/central/log/properties/LogDbProperties.java | 2 -- .../main/java/com/central/log/properties/TraceProperties.java | 2 -- .../java/com/central/oss/properties/FileServerProperties.java | 1 - .../central/common/redis/properties/CacheManagerProperties.java | 2 -- .../central/common/zookeeper/properties/ZookeeperProperty.java | 2 -- 14 files changed, 27 deletions(-) diff --git a/zlt-business/search-center/search-server/src/main/java/com/central/admin/properties/IndexProperties.java b/zlt-business/search-center/search-server/src/main/java/com/central/admin/properties/IndexProperties.java index 0a0edbe12..61d5d1291 100644 --- a/zlt-business/search-center/search-server/src/main/java/com/central/admin/properties/IndexProperties.java +++ b/zlt-business/search-center/search-server/src/main/java/com/central/admin/properties/IndexProperties.java @@ -4,7 +4,6 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.stereotype.Component; /** * 索引配置 @@ -15,7 +14,6 @@ @Getter @ConfigurationProperties(prefix = "zlt.indices") @RefreshScope -@Component public class IndexProperties { /** * 配置过滤的索引名:默认只显示这些索引 diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java index b2b0280b8..c23adea33 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java @@ -4,7 +4,6 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.stereotype.Component; /** * @author zlt @@ -18,7 +17,6 @@ @Getter @ConfigurationProperties(prefix = "zlt.security") @RefreshScope -@Component public class SecurityProperties { private AuthProperties auth = new AuthProperties(); diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java index bb1c4b449..d49a6c4ca 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java @@ -4,7 +4,6 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.stereotype.Component; /** * Token配置 @@ -20,7 +19,6 @@ @Getter @ConfigurationProperties(prefix = "zlt.oauth2.token.store") @RefreshScope -@Component public class TokenStoreProperties { /** * token存储类型(redis/db/authJwt/resJwt) diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/DataScopeProperties.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/DataScopeProperties.java index d2170e81a..2d3720a33 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/DataScopeProperties.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/DataScopeProperties.java @@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableSet; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; import java.util.Collections; import java.util.HashSet; @@ -17,7 +16,6 @@ */ @ConfigurationProperties(prefix = "zlt.datascope") @Data -@Component public class DataScopeProperties { private static final Set INGORE_SQL_ID = ImmutableSet .of("com.central.user.mapper.findRolesByUserId" diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/TenantProperties.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/TenantProperties.java index 51bdedaa3..e749a1f33 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/TenantProperties.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/properties/TenantProperties.java @@ -4,7 +4,6 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; @@ -18,7 +17,6 @@ @Getter @ConfigurationProperties(prefix = "zlt.tenant") @RefreshScope -@Component public class TenantProperties { /** * 是否开启多租户 diff --git a/zlt-commons/zlt-db-spring-boot-starter/src/main/java/com/central/db/properties/MybatisPlusAutoFillProperties.java b/zlt-commons/zlt-db-spring-boot-starter/src/main/java/com/central/db/properties/MybatisPlusAutoFillProperties.java index e62773e30..4217377e8 100644 --- a/zlt-commons/zlt-db-spring-boot-starter/src/main/java/com/central/db/properties/MybatisPlusAutoFillProperties.java +++ b/zlt-commons/zlt-db-spring-boot-starter/src/main/java/com/central/db/properties/MybatisPlusAutoFillProperties.java @@ -4,7 +4,6 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.stereotype.Component; /** * mybatis-plus 配置 @@ -19,7 +18,6 @@ @Getter @ConfigurationProperties(prefix = "zlt.mybatis-plus.auto-fill") @RefreshScope -@Component public class MybatisPlusAutoFillProperties { /** * 是否开启自动填充字段 diff --git a/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/properties/RestClientPoolProperties.java b/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/properties/RestClientPoolProperties.java index 8a8d725f6..bfe5f8d2b 100644 --- a/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/properties/RestClientPoolProperties.java +++ b/zlt-commons/zlt-elasticsearch-spring-boot-starter/src/main/java/com/central/es/properties/RestClientPoolProperties.java @@ -4,7 +4,6 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.stereotype.Component; /** * es的httpClient连接池配置 @@ -19,7 +18,6 @@ @Getter @ConfigurationProperties(prefix = "zlt.elasticsearch.rest-pool") @RefreshScope -@Component public class RestClientPoolProperties { /** * 链接建立超时时间 diff --git a/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/RestTemplateProperties.java b/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/RestTemplateProperties.java index 4833e8cdc..2e51ada20 100644 --- a/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/RestTemplateProperties.java +++ b/zlt-commons/zlt-loadbalancer-spring-boot-starter/src/main/java/com/central/common/lb/config/RestTemplateProperties.java @@ -3,7 +3,6 @@ import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; /** * RestTemplate 配置 @@ -17,7 +16,6 @@ @Setter @Getter @ConfigurationProperties(prefix = "zlt.rest-template") -@Component public class RestTemplateProperties { /** * 最大链接数 diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/AuditLogProperties.java b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/AuditLogProperties.java index 61faf49af..0ea4941ed 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/AuditLogProperties.java +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/AuditLogProperties.java @@ -4,7 +4,6 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.stereotype.Component; /** * 审计日志配置 @@ -19,7 +18,6 @@ @Getter @ConfigurationProperties(prefix = "zlt.audit-log") @RefreshScope -@Component public class AuditLogProperties { /** * 是否开启审计日志 diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/LogDbProperties.java b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/LogDbProperties.java index 4b169c689..f54e98374 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/LogDbProperties.java +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/LogDbProperties.java @@ -5,7 +5,6 @@ import lombok.Setter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; /** * 日志数据源配置 @@ -21,6 +20,5 @@ @Getter @ConfigurationProperties(prefix = "zlt.audit-log.datasource") @ConditionalOnClass(HikariConfig.class) -@Component public class LogDbProperties extends HikariConfig { } diff --git a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/TraceProperties.java b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/TraceProperties.java index 2a3cd2380..a3daa5468 100644 --- a/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/TraceProperties.java +++ b/zlt-commons/zlt-log-spring-boot-starter/src/main/java/com/central/log/properties/TraceProperties.java @@ -4,7 +4,6 @@ import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.stereotype.Component; /** * 日志链路追踪配置 @@ -16,7 +15,6 @@ @Getter @ConfigurationProperties(prefix = "zlt.trace") @RefreshScope -@Component public class TraceProperties { /** * 是否开启日志链路追踪 diff --git a/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java b/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java index 28288093f..565ef7b79 100644 --- a/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java +++ b/zlt-commons/zlt-oss-spring-boot-starter/src/main/java/com/central/oss/properties/FileServerProperties.java @@ -3,7 +3,6 @@ import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; /** * @author zlt diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/properties/CacheManagerProperties.java b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/properties/CacheManagerProperties.java index 4b969a940..422c6ef06 100644 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/properties/CacheManagerProperties.java +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/properties/CacheManagerProperties.java @@ -3,7 +3,6 @@ import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; import java.util.List; @@ -14,7 +13,6 @@ @Setter @Getter @ConfigurationProperties(prefix = "zlt.cache-manager") -@Component public class CacheManagerProperties { private List configs; diff --git a/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/java/com/central/common/zookeeper/properties/ZookeeperProperty.java b/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/java/com/central/common/zookeeper/properties/ZookeeperProperty.java index 637ab89f9..f65781d16 100644 --- a/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/java/com/central/common/zookeeper/properties/ZookeeperProperty.java +++ b/zlt-commons/zlt-zookeeper-spring-boot-starter/src/main/java/com/central/common/zookeeper/properties/ZookeeperProperty.java @@ -3,7 +3,6 @@ import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; /** * zookeeper配置 @@ -18,7 +17,6 @@ @Setter @Getter @ConfigurationProperties(prefix = "zlt.zookeeper") -@Component public class ZookeeperProperty { /** * zk连接集群,多个用逗号隔开 From a9f60ffd348cb0472c1447054b45741c46df1eb7 Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Mon, 4 Dec 2023 17:00:36 +0800 Subject: [PATCH 10/23] =?UTF-8?q?feat:=20gateway=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E9=89=B4=E6=9D=83=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 23 +- .../user/controller/SysUserController.java | 4 +- .../user/service/impl/SysUserServiceImpl.java | 22 +- .../pom.xml | 8 +- .../common/AuthClientAutoConfiguration.java | 3 +- ...ctiveAuthorizationServiceIntrospector.java | 54 +++ .../common/config/BaseSecurityConfig.java | 131 +++++++ .../central/oauth2/common/pojo/ClientDto.java | 48 +++ .../common/properties/PermitProperties.java | 14 +- .../properties/ResourceServerProperties.java | 22 ++ .../common/properties/SecurityProperties.java | 2 + .../properties/TokenStoreProperties.java | 27 -- .../impl/DefaultPermissionServiceImpl.java | 126 +++++++ .../impl/RedisOAuth2AuthorizationService.java | 322 ++++++++++++++++++ .../common/token/CustomAccessToken.java | 2 +- .../token/CustomWebAuthenticationDetails.java | 37 -- .../token/MobileAuthenticationToken.java | 84 ----- .../token/OpenIdAuthenticationToken.java | 78 ----- .../token/PasswordAuthenticationToken.java | 35 ++ ...ntUsernamePasswordAuthenticationToken.java | 37 -- .../central/oauth2/common/util/AuthUtils.java | 80 ++--- zlt-commons/zlt-common-core/pom.xml | 8 + .../common/constant/SecurityConstants.java | 28 ++ .../context/LoginUserContextHolder.java | 8 +- .../handler/CreatorDataScopeSqlHandler.java | 10 +- .../central/common/model/LoginAppUser.java | 71 ++-- .../central/common/utils/LoginUserUtils.java | 105 ++++-- .../common/filter/LoginUserFilter.java | 4 +- .../zlt-redis-spring-boot-starter/pom.xml | 5 + .../common/redis/RedisAutoConfigure.java | 1 - .../RedissonAutoConfigCustomizers.java | 24 ++ zlt-gateway/sc-gateway/pom.xml | 9 +- .../auth/Oauth2ServerAuthSuccessHandler.java | 57 ++++ .../gateway/auth/PermissionAuthManager.java | 56 +++ .../config/ResourceServerConfiguration.java | 87 +++++ .../src/main/resources/application.yml | 4 - zlt-uaa/pom.xml | 8 +- .../central/oauth/service/IClientService.java | 2 + .../oauth/service/ZltUserDetailsService.java | 3 +- .../oauth/service/impl/ClientServiceImpl.java | 34 +- .../service/impl/UserDetailServiceImpl.java | 3 +- .../service/impl/ValidateCodeServiceImpl.java | 4 +- 42 files changed, 1229 insertions(+), 461 deletions(-) create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomReactiveAuthorizationServiceIntrospector.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/BaseSecurityConfig.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java delete mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/DefaultPermissionServiceImpl.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/RedisOAuth2AuthorizationService.java delete mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/CustomWebAuthenticationDetails.java delete mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/MobileAuthenticationToken.java delete mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/OpenIdAuthenticationToken.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/PasswordAuthenticationToken.java delete mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/TenantUsernamePasswordAuthenticationToken.java create mode 100644 zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/component/RedissonAutoConfigCustomizers.java create mode 100644 zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/Oauth2ServerAuthSuccessHandler.java create mode 100644 zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/PermissionAuthManager.java create mode 100644 zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java diff --git a/pom.xml b/pom.xml index 60bb26084..afcf15787 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,6 @@ 2.3.8.RELEASE 1.1.0.RELEASE 3.24.3 - 5.7.20 3.5.4.1 3.8.1 7.2.28 @@ -47,7 +46,6 @@ 8.0.1.Final 2.7.8 5.1.0 - 2.13.4 1.10 1.12.40 2.2.5.RELEASE @@ -65,6 +63,7 @@ 10.1.11 5.2.1 1.1.1 + 11.7 @@ -213,11 +212,6 @@ ${swagger.butler.version} - - cn.hutool - hutool-all - ${hutool.version} - com.aliyun.oss aliyun-sdk-oss @@ -365,11 +359,6 @@ curator-framework ${curator.version} - - com.fasterxml.jackson.core - jackson-databind - ${jackson-databind.version} - org.springframework.security spring-security-oauth2-authorization-server @@ -422,11 +411,6 @@ guava ${guava.version} - - com.fasterxml.jackson.core - jackson-core - ${jackson-databind.version} - org.apache.httpcomponents.client5 httpclient5 @@ -439,6 +423,11 @@ pom import + + com.nimbusds + oauth2-oidc-sdk + ${oauth2-oidc-sdk.version} + diff --git a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java index fc53459f2..25b95550c 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java +++ b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java @@ -95,7 +95,7 @@ public LoginAppUser findByUsername(String username) { */ @GetMapping(value = "/users-anon/mobile", params = "mobile") @Operation(summary = "根据手机号查询用户") - public SysUser findByMobile(String mobile) { + public LoginAppUser findByMobile(String mobile) { return appUserService.findByMobile(mobile); } @@ -106,7 +106,7 @@ public SysUser findByMobile(String mobile) { */ @GetMapping(value = "/users-anon/openId", params = "openId") @Operation(summary = "根据OpenId查询用户") - public SysUser findByOpenId(String openId) { + public LoginAppUser findByOpenId(String openId) { return appUserService.findByOpenId(openId); } diff --git a/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java b/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java index 7d98f15b4..10d8966dd 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java +++ b/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java @@ -21,6 +21,8 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -73,24 +75,26 @@ public LoginAppUser findByMobile(String username) { @Override public LoginAppUser getLoginAppUser(SysUser sysUser) { if (sysUser != null) { - LoginAppUser loginAppUser = new LoginAppUser(); - BeanUtils.copyProperties(sysUser, loginAppUser); - List sysRoles = roleUserService.findRolesByUserId(sysUser.getId()); - // 设置角色 - loginAppUser.setRoles(sysRoles); + Collection authorities = new HashSet<>(); + if (sysRoles != null) { + sysRoles.forEach(role -> authorities.add(new SimpleGrantedAuthority(role.getCode()))); + } + Set permissions = null; if (!CollectionUtils.isEmpty(sysRoles)) { Set roleIds = sysRoles.stream().map(SuperEntity::getId).collect(Collectors.toSet()); List menus = roleMenuMapper.findMenusByRoleIds(roleIds, CommonConstant.PERMISSION); if (!CollectionUtils.isEmpty(menus)) { - Set permissions = menus.stream().map(p -> p.getPath()) + permissions = menus.stream().map(p -> p.getPath()) .collect(Collectors.toSet()); - // 设置权限集合 - loginAppUser.setPermissions(permissions); } } - return loginAppUser; + return new LoginAppUser(sysUser.getId() + , sysUser.getUsername(), sysUser.getPassword() + , sysUser.getMobile(), permissions + , sysUser.getEnabled(), true, true, true + , authorities); } return null; } diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml b/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml index f2fedfc59..204e686cd 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml @@ -13,8 +13,12 @@ 认证客户端通用组件 - org.springframework.security - spring-security-oauth2-authorization-server + org.springframework.boot + spring-boot-starter-oauth2-authorization-server + + + com.nimbusds + oauth2-oidc-sdk com.zlt diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/AuthClientAutoConfiguration.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/AuthClientAutoConfiguration.java index fa7884449..45d1a37d3 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/AuthClientAutoConfiguration.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/AuthClientAutoConfiguration.java @@ -1,7 +1,6 @@ package com.central.oauth2.common; import com.central.oauth2.common.properties.SecurityProperties; -import com.central.oauth2.common.properties.TokenStoreProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.ComponentScan; @@ -15,7 +14,7 @@ * Blog: http://zlt2000.gitee.io * Github: https://github.com/zlt2000 */ -@EnableConfigurationProperties({SecurityProperties.class, TokenStoreProperties.class}) +@EnableConfigurationProperties({SecurityProperties.class}) @ComponentScan public class AuthClientAutoConfiguration { } diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomReactiveAuthorizationServiceIntrospector.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomReactiveAuthorizationServiceIntrospector.java new file mode 100644 index 000000000..61667c4f5 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomReactiveAuthorizationServiceIntrospector.java @@ -0,0 +1,54 @@ +package com.central.oauth2.common.component; + +import com.central.common.constant.SecurityConstants; +import com.central.oauth2.common.util.AuthUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; +import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; +import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal; +import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException; +import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector; +import reactor.core.publisher.Mono; + +import java.security.Principal; +import java.util.*; + +/** + * @author zlt + * @version 1.0 + * @date 2023/12/4 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Slf4j +public class CustomReactiveAuthorizationServiceIntrospector implements ReactiveOpaqueTokenIntrospector { + @Override + public Mono introspect(String accessTokenValue) { + return Mono.just(accessTokenValue) + .map(AuthUtils::checkAccessTokenToAuth) + .map(this::convertClaimsSet) + .onErrorMap((e) -> !(e instanceof OAuth2IntrospectionException), this::onError); + } + + private OAuth2AuthenticatedPrincipal convertClaimsSet(OAuth2Authorization authorization) { + Map claims = new HashMap<>(); + Collection authorities = new ArrayList<>(); + + claims.put(SecurityConstants.CLIENT_ID, authorization.getRegisteredClientId()); + claims.putAll(authorization.getAttributes()); + + Authentication authentication = (Authentication)authorization.getAttributes().get(Principal.class.getName()); + if (authentication != null) { + authorities.addAll(authentication.getAuthorities()); + } + + return new OAuth2IntrospectionAuthenticatedPrincipal(authorization.getPrincipalName(), claims, authorities); + } + + private OAuth2IntrospectionException onError(Throwable ex) { + return new OAuth2IntrospectionException(ex.getMessage(), ex); + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/BaseSecurityConfig.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/BaseSecurityConfig.java new file mode 100644 index 000000000..305cb4c0e --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/BaseSecurityConfig.java @@ -0,0 +1,131 @@ +package com.central.oauth2.common.config; + +import cn.hutool.core.util.StrUtil; +import com.central.common.constant.SecurityConstants; +import com.central.common.utils.ResponseUtil; +import com.central.common.utils.WebfluxResponseUtil; +import com.central.oauth2.common.properties.SecurityProperties; +import com.central.oauth2.common.service.impl.RedisOAuth2AuthorizationService; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nimbusds.jose.jwk.JWKSet; +import com.nimbusds.jose.jwk.RSAKey; +import com.nimbusds.jose.jwk.source.ImmutableJWKSet; +import com.nimbusds.jose.jwk.source.JWKSource; +import com.nimbusds.jose.proc.SecurityContext; +import jakarta.servlet.http.HttpServletRequest; +import org.redisson.api.RBucket; +import org.redisson.api.RedissonClient; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpStatus; +import org.springframework.security.oauth2.jwt.JwtDecoder; +import org.springframework.security.oauth2.jwt.JwtEncoder; +import org.springframework.security.oauth2.jwt.NimbusJwtEncoder; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.server.ServerAuthenticationEntryPoint; +import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler; +import org.springframework.web.server.ServerWebExchange; + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.text.ParseException; +import java.util.UUID; + + +/** + * @author zlt + * @date: 2023/11/25 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class BaseSecurityConfig { + @Bean + public OAuth2AuthorizationService oAuth2AuthorizationService(SecurityProperties securityProperties, RedissonClient redisson) { + return new RedisOAuth2AuthorizationService(securityProperties, redisson); + } + + /** + * 鉴权错误处理 + */ + @Bean + public AuthenticationEntryPoint authenticationEntryPoint(ObjectMapper objectMapper) { + return (request, response, authException) -> ResponseUtil.responseFailed(objectMapper, response, authException.getMessage()); + } + @Bean + public ServerAuthenticationEntryPoint serverAuthenticationEntryPoint() { + return (exchange, e) -> WebfluxResponseUtil.responseFailed(exchange, HttpStatus.UNAUTHORIZED.value(), e.getMessage()); + } + + /** + * 越权错误处理 + */ + @Bean + public AccessDeniedHandler oAuth2AccessDeniedHandler(ObjectMapper objectMapper) { + return (request, response, authException) -> ResponseUtil.responseFailed(objectMapper, response, authException.getMessage()); + } + @Bean + public ServerAccessDeniedHandler serverAccessDeniedHandler() { + return (exchange, e) -> WebfluxResponseUtil.responseFailed(exchange, HttpStatus.FORBIDDEN.value(), e.getMessage()); + } + + /** + * 配置jwk源,使用非对称加密,公开用于检索匹配指定选择器的JWK的方法 + */ + @Bean + public JWKSource jwkSource(RedissonClient redisson) throws ParseException { + RBucket rBucket = redisson.getBucket(SecurityConstants.AUTHORIZATION_JWS_PREFIX_KEY); + String jwkSetCache = rBucket.get(); + JWKSet jwkSet; + // 多个服务共用同一个 jwkSource 对象 + if (StrUtil.isEmpty(jwkSetCache)) { + KeyPair keyPair = generateRsaKey(); + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); + RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); + RSAKey rsaKey = new RSAKey.Builder(publicKey) + .privateKey(privateKey) + .keyID(UUID.randomUUID().toString()) + .build(); + jwkSet = new JWKSet(rsaKey); + String jwkSetString = jwkSet.toString(Boolean.FALSE); + // 缓存 + boolean success = rBucket.setIfAbsent(jwkSetString); + if (!success) {// 防止同时启动服务时创建了多个jwks + jwkSetCache = rBucket.get(); + jwkSet = JWKSet.parse(jwkSetCache); + } + } else { + // 解析存储的jws + jwkSet = JWKSet.parse(jwkSetCache); + } + return new ImmutableJWKSet<>(jwkSet); + } + + private static KeyPair generateRsaKey() { + KeyPair keyPair; + try { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(2048); + keyPair = keyPairGenerator.generateKeyPair(); + } + catch (Exception ex) { + throw new IllegalStateException(ex); + } + return keyPair; + } + + @Bean + public JwtDecoder jwtDecoder(JWKSource jwkSource) { + return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource); + } + + @Bean + public JwtEncoder jwtEncoder(JWKSource jwkSource) { + return new NimbusJwtEncoder(jwkSource); + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java new file mode 100644 index 000000000..22fb003fb --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java @@ -0,0 +1,48 @@ +package com.central.oauth2.common.pojo; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author zlt + * @version 1.0 + * @date 2023/12/2 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Data +public class ClientDto implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + private String clientId; + /** + * 应用名称 + */ + private String clientName; + private String resourceIds = ""; + private String clientSecret; + private String clientSecretStr; + private String scope = "all"; + private String authorizedGrantTypes = "authorization_code,password,refresh_token,client_credentials"; + private String webServerRedirectUri; + private String authorities = ""; + + private Integer accessTokenValiditySeconds = 18000; + + private Integer refreshTokenValiditySeconds = 28800; + private String additionalInformation = "{}"; + private String autoapprove = "true"; + /** + * 是否支持id_token + */ + private Boolean supportIdToken = true; + /** + * id_token有效时间(s) + */ + private Integer idTokenValiditySeconds = 60; + + private Long creatorId; +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/PermitProperties.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/PermitProperties.java index 7c5e45913..c861a3092 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/PermitProperties.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/PermitProperties.java @@ -23,15 +23,11 @@ public class PermitProperties { * 监控中心和swagger需要访问的url */ private static final String[] ENDPOINTS = { - "/oauth/**", - "/actuator/**", - "/*/v2/api-docs", - "/swagger/api-docs", - "/swagger-ui.html", - "/doc.html", - "/swagger-resources/**", - "/webjars/**", - "/druid/**" + "/login.html", "/validata/code/**", + "/v3/api-docs/**", "/*/v3/api-docs/**", + "/doc.html", "/swagger-ui.html", "/swagger-ui/**", + "/actuator/**", "/webjars/**", "/druid/**", + "/css/**", "/js/**", "/images/**", "/favicon.ico", "/error", }; /** diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java new file mode 100644 index 000000000..dcab6931a --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java @@ -0,0 +1,22 @@ +package com.central.oauth2.common.properties; + +import lombok.Getter; +import lombok.Setter; + +/** + * 资源服务器配置 + * + * @author: zlt + * @date: 2023/11/26 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Setter +@Getter +public class ResourceServerProperties { + /** + * token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt)) + */ + private String tokenFormat = "reference"; +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java index c23adea33..7947eaf97 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/SecurityProperties.java @@ -23,4 +23,6 @@ public class SecurityProperties { private PermitProperties ignore = new PermitProperties(); private ValidateCodeProperties code = new ValidateCodeProperties(); + + private ResourceServerProperties resourceServer = new ResourceServerProperties(); } diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java deleted file mode 100644 index d49a6c4ca..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/TokenStoreProperties.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.central.oauth2.common.properties; - -import lombok.Getter; -import lombok.Setter; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; - -/** - * Token配置 - * - * @author zlt - * @version 1.0 - * @date 2021/5/19 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Setter -@Getter -@ConfigurationProperties(prefix = "zlt.oauth2.token.store") -@RefreshScope -public class TokenStoreProperties { - /** - * token存储类型(redis/db/authJwt/resJwt) - */ - private String type = "redis"; -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/DefaultPermissionServiceImpl.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/DefaultPermissionServiceImpl.java new file mode 100644 index 000000000..36435ef16 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/DefaultPermissionServiceImpl.java @@ -0,0 +1,126 @@ +package com.central.oauth2.common.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.central.common.constant.CommonConstant; +import com.central.common.constant.SecurityConstants; +import com.central.common.context.TenantContextHolder; +import com.central.common.model.LoginAppUser; +import com.central.common.model.SysMenu; +import com.central.oauth2.common.properties.SecurityProperties; +import com.central.oauth2.common.util.AuthUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal; +import org.springframework.util.AntPathMatcher; + +import java.security.Principal; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 请求权限判断service + * + * @author zlt + * @date 2018/10/28 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Slf4j +public abstract class DefaultPermissionServiceImpl { + + @Autowired + private SecurityProperties securityProperties; + + private final AntPathMatcher antPathMatcher = new AntPathMatcher(); + + /** + * 查询当前用户拥有的资源权限 + * @param roleCodes 角色code列表,多个以','隔开 + * @return + */ + public abstract List findMenuByRoleCodes(String roleCodes); + + public boolean hasPermission(Authentication authentication, String requestMethod, String requestURI) { + // 前端跨域OPTIONS请求预检放行 也可通过前端配置代理实现 + if (HttpMethod.OPTIONS.name().equalsIgnoreCase(requestMethod)) { + return true; + } + if (!(authentication instanceof AnonymousAuthenticationToken)) { + //判断是否开启url权限验证 + if (!securityProperties.getAuth().getUrlPermission().getEnable()) { + return true; + } + + OAuth2IntrospectionAuthenticatedPrincipal authenticatedPrincipal = (OAuth2IntrospectionAuthenticatedPrincipal)authentication.getPrincipal(); + //超级管理员admin不需认证 + String username = authenticatedPrincipal.getName(); + if (CommonConstant.ADMIN_USER_NAME.equals(username)) { + return true; + } + Map claims = authenticatedPrincipal.getAttributes(); + String clientId = (String)claims.get(SecurityConstants.CLIENT_ID); + //判断应用黑白名单 + if (!isNeedAuth(clientId)) { + return true; + } + + //判断不进行url权限认证的api,所有已登录用户都能访问的url + for (String path : securityProperties.getAuth().getUrlPermission().getIgnoreUrls()) { + if (antPathMatcher.match(path, requestURI)) { + return true; + } + } + + Collection grantedAuthorityList = (Collection) authentication.getAuthorities(); + if (CollectionUtil.isEmpty(grantedAuthorityList)) { + log.warn("角色列表为空:{}", authentication.getPrincipal()); + return false; + } + + //保存租户信息 + TenantContextHolder.setTenant(clientId); + + String roleCodes = grantedAuthorityList.stream().map(SimpleGrantedAuthority::getAuthority).collect(Collectors.joining(", ")); + List menuList = findMenuByRoleCodes(roleCodes); + for (SysMenu menu : menuList) { + if (StringUtils.isNotEmpty(menu.getUrl()) && antPathMatcher.match(menu.getUrl(), requestURI)) { + if (StrUtil.isNotEmpty(menu.getPathMethod())) { + return requestMethod.equalsIgnoreCase(menu.getPathMethod()); + } else { + return true; + } + } + } + } + + return false; + } + + /** + * 判断应用是否满足白名单和黑名单的过滤逻辑 + * @param clientId 应用id + * @return true(需要认证),false(不需要认证) + */ + private boolean isNeedAuth(String clientId) { + boolean result = true; + //白名单 + List includeClientIds = securityProperties.getAuth().getUrlPermission().getIncludeClientIds(); + //黑名单 + List exclusiveClientIds = securityProperties.getAuth().getUrlPermission().getExclusiveClientIds(); + if (includeClientIds.size() > 0) { + result = includeClientIds.contains(clientId); + } else if(exclusiveClientIds.size() > 0) { + result = !exclusiveClientIds.contains(clientId); + } + return result; + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/RedisOAuth2AuthorizationService.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/RedisOAuth2AuthorizationService.java new file mode 100644 index 000000000..666baeece --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/RedisOAuth2AuthorizationService.java @@ -0,0 +1,322 @@ +package com.central.oauth2.common.service.impl; + +import com.central.common.constant.SecurityConstants; +import com.central.oauth2.common.pojo.ClientDto; +import com.central.oauth2.common.properties.SecurityProperties; +import com.central.oauth2.common.token.CustomAccessToken; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.redisson.api.RBucket; +import org.redisson.api.RList; +import org.redisson.api.RedissonClient; +import org.redisson.codec.SerializationCodec; +import org.springframework.lang.Nullable; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.core.OAuth2RefreshToken; +import org.springframework.security.oauth2.core.OAuth2Token; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; +import org.springframework.util.Assert; + +import java.lang.reflect.Field; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.*; + +/** + * @author: zlt + * @date: 2023/11/9 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Slf4j +@RequiredArgsConstructor +public class RedisOAuth2AuthorizationService implements OAuth2AuthorizationService { + private final static SerializationCodec AUTH_CODEC = new SerializationCodec(); + private final static Long TIMEOUT = 10L; + + private static final String AUTHORIZATION = "token"; + + private final SecurityProperties securityProperties; + + private final RedissonClient redisson; + + @Override + public void save(OAuth2Authorization authorization) { + if (isState(authorization)) { + String token = authorization.getAttribute("state"); + this.redisBucketSet(OAuth2ParameterNames.STATE, token, authorization, Duration.ofMinutes(TIMEOUT)); + } + + if (isCode(authorization)) { + OAuth2AuthorizationCode authorizationCode = authorization.getToken(OAuth2AuthorizationCode.class).getToken(); + Duration duration = this.getExpireSeconds(authorizationCode); + this.redisBucketSet(OAuth2ParameterNames.CODE, authorizationCode.getTokenValue(), authorization, duration); + } + + if (isRefreshToken(authorization)) { + OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken(); + Duration duration = this.getExpireSeconds(refreshToken); + this.redisBucketSet(OAuth2ParameterNames.REFRESH_TOKEN, refreshToken.getTokenValue(), authorization, duration); + } + + if (isAccessToken(authorization)) { + Duration duration = this.saveAccessToken(authorization); + OAuth2AccessToken accessToken = authorization.getAccessToken().getToken(); + // 应用id集合 + this.redisListAdd(this.getClientIdListKey(authorization), accessToken.getTokenValue(), duration); + // 应用id + 登录名 集合 + this.redisListAdd(this.getUnameListKey(authorization), accessToken.getTokenValue(), duration); + } + } + + private Duration saveAccessToken(OAuth2Authorization authorization) { + OAuth2AccessToken accessToken = authorization.getAccessToken().getToken(); + Duration duration = this.getExpireSeconds(accessToken); + this.redisBucketSet(OAuth2ParameterNames.ACCESS_TOKEN, accessToken.getTokenValue(), authorization, duration); + return duration; + } + + @Override + public void remove(OAuth2Authorization authorization) { + Assert.notNull(authorization, "authorization cannot be null"); + + List keys = new ArrayList<>(); + if (isState(authorization)) { + String token = authorization.getAttribute("state"); + keys.add(buildKey(OAuth2ParameterNames.STATE, token)); + } + + if (isCode(authorization)) { + OAuth2Authorization.Token authorizationCode = authorization + .getToken(OAuth2AuthorizationCode.class); + OAuth2AuthorizationCode authorizationCodeToken = authorizationCode.getToken(); + keys.add(buildKey(OAuth2ParameterNames.CODE, authorizationCodeToken.getTokenValue())); + } + + if (isRefreshToken(authorization)) { + OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken(); + keys.add(buildKey(OAuth2ParameterNames.REFRESH_TOKEN, refreshToken.getTokenValue())); + } + + if (isAccessToken(authorization)) { + OAuth2AccessToken accessToken = authorization.getAccessToken().getToken(); + keys.add(buildKey(OAuth2ParameterNames.ACCESS_TOKEN, accessToken.getTokenValue())); + } + redisson.getKeys().delete(keys.toArray(String[]::new)); + this.removeList(authorization); + } + + @Override + @Nullable + public OAuth2Authorization findById(String id) { + return this.findByToken(id, OAuth2TokenType.ACCESS_TOKEN); + } + + @Override + @Nullable + public OAuth2Authorization findByToken(String token, @Nullable OAuth2TokenType tokenType) { + Assert.hasText(token, "token cannot be empty"); + if (tokenType == null) { + tokenType = OAuth2TokenType.ACCESS_TOKEN; + } + OAuth2Authorization authorization = this.redisBucketGet(tokenType.getValue(), token); + + boolean isRenew = securityProperties.getAuth().getRenew().getEnable(); + if (isRenew && tokenType.equals(OAuth2TokenType.ACCESS_TOKEN) && authorization != null) { + this.renew(authorization); + } + + return authorization; + } + + public void remove(String accessToken) { + OAuth2Authorization oAuth2Authorization = this.findById(accessToken); + this.remove(oAuth2Authorization); + } + + public List findTokensByClientId(String clientId) { + RList rList = redisson.getList(this.getClientIdListKey(clientId)); + return rList.readAll(); + } + + public List findTokensByClientIdAndUserName(String clientId, String username) { + RList rList = redisson.getList(this.getUnameListKey(clientId, username)); + return rList.readAll(); + } + + private String buildKey(String type, String id) { + return String.format("%s::%s::%s", AUTHORIZATION, type, id); + } + + private static boolean isState(OAuth2Authorization authorization) { + return Objects.nonNull(authorization.getAttribute("state")); + } + + private static boolean isCode(OAuth2Authorization authorization) { + OAuth2Authorization.Token authorizationCode = authorization + .getToken(OAuth2AuthorizationCode.class); + return Objects.nonNull(authorizationCode); + } + + private static boolean isRefreshToken(OAuth2Authorization authorization) { + return Objects.nonNull(authorization.getRefreshToken()); + } + + private static boolean isAccessToken(OAuth2Authorization authorization) { + return Objects.nonNull(authorization.getAccessToken()); + } + + /** + * 续签 access_token + */ + private void renew(OAuth2Authorization authorization) { + // 判断当前应用是否需要自动续签 + if (checkRenewClientId(authorization.getRegisteredClientId())) { + // 获取过期时长 + long validitySeconds = getAccessTokenValiditySeconds(authorization.getRegisteredClientId()); + if (validitySeconds > 0) { + OAuth2AccessToken accessToken = authorization.getAccessToken().getToken(); + long expiresIn = ChronoUnit.SECONDS.between(Instant.now(), accessToken.getExpiresAt()); + double expiresRatio = expiresIn / (double) validitySeconds; + // 判断是否需要续签,当前剩余时间小于过期时长的50%则续签 + if (expiresRatio <= securityProperties.getAuth().getRenew().getTimeRatio()) { + // 更新AccessToken过期时间 + updateAccessTokenExpiresAt(authorization, validitySeconds); + } + } + } + } + + /** + * 判断应用自动续签是否满足白名单和黑名单的过滤逻辑 + * + * @param clientId 应用id + * @return 是否满足 + */ + private boolean checkRenewClientId(String clientId) { + boolean result = true; + //白名单 + List includeClientIds = securityProperties.getAuth().getRenew().getIncludeClientIds(); + //黑名单 + List exclusiveClientIds = securityProperties.getAuth().getRenew().getExclusiveClientIds(); + if (includeClientIds.size() > 0) { + result = includeClientIds.contains(clientId); + } else if (exclusiveClientIds.size() > 0) { + result = !exclusiveClientIds.contains(clientId); + } + return result; + } + + /** + * 获取token的总有效时长 + * + * @param clientId 应用id + */ + private long getAccessTokenValiditySeconds(String clientId) { + ClientDto clientDetails = (ClientDto)redisson.getBucket(clientRedisKey(clientId)).get(); + if (clientDetails != null) { + return clientDetails.getAccessTokenValiditySeconds(); + } + + //返回默认值 + return SecurityConstants.ACCESS_TOKEN_VALIDITY_SECONDS; + } + + private String clientRedisKey(String clientId) { + return SecurityConstants.CACHE_CLIENT_KEY + ":" + clientId; + } + + /** + * 更新 access_token 的过期时间 + */ + @SuppressWarnings("unchecked") + private void updateAccessTokenExpiresAt(OAuth2Authorization authorization, long validitySeconds) { + try { + Class authClazz = authorization.getClass(); + Field tokensField = authClazz.getDeclaredField("tokens"); + tokensField.setAccessible(true); + + Map, OAuth2Authorization.Token> tokens = (Map, OAuth2Authorization.Token>) tokensField.get(authorization); + OAuth2Authorization.Token newToken = this.genateNewAccessToken(authorization.getAccessToken(), validitySeconds); + Map, OAuth2Authorization.Token> newTokens = new HashMap<>(tokens); + newTokens.put(OAuth2AccessToken.class, newToken); + tokensField.set(authorization, Collections.unmodifiableMap(newTokens)); + this.saveAccessToken(authorization); + // 更新集合中的过期时间 + this.updateListExpiresAt(this.getClientIdListKey(authorization), Duration.ofSeconds(validitySeconds)); + this.updateListExpiresAt(this.getUnameListKey(authorization), Duration.ofSeconds(validitySeconds)); + } catch (Exception e) { + log.error("updateAccessTokenExpiresAt-error", e); + throw new RuntimeException(e); + } + } + + + private void removeList(OAuth2Authorization authorization) { + this.redisListDelete(this.getClientIdListKey(authorization), authorization.getId()); + this.redisListDelete(this.getUnameListKey(authorization), authorization.getId()); + } + + private void updateListExpiresAt(String key, Duration duration) { + redisson.getList(key).expire(duration); + } + + private OAuth2Authorization.Token genateNewAccessToken(OAuth2Authorization.Token oldToken, long validitySeconds) { + Instant issuedAt = Instant.now(); + Instant expiresAt = issuedAt.plus(Duration.ofSeconds(validitySeconds)); + + OAuth2AccessToken oldAccessToken = oldToken.getToken(); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + oldAccessToken.getTokenValue(), issuedAt, + expiresAt, oldAccessToken.getScopes()); + return new CustomAccessToken(accessToken, oldToken.getMetadata()); + } + + private Duration getExpireSeconds(OAuth2Token oAuth2Token) { + return Duration.ofSeconds( + ChronoUnit.SECONDS.between(oAuth2Token.getIssuedAt(), oAuth2Token.getExpiresAt())); + } + + private RBucket redisBucketSet(String type, String id, OAuth2Authorization value, Duration duration) { + RBucket rBucket = redisson.getBucket(buildKey(type, id), AUTH_CODEC); + rBucket.set(value, duration); + + return rBucket; + } + + private String getClientIdListKey(OAuth2Authorization authorization) { + return this.getClientIdListKey(authorization.getRegisteredClientId()); + } + private String getClientIdListKey(String clientId) { + return buildKey(SecurityConstants.REDIS_CLIENT_ID_TO_ACCESS, clientId); + } + private String getUnameListKey(OAuth2Authorization authorization) { + return this.getUnameListKey(authorization.getRegisteredClientId(), authorization.getPrincipalName()); + } + private String getUnameListKey(String clientId, String username) { + return buildKey(SecurityConstants.REDIS_UNAME_TO_ACCESS, clientId + "::" + username); + } + + private OAuth2Authorization redisBucketGet(String type, String id) { + return (OAuth2Authorization)redisson.getBucket(buildKey(type, id), AUTH_CODEC).get(); + } + + private RList redisListAdd(String key, String value, Duration duration) { + RList rList = redisson.getList(key); + rList.add(value); + rList.expire(duration); + return rList; + } + + private RList redisListDelete(String key, String value) { + RList rList = redisson.getList(key); + rList.remove(value); + return rList; + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/CustomAccessToken.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/CustomAccessToken.java index 0c53f6b24..4929d9ec6 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/CustomAccessToken.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/CustomAccessToken.java @@ -13,7 +13,7 @@ * Github: https://github.com/zlt2000 */ public class CustomAccessToken extends OAuth2Authorization.Token { - protected CustomAccessToken(OAuth2AccessToken token, Map metadata) { + public CustomAccessToken(OAuth2AccessToken token, Map metadata) { super(token, metadata); } } diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/CustomWebAuthenticationDetails.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/CustomWebAuthenticationDetails.java deleted file mode 100644 index 4713bcdd4..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/CustomWebAuthenticationDetails.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.central.oauth2.common.token; - -import lombok.Getter; - -import java.io.Serializable; - -/** - * 表单登录的认证信息对象 - * - * @author zlt - * @version 1.0 - * @date 2021/7/24 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Getter -public class CustomWebAuthenticationDetails implements Serializable { - private static final long serialVersionUID = - 1; - - private final String accountType; - private final String remoteAddress; - private final String sessionId; - - public CustomWebAuthenticationDetails(String remoteAddress, String sessionId, String accountType) { - this.remoteAddress = remoteAddress; - this.sessionId = sessionId; - this.accountType = accountType; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(super.toString()).append("; accountType: ").append(this.getAccountType()); - return sb.toString(); - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/MobileAuthenticationToken.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/MobileAuthenticationToken.java deleted file mode 100644 index 03835f4d5..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/MobileAuthenticationToken.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * - */ -package com.central.oauth2.common.token; - -import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.SpringSecurityCoreVersion; - -import java.util.Collection; - -/** - * @author zlt - */ -public class MobileAuthenticationToken extends AbstractAuthenticationToken { - - private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; - - // ~ Instance fields - // ================================================================================================ - - private final Object principal; - private Object credentials; - - // ~ Constructors - // =================================================================================================== - - /** - * This constructor can be safely used by any code that wishes to create a - * UsernamePasswordAuthenticationToken, as the {@link #isAuthenticated()} - * will return false. - * - */ - public MobileAuthenticationToken(String mobile, String password) { - super(null); - this.principal = mobile; - this.credentials = password; - setAuthenticated(false); - } - - /** - * This constructor should only be used by AuthenticationManager or - * AuthenticationProvider implementations that are satisfied with - * producing a trusted (i.e. {@link #isAuthenticated()} = true) - * authentication token. - * - * @param principal - * @param authorities - */ - public MobileAuthenticationToken(Object principal, Object credentials, - Collection authorities) { - super(authorities); - this.principal = principal; - this.credentials = credentials; - super.setAuthenticated(true); - } - - // ~ Methods - // ======================================================================================================== - - @Override - public Object getCredentials() { - return this.credentials; - } - - @Override - public Object getPrincipal() { - return this.principal; - } - - @Override - public void setAuthenticated(boolean isAuthenticated) { - if (isAuthenticated) { - throw new IllegalArgumentException( - "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); - } - super.setAuthenticated(false); - } - - @Override - public void eraseCredentials() { - super.eraseCredentials(); - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/OpenIdAuthenticationToken.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/OpenIdAuthenticationToken.java deleted file mode 100644 index 04395939a..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/OpenIdAuthenticationToken.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.central.oauth2.common.token; - -import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.SpringSecurityCoreVersion; - -import java.util.Collection; - -/** - * @author zlt - */ -public class OpenIdAuthenticationToken extends AbstractAuthenticationToken { - - private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; - - // ~ Instance fields - // ================================================================================================ - - private final Object principal; - - // ~ Constructors - // =================================================================================================== - - /** - * This constructor can be safely used by any code that wishes to create a - * UsernamePasswordAuthenticationToken, as the {@link #isAuthenticated()} - * will return false. - * - */ - public OpenIdAuthenticationToken(String openId) { - super(null); - this.principal = openId; - setAuthenticated(false); - } - - /** - * This constructor should only be used by AuthenticationManager or - * AuthenticationProvider implementations that are satisfied with - * producing a trusted (i.e. {@link #isAuthenticated()} = true) - * authentication token. - * - * @param principal - * @param authorities - */ - public OpenIdAuthenticationToken(Object principal, - Collection authorities) { - super(authorities); - this.principal = principal; - super.setAuthenticated(true); - } - - // ~ Methods - // ======================================================================================================== - - @Override - public Object getCredentials() { - return null; - } - - @Override - public Object getPrincipal() { - return this.principal; - } - - @Override - public void setAuthenticated(boolean isAuthenticated) { - if (isAuthenticated) { - throw new IllegalArgumentException( - "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); - } - super.setAuthenticated(false); - } - - @Override - public void eraseCredentials() { - super.eraseCredentials(); - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/PasswordAuthenticationToken.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/PasswordAuthenticationToken.java new file mode 100644 index 000000000..31a0efed3 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/PasswordAuthenticationToken.java @@ -0,0 +1,35 @@ +package com.central.oauth2.common.token; + +import lombok.Getter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.AuthorizationGrantType; + +import java.util.Collection; + +/** + * @author: zlt + * @date: 2023/11/18 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Getter +public class PasswordAuthenticationToken extends BaseAuthenticationToken { + public static final AuthorizationGrantType GRANT_TYPE = new AuthorizationGrantType("password"); + private final Object principal; + private final String credentials; + + public PasswordAuthenticationToken(String username, String password) { + super(GRANT_TYPE); + this.principal = username; + this.credentials = password; + super.setAuthenticated(true); + } + + public PasswordAuthenticationToken(UserDetails user, String password, Collection authorities) { + super(authorities); + this.principal = user; + this.credentials = password; + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/TenantUsernamePasswordAuthenticationToken.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/TenantUsernamePasswordAuthenticationToken.java deleted file mode 100644 index d1907825f..000000000 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/TenantUsernamePasswordAuthenticationToken.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.central.oauth2.common.token; - -import lombok.Getter; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.GrantedAuthority; - -import java.util.Collection; - -/** - * 增加租户id,解决不同租户单点登录时角色没变化 - * - * @author zlt - * @date 2020/6/10 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class TenantUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken { - private static final long serialVersionUID = -5638287853803374687L; - - /** - * 租户id - */ - @Getter - private final String clientId; - - public TenantUsernamePasswordAuthenticationToken(Object principal, Object credentials, String clientId) { - super(principal, credentials); - this.clientId = clientId; - } - - public TenantUsernamePasswordAuthenticationToken(Object principal, Object credentials, - Collection authorities, String clientId) { - super(principal, credentials, authorities); - this.clientId = clientId; - } -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java index 4ef3d8a1e..fed532c89 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java @@ -3,14 +3,12 @@ import cn.hutool.extra.spring.SpringUtil; import com.central.common.constant.CommonConstant; import com.central.common.constant.SecurityConstants; -import com.central.common.context.LoginUserContextHolder; -import com.central.common.model.SysUser; +import com.central.common.model.LoginAppUser; +import com.central.common.utils.LoginUserUtils; import com.central.oauth2.common.exception.CustomOAuth2AuthenticationException; import com.central.oauth2.common.token.BaseAuthenticationToken; import lombok.extern.slf4j.Slf4j; -import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; @@ -18,8 +16,10 @@ import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; +import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException; import java.nio.charset.StandardCharsets; +import java.security.Principal; import java.util.*; /** @@ -79,36 +79,33 @@ private static String extractHeaderToken(HttpServletRequest request) { /** * 校验accessToken */ - public static SysUser checkAccessToken(HttpServletRequest request) { + public static LoginAppUser checkAccessToken(HttpServletRequest request) { String accessToken = extractToken(request); return checkAccessToken(accessToken); } - public static SysUser checkAccessToken(String accessTokenValue) { - OAuth2AuthorizationService tokenService = SpringUtil.getBean(OAuth2AuthorizationService.class); - OAuth2Authorization oAuth2Authorization = tokenService.findByToken(accessTokenValue, OAuth2TokenType.ACCESS_TOKEN); - if (oAuth2Authorization == null || oAuth2Authorization.getAccessToken() == null) { - throw new CustomOAuth2AuthenticationException("Invalid access token: " + accessTokenValue); - } else if (oAuth2Authorization.getAccessToken().isExpired()) { - tokenService.remove(oAuth2Authorization); - throw new CustomOAuth2AuthenticationException("Access token expired: " + accessTokenValue); + public static LoginAppUser checkAccessToken(String accessTokenValue) { + OAuth2Authorization authorization = checkAccessTokenToAuth(accessTokenValue); + Authentication authentication = (Authentication)authorization.getAttributes().get(Principal.class.getName()); + if (authentication == null) { + throw new OAuth2IntrospectionException("Invalid access token: " + accessTokenValue); } - /*OAuth2Authentication result = tokenStore.readAuthentication(accessToken); - if (result == null) { - throw new OAuth2AuthenticationException("Invalid access token: " + accessTokenValue); - }*/ - // TODO 如何生成 Authentication 对象 - return setContext(null); + return LoginUserUtils.setContext(authentication); } - /** - * 用户信息赋值 context 对象 - */ - public static SysUser setContext(Authentication authentication) { - SecurityContextHolder.getContext().setAuthentication(authentication); - SysUser user = getUser(authentication); - LoginUserContextHolder.setUser(user); - return user; + public static OAuth2Authorization checkAccessTokenToAuth(String accessTokenValue) { + if (accessTokenValue == null) { + throw new OAuth2IntrospectionException("Invalid access token: " + null); + } + OAuth2AuthorizationService authorizationService = SpringUtil.getBean(OAuth2AuthorizationService.class); + OAuth2Authorization authorization = authorizationService.findByToken(accessTokenValue, OAuth2TokenType.ACCESS_TOKEN); + if (authorization == null || authorization.getAccessToken() == null) { + throw new OAuth2IntrospectionException("Invalid access token: " + accessTokenValue); + } else if (authorization.getAccessToken().isExpired()) { + authorizationService.remove(authorization); + throw new OAuth2IntrospectionException("Access token expired: " + accessTokenValue); + } + return authorization; } /** @@ -147,35 +144,6 @@ public static String[] extractHeaderClient(String header) { return clientArr; } - /** - * 获取登陆的用户名 - */ - public static String getUsername(Authentication authentication) { - Object principal = authentication.getPrincipal(); - String username = null; - if (principal instanceof SysUser) { - username = ((SysUser) principal).getUsername(); - } else if (principal instanceof String) { - username = (String) principal; - } - return username; - } - - /** - * 获取登陆的用户对象 - */ - public static SysUser getUser(Authentication authentication) { - SysUser user = null; - if (authentication != null && !(authentication instanceof AnonymousAuthenticationToken)) { - Object principal = authentication.getPrincipal(); - //客户端模式只返回一个clientId - if (principal instanceof SysUser) { - user = (SysUser)principal; - } - } - return user; - } - /** * 获取登陆的帐户类型 */ diff --git a/zlt-commons/zlt-common-core/pom.xml b/zlt-commons/zlt-common-core/pom.xml index 746451ba1..f8d91b5bc 100644 --- a/zlt-commons/zlt-common-core/pom.xml +++ b/zlt-commons/zlt-common-core/pom.xml @@ -93,5 +93,13 @@ com.alibaba transmittable-thread-local + + org.springframework.security + spring-security-oauth2-core + + + org.springframework.security + spring-security-oauth2-jose + \ No newline at end of file diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java index 9522a7429..4d3888bca 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java @@ -189,4 +189,32 @@ public interface SecurityConstants { * 账号类型参数名 */ String ACCOUNT_TYPE_PARAM_NAME = "account_type"; + + /** + * 协议字段 + */ + String LICENSE_NAME = "license"; + + /** + * 客户端ID + */ + String CLIENT_ID = "clientId"; + + /** + * 用户信息 + */ + String DETAILS_USER = "user_info"; + /** + * 用户ID + */ + String DETAILS_USER_ID = "user_id"; + /** + * 用户名 + */ + String USERNAME = "username"; + + /** + * jwk set缓存前缀 + */ + String AUTHORIZATION_JWS_PREFIX_KEY = "authorization_jws"; } diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/context/LoginUserContextHolder.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/context/LoginUserContextHolder.java index 12f4fa5c9..900ab452e 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/context/LoginUserContextHolder.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/context/LoginUserContextHolder.java @@ -1,7 +1,7 @@ package com.central.common.context; import com.alibaba.ttl.TransmittableThreadLocal; -import com.central.common.model.SysUser; +import com.central.common.model.LoginAppUser; /** * 登录用户holder @@ -13,13 +13,13 @@ * Github: https://github.com/zlt2000 */ public class LoginUserContextHolder { - private static final ThreadLocal CONTEXT = new TransmittableThreadLocal<>(); + private static final ThreadLocal CONTEXT = new TransmittableThreadLocal<>(); - public static void setUser(SysUser user) { + public static void setUser(LoginAppUser user) { CONTEXT.set(user); } - public static SysUser getUser() { + public static LoginAppUser getUser() { return CONTEXT.get(); } diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/datascope/mp/sql/handler/CreatorDataScopeSqlHandler.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/datascope/mp/sql/handler/CreatorDataScopeSqlHandler.java index 8630b75b0..fac8df9ba 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/datascope/mp/sql/handler/CreatorDataScopeSqlHandler.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/datascope/mp/sql/handler/CreatorDataScopeSqlHandler.java @@ -6,11 +6,11 @@ import com.central.common.context.LoginUserContextHolder; import com.central.common.enums.DataScope; import com.central.common.feign.UserService; +import com.central.common.model.LoginAppUser; import com.central.common.model.SysRole; -import com.central.common.model.SysUser; import com.central.common.properties.DataScopeProperties; -import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.Resource; import java.util.List; import java.util.Objects; @@ -21,10 +21,10 @@ */ public class CreatorDataScopeSqlHandler implements SqlHandler{ - @Autowired + @Resource UserService userService; - @Autowired + @Resource private DataScopeProperties dataScopeProperties; /** @@ -35,7 +35,7 @@ public class CreatorDataScopeSqlHandler implements SqlHandler{ */ @Override public String handleScopeSql() { - SysUser user = LoginUserContextHolder.getUser(); + LoginAppUser user = LoginUserContextHolder.getUser(); Assert.notNull(user, "登陆人不能为空"); List roleList = userService.findRolesByUserId(user.getId()); return StrUtil.isBlank(dataScopeProperties.getCreatorIdColumnName()) diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/model/LoginAppUser.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/model/LoginAppUser.java index 558b5c893..89a5a26d7 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/model/LoginAppUser.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/model/LoginAppUser.java @@ -1,15 +1,13 @@ package com.central.common.model; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; +import java.io.Serial; +import java.util.*; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.social.security.SocialUserDetails; -import org.springframework.util.CollectionUtils; - -import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; import lombok.Getter; import lombok.Setter; @@ -20,46 +18,49 @@ */ @Getter @Setter -public class LoginAppUser extends SysUser implements SocialUserDetails { +public class LoginAppUser extends User implements OAuth2AuthenticatedPrincipal { + @Serial private static final long serialVersionUID = -3685249101751401211L; - private Set permissions; + @JsonSerialize(using = ToStringSerializer.class) + private final Long id; - /*** - * 权限重写 - */ - @JsonIgnore - @Override - public Collection getAuthorities() { - Collection collection = new HashSet<>(); - if (!CollectionUtils.isEmpty(super.getRoles())) { - super.getRoles().forEach(role -> collection.add(new SimpleGrantedAuthority(role.getCode()))); - } - return collection; - } + private final String mobile; - @Override - public boolean isAccountNonExpired() { - return true; + private final Collection permissions; + + private final Map attributes = new HashMap<>(); + + public LoginAppUser() { + super(" ", "", true, true, true, true, new HashSet<>()); + this.id = null; + this.mobile = null; + this.permissions = new HashSet<>(0); } - @Override - public boolean isAccountNonLocked() { - return true; + public LoginAppUser(Long id, String username, Collection authorities) { + super(username, "" + , true, true, true, true, authorities); + this.id = id; + this.mobile = null; + this.permissions = new HashSet<>(0); } - @Override - public boolean isCredentialsNonExpired() { - return true; + public LoginAppUser(Long id, String username, String password, String mobile, Collection permissions, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection authorities) { + super(username, Optional.ofNullable(password).orElse("") + , enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); + this.id = id; + this.mobile = mobile; + this.permissions = Optional.ofNullable(permissions).orElse(new HashSet<>(0)); } @Override - public boolean isEnabled() { - return getEnabled(); + public Map getAttributes() { + return this.attributes; } @Override - public String getUserId() { - return getOpenId(); + public String getName() { + return this.getUsername(); } } diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java index a05978cbf..fceb4ba58 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java @@ -2,19 +2,20 @@ import cn.hutool.core.util.StrUtil; import com.central.common.constant.SecurityConstants; +import com.central.common.context.LoginUserContextHolder; import com.central.common.feign.UserService; -import com.central.common.model.SysRole; -import com.central.common.model.SysUser; +import com.central.common.model.LoginAppUser; import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.security.oauth2.jwt.Jwt; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; /** * 获取当前登录人工具类 @@ -27,19 +28,17 @@ * Github: https://github.com/zlt2000 */ public class LoginUserUtils { + private final static String ATT_PERMISSIONS = "permissions"; + /** * 获取当前登录人 */ - public static SysUser getCurrentUser(HttpServletRequest request, boolean isFull) { - SysUser user = null; + public static LoginAppUser getCurrentUser(HttpServletRequest request, boolean isFull) { + LoginAppUser user = null; Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null && !(authentication instanceof AnonymousAuthenticationToken)) { - Object principal = authentication.getPrincipal(); - //客户端模式只返回一个clientId - if (principal instanceof SysUser) { - user = (SysUser)principal; - } + user = getUser(authentication); } if (user == null) { String userId = request.getHeader(SecurityConstants.USER_ID_HEADER); @@ -49,27 +48,20 @@ public static SysUser getCurrentUser(HttpServletRequest request, boolean isFull) if (StrUtil.isAllNotBlank(username, userId)) { if (isFull) { UserService userService = SpringUtil.getBean(UserService.class); - user = userService.selectByUsername(username); + user = userService.findByUsername(username); } else { - user = new SysUser(); - user.setId(Long.valueOf(userId)); - user.setUsername(username); - } - if (StrUtil.isNotBlank(roles)) { - List sysRoleList = new ArrayList<>(); - Arrays.stream(roles.split(",")).forEach(role -> { - SysRole sysRole = new SysRole(); - sysRole.setCode(role); - sysRoleList.add(sysRole); - }); - user.setRoles(sysRoleList); + Collection authorities = new HashSet<>(); + if (StrUtil.isNotBlank(roles)) { + Arrays.stream(roles.split(",")).forEach(role -> authorities.add(new SimpleGrantedAuthority(role))); + } + return new LoginAppUser(Long.valueOf(userId), username, authorities); } } } return user; } - public static SysUser getCurrentUser(boolean isFull) { + public static LoginAppUser getCurrentUser(boolean isFull) { // 从请求上下文里获取 Request 对象 ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest contextRequest = requestAttributes.getRequest(); @@ -78,4 +70,65 @@ public static SysUser getCurrentUser(boolean isFull) { } return null; } + + /** + * 获取登陆的用户对象 + */ + public static LoginAppUser getUser(Authentication authentication) { + LoginAppUser user = null; + if (authentication != null && !(authentication instanceof AnonymousAuthenticationToken)) { + Object principal = authentication.getPrincipal(); + //客户端模式只返回一个clientId + if (principal instanceof LoginAppUser) { + user = (LoginAppUser) principal; + } else if (principal instanceof Jwt jwt) { + Map userMap = jwt.getClaim(SecurityConstants.DETAILS_USER); + user = getLoginAppUser(userMap); + } + } + return user; + } + + /** + * 获取登陆的用户名 + */ + public static String getUsername(Authentication authentication) { + LoginAppUser user = getUser(authentication); + String username = null; + if (user != null) { + username = user.getUsername(); + } + return username; + } + + /** + * 用户信息赋值 context 对象 + */ + public static LoginAppUser setContext(Authentication authentication) { + SecurityContextHolder.getContext().setAuthentication(authentication); + LoginAppUser user = getUser(authentication); + LoginUserContextHolder.setUser(user); + return user; + } + + @SuppressWarnings("unchecked") + public static LoginAppUser getLoginAppUser(Map userObj) { + return new LoginAppUser( + (Long)userObj.get("id"), + (String)userObj.get("username"), + (String)userObj.get("password"), + (String)userObj.get("mobile"), + (Collection)userObj.get(ATT_PERMISSIONS), + Optional.ofNullable((Boolean)userObj.get("enabled")).orElse(true), + true, true, true, + getGrantedAuthoritys((List>)userObj.get("authorities"))); + } + private static Collection getGrantedAuthoritys(List> authorities) { + if (authorities != null) { + List result = new ArrayList<>(authorities.size()); + authorities.forEach(e -> result.add(new SimpleGrantedAuthority(e.get("role")))); + return result; + } + return null; + } } diff --git a/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/LoginUserFilter.java b/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/LoginUserFilter.java index b169e2e5b..f1f875f86 100644 --- a/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/LoginUserFilter.java +++ b/zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/filter/LoginUserFilter.java @@ -1,7 +1,7 @@ package com.central.common.filter; import com.central.common.context.LoginUserContextHolder; -import com.central.common.model.SysUser; +import com.central.common.model.LoginAppUser; import com.central.common.utils.LoginUserUtils; import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; @@ -30,7 +30,7 @@ public class LoginUserFilter extends OncePerRequestFilter { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { try { - SysUser user = LoginUserUtils.getCurrentUser(request, false); + LoginAppUser user = LoginUserUtils.getCurrentUser(request, false); LoginUserContextHolder.setUser(user); filterChain.doFilter(request, response); } finally { diff --git a/zlt-commons/zlt-redis-spring-boot-starter/pom.xml b/zlt-commons/zlt-redis-spring-boot-starter/pom.xml index ddf27ba35..ef8709234 100644 --- a/zlt-commons/zlt-redis-spring-boot-starter/pom.xml +++ b/zlt-commons/zlt-redis-spring-boot-starter/pom.xml @@ -37,5 +37,10 @@ spring-boot-configuration-processor true + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java index edfa0d36d..60196b5c8 100644 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/RedisAutoConfigure.java @@ -9,7 +9,6 @@ import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/component/RedissonAutoConfigCustomizers.java b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/component/RedissonAutoConfigCustomizers.java new file mode 100644 index 000000000..0f6e49866 --- /dev/null +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/component/RedissonAutoConfigCustomizers.java @@ -0,0 +1,24 @@ +package com.central.common.redis.component; + +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.redisson.codec.JsonJacksonCodec; +import org.redisson.config.Config; +import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; +import org.springframework.stereotype.Component; + +/** + * @author: zlt + * @date: 2023/11/21 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Component +public class RedissonAutoConfigCustomizers implements RedissonAutoConfigurationCustomizer { + @Override + public void customize(Config configuration) { + JsonJacksonCodec jacksonCodec = new JsonJacksonCodec(); + jacksonCodec.getObjectMapper().registerModule(new JavaTimeModule()); + configuration.setCodec(jacksonCodec); + } +} diff --git a/zlt-gateway/sc-gateway/pom.xml b/zlt-gateway/sc-gateway/pom.xml index ccd5f63d9..b8538b5d3 100644 --- a/zlt-gateway/sc-gateway/pom.xml +++ b/zlt-gateway/sc-gateway/pom.xml @@ -54,10 +54,11 @@ - + org.springframework.cloud @@ -78,10 +79,6 @@ knife4j-gateway-spring-boot-starter - com.baomidou mybatis-plus-extension diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/Oauth2ServerAuthSuccessHandler.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/Oauth2ServerAuthSuccessHandler.java new file mode 100644 index 000000000..1aa677649 --- /dev/null +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/Oauth2ServerAuthSuccessHandler.java @@ -0,0 +1,57 @@ +package com.central.gateway.auth; + +import cn.hutool.core.collection.CollectionUtil; +import com.central.common.constant.SecurityConstants; +import com.central.common.model.LoginAppUser; +import com.central.common.utils.LoginUserUtils; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal; +import org.springframework.security.web.server.WebFilterExchange; +import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.security.Principal; +import java.util.Map; + +/** + * 认证成功处理类 + * + * @author zlt + * @date 2019/10/7 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class Oauth2ServerAuthSuccessHandler implements ServerAuthenticationSuccessHandler { + @Override + public Mono onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { + MultiValueMap headerValues = new LinkedMultiValueMap<>(4); + Object principal = authentication.getPrincipal(); + + if (principal instanceof OAuth2IntrospectionAuthenticatedPrincipal authenticatedPrincipal) { + Map claims = authenticatedPrincipal.getAttributes(); + Authentication auth = (Authentication)claims.get(Principal.class.getName()); + LoginAppUser user = LoginUserUtils.getUser(auth); + if (user != null) { + headerValues.add(SecurityConstants.USER_ID_HEADER, String.valueOf(user.getId())); + headerValues.add(SecurityConstants.USER_HEADER, user.getUsername()); + } + + headerValues.add(SecurityConstants.ROLE_HEADER, CollectionUtil.join(authentication.getAuthorities(), ",")); + headerValues.add(SecurityConstants.TENANT_HEADER, (String)claims.get(SecurityConstants.CLIENT_ID)); + headerValues.add(SecurityConstants.ACCOUNT_TYPE_HEADER, (String)claims.get(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME)); + } + + ServerWebExchange exchange = webFilterExchange.getExchange(); + ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate() + .headers(h -> h.addAll(headerValues)) + .build(); + + ServerWebExchange build = exchange.mutate().request(serverHttpRequest).build(); + return webFilterExchange.getChain().filter(build); + } +} diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/PermissionAuthManager.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/PermissionAuthManager.java new file mode 100644 index 000000000..15987debb --- /dev/null +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/PermissionAuthManager.java @@ -0,0 +1,56 @@ +package com.central.gateway.auth; + +import com.central.common.model.SysMenu; +import com.central.gateway.feign.AsynMenuService; +import com.central.oauth2.common.service.impl.DefaultPermissionServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.authorization.ReactiveAuthorizationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.server.authorization.AuthorizationContext; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import javax.annotation.Resource; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Future; + +/** + * url权限认证 + * + * @author zlt + * @date 2019/10/6 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Slf4j +@Component +public class PermissionAuthManager extends DefaultPermissionServiceImpl implements ReactiveAuthorizationManager { + @Resource + private AsynMenuService asynMenuService; + + @Override + public Mono check(Mono authentication, AuthorizationContext authorizationContext) { + return authentication.map(auth -> { + ServerWebExchange exchange = authorizationContext.getExchange(); + ServerHttpRequest request = exchange.getRequest(); + boolean isPermission = super.hasPermission(auth, request.getMethod().name(), request.getURI().getPath()); + return new AuthorizationDecision(isPermission); + }).defaultIfEmpty(new AuthorizationDecision(false)); + } + + @Override + public List findMenuByRoleCodes(String roleCodes) { + Future> futureResult = asynMenuService.findByRoleCodes(roleCodes); + try { + return futureResult.get(); + } catch (Exception e) { + log.error("asynMenuService.findMenuByRoleCodes-error", e); + } + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java new file mode 100644 index 000000000..80dca0bea --- /dev/null +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java @@ -0,0 +1,87 @@ +package com.central.gateway.config; + +import com.central.gateway.auth.*; +import com.central.oauth2.common.component.CustomReactiveAuthorizationServiceIntrospector; +import com.central.oauth2.common.config.BaseSecurityConfig; +import com.central.oauth2.common.properties.SecurityProperties; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.SecurityWebFiltersOrder; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenReactiveAuthenticationManager; +import org.springframework.security.oauth2.server.resource.web.server.authentication.ServerBearerTokenAuthenticationConverter; +import org.springframework.security.web.server.SecurityWebFilterChain; +import org.springframework.security.web.server.ServerAuthenticationEntryPoint; +import org.springframework.security.web.server.authentication.AuthenticationWebFilter; +import org.springframework.security.web.server.authentication.ServerAuthenticationEntryPointFailureHandler; +import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler; + +/** + * 资源服务器 + * + * @author: zlt + * @date: 2023/11/25 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Configuration +@EnableWebFluxSecurity +@Slf4j +@Import(BaseSecurityConfig.class) +public class ResourceServerConfiguration { + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http + , SecurityProperties securityProperties, PermissionAuthManager permissionAuthManager + , ServerAuthenticationEntryPoint authenticationEntryPoint, ServerAccessDeniedHandler accessDeniedHandler) { + http.csrf(ServerHttpSecurity.CsrfSpec::disable) + .cors(ServerHttpSecurity.CorsSpec::disable) + .headers(hSpec -> hSpec.frameOptions(ServerHttpSecurity.HeaderSpec.FrameOptionsSpec::disable)) + .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable) + .exceptionHandling(e -> { + e.authenticationEntryPoint(authenticationEntryPoint) + .accessDeniedHandler(accessDeniedHandler); + }); + + http.authorizeExchange(exchange -> { + if (securityProperties.getAuth().getHttpUrls().length > 0) { + exchange.pathMatchers(securityProperties.getAuth().getHttpUrls()).authenticated(); + } + if (securityProperties.getIgnore().getUrls().length > 0) { + exchange.pathMatchers(securityProperties.getIgnore().getUrls()).permitAll(); + } + exchange.pathMatchers(HttpMethod.OPTIONS).permitAll() + .anyExchange().access(permissionAuthManager); + }); + + http.addFilterAt(this.getAuthWebFilter(authenticationEntryPoint) + , SecurityWebFiltersOrder.AUTHENTICATION); + + return http.build(); + } + + private AuthenticationWebFilter getAuthWebFilter(ServerAuthenticationEntryPoint authenticationEntryPoint) { + OpaqueTokenReactiveAuthenticationManager authenticationManager = + new OpaqueTokenReactiveAuthenticationManager( + new CustomReactiveAuthorizationServiceIntrospector()); + ServerBearerTokenAuthenticationConverter authenticationConverter = new ServerBearerTokenAuthenticationConverter(); + authenticationConverter.setAllowUriQueryParameter(true); + + AuthenticationWebFilter oauth2 = new AuthenticationWebFilter(authenticationManager); + oauth2.setServerAuthenticationConverter(authenticationConverter); + oauth2.setAuthenticationFailureHandler(getFailureHandler(authenticationEntryPoint)); + oauth2.setAuthenticationSuccessHandler(new Oauth2ServerAuthSuccessHandler()); + return oauth2; + } + + private ServerAuthenticationEntryPointFailureHandler getFailureHandler(ServerAuthenticationEntryPoint authenticationEntryPoint) { + ServerAuthenticationEntryPointFailureHandler failureHandler = + new ServerAuthenticationEntryPointFailureHandler(authenticationEntryPoint); + failureHandler.setRethrowAuthenticationServiceException(false); + return failureHandler; + } +} diff --git a/zlt-gateway/sc-gateway/src/main/resources/application.yml b/zlt-gateway/sc-gateway/src/main/resources/application.yml index b73d27b3b..c5f14ed86 100644 --- a/zlt-gateway/sc-gateway/src/main/resources/application.yml +++ b/zlt-gateway/sc-gateway/src/main/resources/application.yml @@ -96,10 +96,6 @@ knife4j: url: /api-file/v3/api-docs/default context-path: /api-file -# discover: -# version: openapi3 -# excluded-services: ${spring.application.name} - zlt: oauth2: token: diff --git a/zlt-uaa/pom.xml b/zlt-uaa/pom.xml index 5efd2379b..53d17a81f 100644 --- a/zlt-uaa/pom.xml +++ b/zlt-uaa/pom.xml @@ -21,10 +21,10 @@ com.zlt zlt-common-spring-boot-starter - + com.zlt zlt-db-spring-boot-starter @@ -50,6 +50,10 @@ com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery + + org.springframework.boot + spring-boot-starter-oauth2-authorization-server + org.springframework.social spring-social-security diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java b/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java index c419e99d5..c9afe37e0 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java @@ -26,4 +26,6 @@ public interface IClientService extends ISuperService { void delClient(long id); Client loadClientByClientId(String clientId); + + void loadAllClientToCache(); } diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/ZltUserDetailsService.java b/zlt-uaa/src/main/java/com/central/oauth/service/ZltUserDetailsService.java index bdeda6224..a3148273f 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/ZltUserDetailsService.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/ZltUserDetailsService.java @@ -3,7 +3,6 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.social.security.SocialUserDetails; /** * @author zlt @@ -31,5 +30,5 @@ public interface ZltUserDetailsService extends UserDetailsService { * 根据用户id/openId查询用户 * @param userId 用户id/openId */ - SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException; + UserDetails loadUserByUserId(String userId) throws UsernameNotFoundException; } diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java index bfc2a751c..7a7fa3e72 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java @@ -8,13 +8,15 @@ import com.central.common.lock.DistributedLock; import com.central.common.model.PageResult; import com.central.common.model.Result; -import com.central.common.redis.template.RedisRepository; import com.central.common.service.impl.SuperServiceImpl; import com.central.oauth.mapper.ClientMapper; import com.central.oauth.model.Client; import com.central.oauth.service.IClientService; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.MapUtils; +import org.redisson.api.RBucket; +import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @@ -29,18 +31,16 @@ * Github: https://github.com/zlt2000 */ @Slf4j +@RequiredArgsConstructor @Service public class ClientServiceImpl extends SuperServiceImpl implements IClientService { private final static String LOCK_KEY_CLIENTID = "clientId:"; - @Autowired - private RedisRepository redisRepository; + private final RedissonClient redisson; - @Autowired - private PasswordEncoder passwordEncoder; + private final PasswordEncoder passwordEncoder; - @Autowired - private DistributedLock lock; + private final DistributedLock lock; @Override public Result saveClient(Client client) throws Exception { @@ -53,6 +53,9 @@ public Result saveClient(Client client) throws Exception { , LOCK_KEY_CLIENTID+clientId , new QueryWrapper().eq("client_id", clientId) , clientId + "已存在"); + + redisson.getBucket(clientRedisKey(clientId)).set(client); + return Result.succeed("操作成功"); } @@ -73,14 +76,27 @@ public PageResult listClient(Map params, boolean isPage) public void delClient(long id) { String clientId = baseMapper.selectById(id).getClientId(); baseMapper.deleteById(id); - redisRepository.del(clientRedisKey(clientId)); + redisson.getBucket(clientRedisKey(clientId)).delete(); } @Override public Client loadClientByClientId(String clientId) { + RBucket clientBucket = redisson.getBucket(clientRedisKey(clientId)); + Client client = clientBucket.get(); + if (client != null) { + return client; + } QueryWrapper wrapper = Wrappers.query(); wrapper.eq("client_id", clientId); - return this.getOne(wrapper); + client = this.getOne(wrapper); + clientBucket.set(client); + return client; + } + + @Override + public void loadAllClientToCache() { + List clientList = this.list(); + clientList.forEach(c -> redisson.getBucket(clientRedisKey(c.getClientId())).set(c)); } private String clientRedisKey(String clientId) { diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceImpl.java index e227fa072..0f505921f 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceImpl.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceImpl.java @@ -8,7 +8,6 @@ import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.InternalAuthenticationServiceException; import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.social.security.SocialUserDetails; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -42,7 +41,7 @@ public UserDetails loadUserByUsername(String username) { } @Override - public SocialUserDetails loadUserByUserId(String openId) { + public UserDetails loadUserByUserId(String openId) { LoginAppUser loginAppUser = userService.findByOpenId(openId); return checkUser(loginAppUser); } diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java index 04cce984c..dae161a31 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java @@ -4,8 +4,8 @@ import cn.hutool.core.util.StrUtil; import com.central.common.constant.SecurityConstants; import com.central.common.feign.UserService; +import com.central.common.model.LoginAppUser; import com.central.common.model.Result; -import com.central.common.model.SysUser; import com.central.common.redis.template.RedisRepository; import com.central.oauth.exception.ValidateCodeException; import com.central.oauth.service.IValidateCodeService; @@ -61,7 +61,7 @@ public Result sendSmsCode(String mobile) { return Result.failed("验证码未失效,请失效后再次申请"); } - SysUser user = userService.findByMobile(mobile); + LoginAppUser user = userService.findByMobile(mobile); if (user == null) { log.error("根据用户手机号{}查询用户为空", mobile); return Result.failed("手机号不存在"); From b604e4665a05e49d2f35ba1877046679d9d078ca Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Mon, 4 Dec 2023 17:24:23 +0800 Subject: [PATCH 11/23] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E6=9C=8D=E5=8A=A1=E5=99=A8=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/config/BaseSecurityConfig.java | 9 +++++--- .../oauth2/common/enums/TokenType.java | 23 +++++++++++++++++++ .../properties/ResourceServerProperties.java | 8 +++++-- 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/enums/TokenType.java diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/BaseSecurityConfig.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/BaseSecurityConfig.java index 305cb4c0e..b342b95f5 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/BaseSecurityConfig.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/BaseSecurityConfig.java @@ -4,6 +4,7 @@ import com.central.common.constant.SecurityConstants; import com.central.common.utils.ResponseUtil; import com.central.common.utils.WebfluxResponseUtil; +import com.central.oauth2.common.enums.TokenType; import com.central.oauth2.common.properties.SecurityProperties; import com.central.oauth2.common.service.impl.RedisOAuth2AuthorizationService; import com.fasterxml.jackson.databind.ObjectMapper; @@ -12,22 +13,20 @@ import com.nimbusds.jose.jwk.source.ImmutableJWKSet; import com.nimbusds.jose.jwk.source.JWKSource; import com.nimbusds.jose.proc.SecurityContext; -import jakarta.servlet.http.HttpServletRequest; import org.redisson.api.RBucket; import org.redisson.api.RedissonClient; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpStatus; import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.jwt.JwtEncoder; import org.springframework.security.oauth2.jwt.NimbusJwtEncoder; +import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationService; import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.server.ServerAuthenticationEntryPoint; import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler; -import org.springframework.web.server.ServerWebExchange; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -47,6 +46,10 @@ public class BaseSecurityConfig { @Bean public OAuth2AuthorizationService oAuth2AuthorizationService(SecurityProperties securityProperties, RedissonClient redisson) { + String tokenType = securityProperties.getResourceServer().getTokenType(); + if (TokenType.MEMORY.getName().equals(tokenType)) { + return new InMemoryOAuth2AuthorizationService(); + } return new RedisOAuth2AuthorizationService(securityProperties, redisson); } diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/enums/TokenType.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/enums/TokenType.java new file mode 100644 index 000000000..a93630d37 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/enums/TokenType.java @@ -0,0 +1,23 @@ +package com.central.oauth2.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * token 类型 + * + * @author: zlt + * @date: 2023/12/4 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Getter +@AllArgsConstructor +public enum TokenType { + REDIS("redis"), + MEMORY("inMemory"), + JWT("jwt"), + REF("reference"); + private final String name; +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java index dcab6931a..8b9567c16 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java @@ -16,7 +16,11 @@ @Getter public class ResourceServerProperties { /** - * token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt)) + * token格式: + * - redis: 通过 redis 来验证 + * - inMemory: 通过本地内存来验证 + * - jwt: 自包含令牌,自己解析内容 + * - reference: 引用令牌,通过远程调用授权服务器进行验证 */ - private String tokenFormat = "reference"; + private String tokenType = "redis"; } From 1d8757c58e0457336a570722ffcd8a59e651b378 Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Tue, 5 Dec 2023 17:27:15 +0800 Subject: [PATCH 12/23] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E6=8E=92?= =?UTF-8?q?=E9=99=A4=E9=89=B4=E6=9D=83=E7=9A=84=E5=9C=B0=E5=9D=80=E5=8D=B3?= =?UTF-8?q?=E4=BD=BF=E5=8F=82=E6=95=B0=E5=B8=A6=20access=5Ftoken=20?= =?UTF-8?q?=E4=B9=9F=E4=B8=8D=E4=BC=9A=E8=BF=9B=E8=A1=8C=E9=89=B4=E6=9D=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CustomBearerTokenResolver.java | 24 +-- .../CustomServerBearerTokenAuthConverter.java | 147 ++++++++++++++++++ .../central/oauth2/common/util/AuthUtils.java | 27 ++-- .../common/constant/SecurityConstants.java | 2 +- .../config/ResourceServerConfiguration.java | 10 +- 5 files changed, 171 insertions(+), 39 deletions(-) rename zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/{service/impl => component}/CustomBearerTokenResolver.java (78%) create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomServerBearerTokenAuthConverter.java diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/CustomBearerTokenResolver.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomBearerTokenResolver.java similarity index 78% rename from zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/CustomBearerTokenResolver.java rename to zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomBearerTokenResolver.java index 833d1ca26..80813ceb2 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/CustomBearerTokenResolver.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomBearerTokenResolver.java @@ -1,7 +1,8 @@ -package com.central.oauth2.common.service.impl; +package com.central.oauth2.common.component; import com.central.oauth2.common.properties.PermitProperties; import com.central.oauth2.common.properties.SecurityProperties; +import com.central.oauth2.common.util.AuthUtils; import jakarta.servlet.http.HttpServletRequest; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.http.HttpHeaders; @@ -13,11 +14,8 @@ import org.springframework.stereotype.Component; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; -import org.springframework.util.StringUtils; import java.util.Arrays; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * @author: zlt @@ -29,9 +27,6 @@ @ConditionalOnClass(HttpServletRequest.class) @Component public class CustomBearerTokenResolver implements BearerTokenResolver { - private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?[a-zA-Z0-9-:._~+/]+=*)$", - Pattern.CASE_INSENSITIVE); - private final boolean allowFormEncodedBodyParameter = false; private final boolean allowUriQueryParameter = true; @@ -55,7 +50,7 @@ public String resolve(HttpServletRequest request) { return null; } - final String authorizationHeaderToken = resolveFromAuthorizationHeader(request); + final String authorizationHeaderToken = AuthUtils.extractHeaderToken(request); final String parameterToken = isParameterTokenSupportedForRequest(request) ? resolveFromRequestParameters(request) : null; if (authorizationHeaderToken != null) { @@ -72,19 +67,6 @@ public String resolve(HttpServletRequest request) { return null; } - private String resolveFromAuthorizationHeader(HttpServletRequest request) { - String authorization = request.getHeader(this.bearerTokenHeaderName); - if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) { - return null; - } - Matcher matcher = authorizationPattern.matcher(authorization); - if (!matcher.matches()) { - BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed"); - throw new OAuth2AuthenticationException(error); - } - return matcher.group("token"); - } - private static String resolveFromRequestParameters(HttpServletRequest request) { String[] values = request.getParameterValues("access_token"); if (values == null || values.length == 0) { diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomServerBearerTokenAuthConverter.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomServerBearerTokenAuthConverter.java new file mode 100644 index 000000000..b14ce08d5 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomServerBearerTokenAuthConverter.java @@ -0,0 +1,147 @@ +package com.central.oauth2.common.component; + +import com.central.oauth2.common.properties.PermitProperties; +import com.central.oauth2.common.properties.SecurityProperties; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.server.resource.BearerTokenError; +import org.springframework.security.oauth2.server.resource.BearerTokenErrors; +import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationToken; +import org.springframework.security.web.server.authentication.ServerAuthenticationConverter; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.CollectionUtils; +import org.springframework.util.PathMatcher; +import org.springframework.util.StringUtils; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 实现排除鉴权的地址即使参数带 access_token 也不会进行鉴权 + * + * @author zlt + * @version 1.0 + * @date 2023/12/5 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class CustomServerBearerTokenAuthConverter implements ServerAuthenticationConverter { + private final PathMatcher pathMatcher = new AntPathMatcher(); + + private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?[a-zA-Z0-9-._~+/]+=*)$", + Pattern.CASE_INSENSITIVE); + + private boolean allowUriQueryParameter = false; + + private String bearerTokenHeaderName = HttpHeaders.AUTHORIZATION; + + private final PermitProperties permitProperties; + + public CustomServerBearerTokenAuthConverter(SecurityProperties securityProperties) { + this.permitProperties = securityProperties.getIgnore(); + } + + @Override + public Mono convert(ServerWebExchange exchange) { + return Mono.fromCallable(() -> token(exchange.getRequest())).map((token) -> { + if (token.isEmpty()) { + BearerTokenError error = invalidTokenError(); + throw new OAuth2AuthenticationException(error); + } + return new BearerTokenAuthenticationToken(token); + }); + } + + private String token(ServerHttpRequest request) { + boolean match = Arrays.stream(permitProperties.getUrls()) + .anyMatch(url -> pathMatcher.match(url, request.getURI().getPath())); + + if (match) { + return null; + } + + String authorizationHeaderToken = resolveFromAuthorizationHeader(request.getHeaders()); + String parameterToken = resolveAccessTokenFromRequest(request); + + if (authorizationHeaderToken != null) { + if (parameterToken != null) { + BearerTokenError error = BearerTokenErrors + .invalidRequest("Found multiple bearer tokens in the request"); + throw new OAuth2AuthenticationException(error); + } + return authorizationHeaderToken; + } + if (parameterToken != null && isParameterTokenSupportedForRequest(request)) { + return parameterToken; + } + return null; + } + + private static String resolveAccessTokenFromRequest(ServerHttpRequest request) { + List parameterTokens = request.getQueryParams().get("access_token"); + if (CollectionUtils.isEmpty(parameterTokens)) { + return null; + } + if (parameterTokens.size() == 1) { + return parameterTokens.get(0); + } + + BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request"); + throw new OAuth2AuthenticationException(error); + + } + + /** + * Set if transport of access token using URI query parameter is supported. Defaults + * to {@code false}. + * + * The spec recommends against using this mechanism for sending bearer tokens, and + * even goes as far as stating that it was only included for completeness. + * @param allowUriQueryParameter if the URI query parameter is supported + */ + public void setAllowUriQueryParameter(boolean allowUriQueryParameter) { + this.allowUriQueryParameter = allowUriQueryParameter; + } + + /** + * Set this value to configure what header is checked when resolving a Bearer Token. + * This value is defaulted to {@link HttpHeaders#AUTHORIZATION}. + * + * This allows other headers to be used as the Bearer Token source such as + * {@link HttpHeaders#PROXY_AUTHORIZATION} + * @param bearerTokenHeaderName the header to check when retrieving the Bearer Token. + * @since 5.4 + */ + public void setBearerTokenHeaderName(String bearerTokenHeaderName) { + this.bearerTokenHeaderName = bearerTokenHeaderName; + } + + private String resolveFromAuthorizationHeader(HttpHeaders headers) { + String authorization = headers.getFirst(this.bearerTokenHeaderName); + if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) { + return null; + } + Matcher matcher = authorizationPattern.matcher(authorization); + if (!matcher.matches()) { + BearerTokenError error = invalidTokenError(); + throw new OAuth2AuthenticationException(error); + } + return matcher.group("token"); + } + + private static BearerTokenError invalidTokenError() { + return BearerTokenErrors.invalidToken("Bearer token is malformed"); + } + + private boolean isParameterTokenSupportedForRequest(ServerHttpRequest request) { + return this.allowUriQueryParameter && HttpMethod.GET.equals(request.getMethod()); + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java index fed532c89..75399d9ae 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java @@ -9,7 +9,6 @@ import com.central.oauth2.common.token.BaseAuthenticationToken; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import jakarta.servlet.http.HttpServletRequest; @@ -17,10 +16,13 @@ import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException; +import org.springframework.util.StringUtils; import java.nio.charset.StandardCharsets; import java.security.Principal; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * 认证授权相关工具类 @@ -39,6 +41,9 @@ private AuthUtils() { private static final String BASIC_ = "Basic "; + private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?[a-zA-Z0-9-:._~+/]+=*)$", + Pattern.CASE_INSENSITIVE); + /** * 获取requet(head/param)中的token * @param request @@ -60,18 +65,14 @@ public static String extractToken(HttpServletRequest request) { * @param request * @return */ - private static String extractHeaderToken(HttpServletRequest request) { - Enumeration headers = request.getHeaders(CommonConstant.TOKEN_HEADER); - while (headers.hasMoreElements()) { - String value = headers.nextElement(); - if ((value.startsWith(OAuth2AccessToken.TokenType.BEARER.getValue()))) { - String authHeaderValue = value.substring(OAuth2AccessToken.TokenType.BEARER.getValue().length()).trim(); - int commaIndex = authHeaderValue.indexOf(','); - if (commaIndex > 0) { - authHeaderValue = authHeaderValue.substring(0, commaIndex); - } - return authHeaderValue; - } + public static String extractHeaderToken(HttpServletRequest request) { + String authorization = request.getHeader(CommonConstant.TOKEN_HEADER); + if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) { + return null; + } + Matcher matcher = authorizationPattern.matcher(authorization); + if (matcher.matches()) { + return matcher.group("token"); } return null; } diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java index 4d3888bca..e8e22c023 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java @@ -198,7 +198,7 @@ public interface SecurityConstants { /** * 客户端ID */ - String CLIENT_ID = "clientId"; + String CLIENT_ID = "client_id"; /** * 用户信息 diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java index 80dca0bea..629d7564c 100644 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java @@ -2,6 +2,7 @@ import com.central.gateway.auth.*; import com.central.oauth2.common.component.CustomReactiveAuthorizationServiceIntrospector; +import com.central.oauth2.common.component.CustomServerBearerTokenAuthConverter; import com.central.oauth2.common.config.BaseSecurityConfig; import com.central.oauth2.common.properties.SecurityProperties; import lombok.extern.slf4j.Slf4j; @@ -13,7 +14,6 @@ import org.springframework.security.config.web.server.SecurityWebFiltersOrder; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenReactiveAuthenticationManager; -import org.springframework.security.oauth2.server.resource.web.server.authentication.ServerBearerTokenAuthenticationConverter; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.ServerAuthenticationEntryPoint; import org.springframework.security.web.server.authentication.AuthenticationWebFilter; @@ -58,17 +58,19 @@ public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http .anyExchange().access(permissionAuthManager); }); - http.addFilterAt(this.getAuthWebFilter(authenticationEntryPoint) + http.addFilterAt(this.getAuthWebFilter(authenticationEntryPoint, securityProperties) , SecurityWebFiltersOrder.AUTHENTICATION); return http.build(); } - private AuthenticationWebFilter getAuthWebFilter(ServerAuthenticationEntryPoint authenticationEntryPoint) { + private AuthenticationWebFilter getAuthWebFilter(ServerAuthenticationEntryPoint authenticationEntryPoint + , SecurityProperties securityProperties) { OpaqueTokenReactiveAuthenticationManager authenticationManager = new OpaqueTokenReactiveAuthenticationManager( new CustomReactiveAuthorizationServiceIntrospector()); - ServerBearerTokenAuthenticationConverter authenticationConverter = new ServerBearerTokenAuthenticationConverter(); + CustomServerBearerTokenAuthConverter authenticationConverter = + new CustomServerBearerTokenAuthConverter(securityProperties); authenticationConverter.setAllowUriQueryParameter(true); AuthenticationWebFilter oauth2 = new AuthenticationWebFilter(authenticationManager); From 671ab86543ad7662f2047901e2072afdf5a57f8c Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Tue, 5 Dec 2023 23:01:28 +0800 Subject: [PATCH 13/23] =?UTF-8?q?feat:=20=E6=8A=BD=E5=8F=96=E9=80=9A?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E8=B5=84=E6=BA=90=E6=9C=8D=E5=8A=A1=E5=99=A8?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pom.xml | 4 + ...ustomAuthorizationServiceIntrospector.java | 55 +++++++++ ...ctiveAuthorizationServiceIntrospector.java | 2 + .../config/DefaultResourceServerConf.java | 84 +++++++++++++ .../DefaultWebFluxResourceServerConf.java | 116 ++++++++++++++++++ .../central/common/utils/LoginUserUtils.java | 1 + .../com/central/common/utils/SpringUtil.java | 34 ----- .../auth/Oauth2ServerAuthSuccessHandler.java | 2 + .../config/ResourceServerConfiguration.java | 76 +----------- 9 files changed, 267 insertions(+), 107 deletions(-) create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomAuthorizationServiceIntrospector.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultWebFluxResourceServerConf.java delete mode 100644 zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/SpringUtil.java diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml b/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml index 204e686cd..1420f827f 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/pom.xml @@ -16,6 +16,10 @@ org.springframework.boot spring-boot-starter-oauth2-authorization-server + + com.zlt + zlt-common-core + com.nimbusds oauth2-oidc-sdk diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomAuthorizationServiceIntrospector.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomAuthorizationServiceIntrospector.java new file mode 100644 index 000000000..58a6f9846 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomAuthorizationServiceIntrospector.java @@ -0,0 +1,55 @@ +package com.central.oauth2.common.component; + +import com.central.common.constant.SecurityConstants; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal; +import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; +import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; +import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException; +import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector; + +import java.security.Principal; +import java.util.Objects; + +/** + * 内省 token 解析器 + * + * @author: zlt + * @date: 2023/12/5 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Slf4j +@RequiredArgsConstructor +public class CustomAuthorizationServiceIntrospector implements OpaqueTokenIntrospector { + private final OAuth2AuthorizationService authorizationService; + + @Override + public OAuth2AuthenticatedPrincipal introspect(String token) { + OAuth2Authorization authorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); + if (Objects.isNull(authorization)) { + throw new InvalidBearerTokenException("invalid_token: " + token); + } + + // 客户端模式默认返回 + if (AuthorizationGrantType.CLIENT_CREDENTIALS.equals(authorization.getAuthorizationGrantType())) { + return new DefaultOAuth2AuthenticatedPrincipal(authorization.getPrincipalName() + , authorization.getAttributes(), AuthorityUtils.NO_AUTHORITIES); + } + + String accountType = (String)authorization.getAttributes().get(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME); + Authentication authentication = (Authentication)authorization.getAttributes().get(Principal.class.getName()); + OAuth2AuthenticatedPrincipal principal = (OAuth2AuthenticatedPrincipal)authentication.getPrincipal(); + principal.getAttributes().put(SecurityConstants.CLIENT_ID, authorization.getRegisteredClientId()); + principal.getAttributes().put(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME, accountType); + + return principal; + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomReactiveAuthorizationServiceIntrospector.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomReactiveAuthorizationServiceIntrospector.java index 61667c4f5..9e64a0642 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomReactiveAuthorizationServiceIntrospector.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/component/CustomReactiveAuthorizationServiceIntrospector.java @@ -16,6 +16,8 @@ import java.util.*; /** + * webFlux 内省 token 解析器 + * * @author zlt * @version 1.0 * @date 2023/12/4 diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java new file mode 100644 index 000000000..8ef191f8e --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java @@ -0,0 +1,84 @@ +package com.central.oauth2.common.config; + +import cn.hutool.extra.spring.SpringUtil; +import com.central.oauth2.common.component.CustomAuthorizationServiceIntrospector; +import com.central.oauth2.common.component.CustomBearerTokenResolver; +import com.central.oauth2.common.properties.SecurityProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; +import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.access.AccessDeniedHandler; + +import javax.annotation.Resource; + +/** + * @author zlt + * @version 1.0 + * @date 2023/12/5 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@EnableWebSecurity +@Import(BaseSecurityConfig.class) +public class DefaultResourceServerConf { + @Resource + private SecurityProperties securityProperties; + + @Resource + private AuthenticationEntryPoint authenticationEntryPoint; + + @Resource + private CustomBearerTokenResolver customBearerTokenResolver; + + @Resource + private AccessDeniedHandler oAuth2AccessDeniedHandler; + + @Bean + public SecurityFilterChain springSecurityFilterChain(HttpSecurity http) throws Exception { + http.authorizeHttpRequests(authorizeRequests -> { + AuthorizeHttpRequestsConfigurer.AuthorizedUrl authorizedUrl = authorizeRequests + .requestMatchers(HttpMethod.OPTIONS).permitAll() + .requestMatchers(securityProperties.getIgnore().getUrls()).permitAll() + .anyRequest(); + this.setAuthenticate(authorizedUrl); + }).headers(header -> header + // 避免iframe同源无法登录许iframe + .frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin) + ).csrf(AbstractHttpConfigurer::disable) + .sessionManagement(session -> session + .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)); + + // 资源服务配置 + http.oauth2ResourceServer(oauth2 -> { + oauth2.authenticationEntryPoint(authenticationEntryPoint) + .bearerTokenResolver(customBearerTokenResolver) + .accessDeniedHandler(oAuth2AccessDeniedHandler) + .opaqueToken(token -> token.introspector(this.getOpaqueTokenIntrospector())); + }); + + return http.build(); + } + + protected OpaqueTokenIntrospector getOpaqueTokenIntrospector() { + OAuth2AuthorizationService authorizationService = SpringUtil.getBean(OAuth2AuthorizationService.class); + return new CustomAuthorizationServiceIntrospector(authorizationService); + } + + /** + * url权限控制,默认是认证就通过,可以重写实现个性化 + */ + protected void setAuthenticate(AuthorizeHttpRequestsConfigurer.AuthorizedUrl authorizedUrl) { + authorizedUrl.authenticated(); + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultWebFluxResourceServerConf.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultWebFluxResourceServerConf.java new file mode 100644 index 000000000..de6de0f3f --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultWebFluxResourceServerConf.java @@ -0,0 +1,116 @@ +package com.central.oauth2.common.config; + +import com.central.oauth2.common.component.CustomReactiveAuthorizationServiceIntrospector; +import com.central.oauth2.common.component.CustomServerBearerTokenAuthConverter; +import com.central.oauth2.common.properties.SecurityProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.ReactiveAuthenticationManager; +import org.springframework.security.authorization.ReactiveAuthorizationManager; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.SecurityWebFiltersOrder; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenReactiveAuthenticationManager; +import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector; +import org.springframework.security.web.server.SecurityWebFilterChain; +import org.springframework.security.web.server.ServerAuthenticationEntryPoint; +import org.springframework.security.web.server.authentication.AuthenticationWebFilter; +import org.springframework.security.web.server.authentication.ServerAuthenticationConverter; +import org.springframework.security.web.server.authentication.ServerAuthenticationEntryPointFailureHandler; +import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler; +import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler; + +import javax.annotation.Resource; + +/** + * @author zlt + * @version 1.0 + * @date 2023/12/5 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@EnableWebFluxSecurity +@Import(BaseSecurityConfig.class) +public class DefaultWebFluxResourceServerConf { + @Resource + private SecurityProperties securityProperties; + + @Resource + private ServerAuthenticationEntryPoint serverAuthenticationEntryPoint; + + @Resource + private ServerAccessDeniedHandler serverAccessDeniedHandler; + + @Autowired(required = false) + private ReactiveAuthorizationManager authorizationManager; + + @Autowired(required = false) + private ServerAuthenticationSuccessHandler successHandler; + + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + http.csrf(ServerHttpSecurity.CsrfSpec::disable) + .cors(ServerHttpSecurity.CorsSpec::disable) + .headers(hSpec -> hSpec.frameOptions(ServerHttpSecurity.HeaderSpec.FrameOptionsSpec::disable)) + .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable) + .exceptionHandling(e -> { + e.authenticationEntryPoint(serverAuthenticationEntryPoint) + .accessDeniedHandler(serverAccessDeniedHandler); + }); + + http.authorizeExchange(exchange -> { + if (securityProperties.getAuth().getHttpUrls().length > 0) { + exchange.pathMatchers(securityProperties.getAuth().getHttpUrls()).authenticated(); + } + if (securityProperties.getIgnore().getUrls().length > 0) { + exchange.pathMatchers(securityProperties.getIgnore().getUrls()).permitAll(); + } + exchange.pathMatchers(HttpMethod.OPTIONS).permitAll(); + // url 鉴权 + if (authorizationManager != null) { + exchange.anyExchange().access(authorizationManager); + } else { + exchange.anyExchange().authenticated(); + } + }); + + http.addFilterAt(this.getAuthWebFilter(), SecurityWebFiltersOrder.AUTHENTICATION); + + return http.build(); + } + + protected AuthenticationWebFilter getAuthWebFilter() { + AuthenticationWebFilter oauth2 = new AuthenticationWebFilter(this.getAuthenticationManager()); + oauth2.setServerAuthenticationConverter(this.getAuthenticationConverter()); + oauth2.setAuthenticationFailureHandler(this.getFailureHandler()); + if (successHandler != null) { + oauth2.setAuthenticationSuccessHandler(successHandler); + } + return oauth2; + } + + protected ReactiveAuthenticationManager getAuthenticationManager() { + return new OpaqueTokenReactiveAuthenticationManager(this.getOpaqueTokenIntrospector()); + } + + protected ServerAuthenticationConverter getAuthenticationConverter() { + CustomServerBearerTokenAuthConverter authenticationConverter = + new CustomServerBearerTokenAuthConverter(securityProperties); + authenticationConverter.setAllowUriQueryParameter(true); + return authenticationConverter; + } + + protected ReactiveOpaqueTokenIntrospector getOpaqueTokenIntrospector() { + return new CustomReactiveAuthorizationServiceIntrospector(); + } + + protected ServerAuthenticationEntryPointFailureHandler getFailureHandler() { + ServerAuthenticationEntryPointFailureHandler failureHandler = + new ServerAuthenticationEntryPointFailureHandler(serverAuthenticationEntryPoint); + failureHandler.setRethrowAuthenticationServiceException(false); + return failureHandler; + } +} diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java index fceb4ba58..d8e91f06c 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java @@ -1,6 +1,7 @@ package com.central.common.utils; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; import com.central.common.constant.SecurityConstants; import com.central.common.context.LoginUserContextHolder; import com.central.common.feign.UserService; diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/SpringUtil.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/SpringUtil.java deleted file mode 100644 index 9d909fe9f..000000000 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/SpringUtil.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.central.common.utils; - -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.core.annotation.Order; -import org.springframework.core.env.Environment; - -/** - * spring获取bean工具类 - * - * @author 作者 owen E-mail: 624191343@qq.com - */ -@Order(0) -public class SpringUtil implements ApplicationContextAware { - - private static ApplicationContext applicationContext = null; - - public static T getBean(Class cla) { - return applicationContext.getBean(cla); - } - - public static T getBean(String name, Class cal) { - return applicationContext.getBean(name, cal); - } - - public static String getProperty(String key) { - return applicationContext.getBean(Environment.class).getProperty(key); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) { - SpringUtil.applicationContext = applicationContext; - } -} diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/Oauth2ServerAuthSuccessHandler.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/Oauth2ServerAuthSuccessHandler.java index 1aa677649..a86dd6973 100644 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/Oauth2ServerAuthSuccessHandler.java +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/auth/Oauth2ServerAuthSuccessHandler.java @@ -9,6 +9,7 @@ import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal; import org.springframework.security.web.server.WebFilterExchange; import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler; +import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.server.ServerWebExchange; @@ -26,6 +27,7 @@ * Blog: https://zlt2000.gitee.io * Github: https://github.com/zlt2000 */ +@Component public class Oauth2ServerAuthSuccessHandler implements ServerAuthenticationSuccessHandler { @Override public Mono onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { diff --git a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java index 629d7564c..dcc7373c3 100644 --- a/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java +++ b/zlt-gateway/sc-gateway/src/main/java/com/central/gateway/config/ResourceServerConfiguration.java @@ -1,24 +1,8 @@ package com.central.gateway.config; -import com.central.gateway.auth.*; -import com.central.oauth2.common.component.CustomReactiveAuthorizationServiceIntrospector; -import com.central.oauth2.common.component.CustomServerBearerTokenAuthConverter; -import com.central.oauth2.common.config.BaseSecurityConfig; -import com.central.oauth2.common.properties.SecurityProperties; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Bean; +import com.central.oauth2.common.config.DefaultWebFluxResourceServerConf; + import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.http.HttpMethod; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.config.web.server.SecurityWebFiltersOrder; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenReactiveAuthenticationManager; -import org.springframework.security.web.server.SecurityWebFilterChain; -import org.springframework.security.web.server.ServerAuthenticationEntryPoint; -import org.springframework.security.web.server.authentication.AuthenticationWebFilter; -import org.springframework.security.web.server.authentication.ServerAuthenticationEntryPointFailureHandler; -import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler; /** * 资源服务器 @@ -30,60 +14,6 @@ * Github: https://github.com/zlt2000 */ @Configuration -@EnableWebFluxSecurity -@Slf4j -@Import(BaseSecurityConfig.class) -public class ResourceServerConfiguration { - @Bean - public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http - , SecurityProperties securityProperties, PermissionAuthManager permissionAuthManager - , ServerAuthenticationEntryPoint authenticationEntryPoint, ServerAccessDeniedHandler accessDeniedHandler) { - http.csrf(ServerHttpSecurity.CsrfSpec::disable) - .cors(ServerHttpSecurity.CorsSpec::disable) - .headers(hSpec -> hSpec.frameOptions(ServerHttpSecurity.HeaderSpec.FrameOptionsSpec::disable)) - .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable) - .exceptionHandling(e -> { - e.authenticationEntryPoint(authenticationEntryPoint) - .accessDeniedHandler(accessDeniedHandler); - }); - - http.authorizeExchange(exchange -> { - if (securityProperties.getAuth().getHttpUrls().length > 0) { - exchange.pathMatchers(securityProperties.getAuth().getHttpUrls()).authenticated(); - } - if (securityProperties.getIgnore().getUrls().length > 0) { - exchange.pathMatchers(securityProperties.getIgnore().getUrls()).permitAll(); - } - exchange.pathMatchers(HttpMethod.OPTIONS).permitAll() - .anyExchange().access(permissionAuthManager); - }); - - http.addFilterAt(this.getAuthWebFilter(authenticationEntryPoint, securityProperties) - , SecurityWebFiltersOrder.AUTHENTICATION); - - return http.build(); - } - - private AuthenticationWebFilter getAuthWebFilter(ServerAuthenticationEntryPoint authenticationEntryPoint - , SecurityProperties securityProperties) { - OpaqueTokenReactiveAuthenticationManager authenticationManager = - new OpaqueTokenReactiveAuthenticationManager( - new CustomReactiveAuthorizationServiceIntrospector()); - CustomServerBearerTokenAuthConverter authenticationConverter = - new CustomServerBearerTokenAuthConverter(securityProperties); - authenticationConverter.setAllowUriQueryParameter(true); - - AuthenticationWebFilter oauth2 = new AuthenticationWebFilter(authenticationManager); - oauth2.setServerAuthenticationConverter(authenticationConverter); - oauth2.setAuthenticationFailureHandler(getFailureHandler(authenticationEntryPoint)); - oauth2.setAuthenticationSuccessHandler(new Oauth2ServerAuthSuccessHandler()); - return oauth2; - } +public class ResourceServerConfiguration extends DefaultWebFluxResourceServerConf { - private ServerAuthenticationEntryPointFailureHandler getFailureHandler(ServerAuthenticationEntryPoint authenticationEntryPoint) { - ServerAuthenticationEntryPointFailureHandler failureHandler = - new ServerAuthenticationEntryPointFailureHandler(authenticationEntryPoint); - failureHandler.setRethrowAuthenticationServiceException(false); - return failureHandler; - } } From 2a05c6ab9179b5bb8e471c4c385cf4500473b1be Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Tue, 12 Dec 2023 10:48:32 +0800 Subject: [PATCH 14/23] =?UTF-8?q?feat:=20uaa=E6=94=B9=E9=80=A0=E4=B8=BASpr?= =?UTF-8?q?ing=20Authorization=20Server?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/central/file/config/WebMvcConfig.java | 12 -- .../central/common/config/WebMvcConfig.java | 11 - .../com/central/user/config/WebMvcConfig.java | 12 -- .../user/controller/SysMenuController.java | 11 +- .../user/controller/SysUserController.java | 12 +- .../central/user/mapper/SysMenuMapper.java | 5 +- .../central/user/service/ISysMenuService.java | 2 + .../central/user/service/ISysUserService.java | 11 +- .../user/service/impl/SysMenuServiceImpl.java | 4 + .../user/service/impl/SysUserServiceImpl.java | 33 ++- .../main/resources/mapper/SysMenuMapper.xml | 12 +- .../user/service/SysUserServiceTest.java | 5 +- .../config/DefaultResourceServerConf.java | 1 + .../CustomOAuth2AuthorizationException.java | 17 ++ .../central/oauth2/common/pojo/ClientDto.java | 9 +- .../common/properties/PermitProperties.java | 9 +- .../impl/RedisOAuth2AuthorizationService.java | 63 +++++- .../token/MobileAuthenticationToken.java | 36 ++++ .../token/OpenIdAuthenticationToken.java | 32 +++ .../PasswordCodeAuthenticationToken.java | 42 ++++ .../central/oauth2/common/util/AuthUtils.java | 8 +- .../common/util/OAuth2ConfigurerUtils.java | 197 +++++++++++++++++ zlt-commons/zlt-common-core/pom.xml | 11 +- .../common/annotation/LoginClient.java | 16 -- .../central/common/annotation/LoginUser.java | 21 -- .../common/config/DefaultWebMvcConfig.java | 39 ---- .../common/constant/SecurityConstants.java | 8 +- .../com/central/common/feign/UserService.java | 7 +- .../fallback/UserServiceFallbackFactory.java | 13 +- .../com/central/common/model/SysUser.java | 3 + .../resolver/ClientArgumentResolver.java | 53 ----- .../resolver/TokenArgumentResolver.java | 64 ------ .../central/common/utils/LoginUserUtils.java | 21 +- ...ot.autoconfigure.AutoConfiguration.imports | 3 +- .../java/org/zlt/config/WebMvcConfig.java | 18 -- .../org/zlt/controller/TestController.java | 11 +- .../src/main/resources/application.yml | 6 +- zlt-uaa/pom.xml | 13 -- .../main/java/com/central/UaaServerApp.java | 1 - ...cessTokenResponseHttpMessageConverter.java | 48 +++++ .../CustomeOAuth2TokenCustomizer.java | 35 +++ .../LoginProcessSetTenantFilter.java | 66 ++++++ .../config/AuthorizationServerConfig.java | 151 +++++++++++++ .../config/FormIdentityLoginConfigurer.java | 45 ++++ .../oauth/config/RedisListenerConfig.java | 23 -- .../central/oauth/config/SecurityConfig.java | 144 +++++++++++++ .../central/oauth/config/WebMvcConfig.java | 14 -- .../oauth/controller/ClientController.java | 23 +- .../oauth/controller/TokensController.java | 35 +++ .../java/com/central/oauth/dto/ClientDto.java | 18 -- .../CustomOAuth2AuthenticationException.java | 2 +- .../exception/ValidateCodeException.java | 15 -- .../oauth/handler/OauthLogoutHandler.java | 50 +++++ .../handler/OauthLogoutSuccessHandler.java | 51 +++++ .../java/com/central/oauth/model/Client.java | 9 +- .../SupplierDeferredSecurityContext.java | 54 +++++ .../central/oauth/service/IClientService.java | 5 +- .../oauth/service/impl/ClientServiceImpl.java | 34 +-- .../CustomRegisteredClientRepository.java | 90 ++++++++ ...edisOAuth2AuthorizationConsentService.java | 55 +++++ .../impl/RedisSecurityContextRepository.java | 138 ++++++++++++ .../service/impl/RedisTokensServiceImpl.java | 102 +++++++++ .../service/impl/RegisteredClientService.java | 89 ++++++++ .../service/impl/UnifiedLogoutService.java | 125 +++++++++++ .../impl/UserDetailServiceFactory.java | 53 +++++ .../service/impl/UserDetailServiceImpl.java | 25 ++- .../service/impl/ValidateCodeServiceImpl.java | 44 ++-- .../base/BaseAuthenticationConverter.java | 88 ++++++++ .../base/BaseAuthenticationProvider.java | 201 ++++++++++++++++++ .../mobile/MobileAuthenticationConverter.java | 38 ++++ .../mobile/MobileAuthenticationProvider.java | 67 ++++++ .../openid/OpenIdAuthenticationConverter.java | 36 ++++ .../openid/OpenIdAuthenticationProvider.java | 63 ++++++ .../PasswordAuthenticationConverter.java | 36 ++++ .../PasswordAuthenticationProvider.java | 71 +++++++ .../PasswordCodeAuthenticationConverter.java | 41 ++++ .../PasswordCodeAuthenticationProvider.java | 81 +++++++ .../oauth/utils/OAuth2ConfigurerUtils.java | 197 +++++++++++++++++ .../oauth/utils/OAuthEndpointUtils.java | 94 ++++++++ .../central/oauth/utils/UsernameHolder.java | 25 +++ zlt-uaa/src/main/resources/application.yml | 4 - 81 files changed, 2917 insertions(+), 520 deletions(-) delete mode 100644 zlt-business/file-center/src/main/java/com/central/file/config/WebMvcConfig.java delete mode 100644 zlt-business/search-center/search-server/src/main/java/com/central/common/config/WebMvcConfig.java delete mode 100644 zlt-business/user-center/src/main/java/com/central/user/config/WebMvcConfig.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/exception/CustomOAuth2AuthorizationException.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/MobileAuthenticationToken.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/OpenIdAuthenticationToken.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/PasswordCodeAuthenticationToken.java create mode 100644 zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/OAuth2ConfigurerUtils.java delete mode 100644 zlt-commons/zlt-common-core/src/main/java/com/central/common/annotation/LoginClient.java delete mode 100644 zlt-commons/zlt-common-core/src/main/java/com/central/common/annotation/LoginUser.java delete mode 100644 zlt-commons/zlt-common-core/src/main/java/com/central/common/config/DefaultWebMvcConfig.java delete mode 100644 zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/ClientArgumentResolver.java delete mode 100644 zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/TokenArgumentResolver.java delete mode 100644 zlt-demo/resources-server-demo/src/main/java/org/zlt/config/WebMvcConfig.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/component/CustomAccessTokenResponseHttpMessageConverter.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/component/CustomeOAuth2TokenCustomizer.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/component/LoginProcessSetTenantFilter.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/config/FormIdentityLoginConfigurer.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/config/RedisListenerConfig.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/config/WebMvcConfig.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/controller/TokensController.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/dto/ClientDto.java rename {zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common => zlt-uaa/src/main/java/com/central/oauth}/exception/CustomOAuth2AuthenticationException.java (91%) delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/exception/ValidateCodeException.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutHandler.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutSuccessHandler.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/model/SupplierDeferredSecurityContext.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/CustomRegisteredClientRepository.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisOAuth2AuthorizationConsentService.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisSecurityContextRepository.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/RegisteredClientService.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/UnifiedLogoutService.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceFactory.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/support/base/BaseAuthenticationConverter.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/support/base/BaseAuthenticationProvider.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/support/mobile/MobileAuthenticationConverter.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/support/mobile/MobileAuthenticationProvider.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/support/openid/OpenIdAuthenticationConverter.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/support/openid/OpenIdAuthenticationProvider.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/support/password/PasswordAuthenticationConverter.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/support/password/PasswordAuthenticationProvider.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/support/passwordCode/PasswordCodeAuthenticationConverter.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/support/passwordCode/PasswordCodeAuthenticationProvider.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/utils/OAuth2ConfigurerUtils.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/utils/OAuthEndpointUtils.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/utils/UsernameHolder.java diff --git a/zlt-business/file-center/src/main/java/com/central/file/config/WebMvcConfig.java b/zlt-business/file-center/src/main/java/com/central/file/config/WebMvcConfig.java deleted file mode 100644 index c4dc350f7..000000000 --- a/zlt-business/file-center/src/main/java/com/central/file/config/WebMvcConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.central.file.config; - -import com.central.common.config.DefaultWebMvcConfig; -import org.springframework.context.annotation.Configuration; - -/** - * @author zlt - * @date 2019/8/5 - */ -@Configuration -public class WebMvcConfig extends DefaultWebMvcConfig { -} diff --git a/zlt-business/search-center/search-server/src/main/java/com/central/common/config/WebMvcConfig.java b/zlt-business/search-center/search-server/src/main/java/com/central/common/config/WebMvcConfig.java deleted file mode 100644 index b7b56bf32..000000000 --- a/zlt-business/search-center/search-server/src/main/java/com/central/common/config/WebMvcConfig.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.central.common.config; - -import org.springframework.context.annotation.Configuration; - -/** - * @author zlt - * @date 2019/8/5 - */ -@Configuration -public class WebMvcConfig extends DefaultWebMvcConfig { -} diff --git a/zlt-business/user-center/src/main/java/com/central/user/config/WebMvcConfig.java b/zlt-business/user-center/src/main/java/com/central/user/config/WebMvcConfig.java deleted file mode 100644 index 4db93cde8..000000000 --- a/zlt-business/user-center/src/main/java/com/central/user/config/WebMvcConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.central.user.config; - -import com.central.common.config.DefaultWebMvcConfig; -import org.springframework.context.annotation.Configuration; - -/** - * @author zlt - * @date 2019/8/5 - */ -@Configuration -public class WebMvcConfig extends DefaultWebMvcConfig { -} diff --git a/zlt-business/user-center/src/main/java/com/central/user/controller/SysMenuController.java b/zlt-business/user-center/src/main/java/com/central/user/controller/SysMenuController.java index dfe8727c3..3ad3081e7 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/controller/SysMenuController.java +++ b/zlt-business/user-center/src/main/java/com/central/user/controller/SysMenuController.java @@ -3,10 +3,8 @@ import java.util.*; import java.util.stream.Collectors; -import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; -import com.central.common.annotation.LoginUser; import com.central.common.constant.CommonConstant; import com.central.common.context.LoginUserContextHolder; import com.central.common.model.*; @@ -165,12 +163,9 @@ public Result saveOrUpdate(@RequestBody SysMenu menu) { */ @GetMapping("/current") @Operation(summary = "查询当前用户菜单") - public List findMyMenu(@LoginUser SysUser user) { - List roles = user.getRoles(); - if (CollectionUtil.isEmpty(roles)) { - return Collections.emptyList(); - } - List menus = menuService.findByRoleCodes(roles.stream().map(SysRole::getCode).collect(Collectors.toSet()), CommonConstant.MENU); + public List findMyMenu() { + LoginAppUser user = LoginUserContextHolder.getUser(); + List menus = menuService.findByUserId(user.getId(), CommonConstant.MENU); return treeBuilder(menus); } } diff --git a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java index 25b95550c..55c1e86f6 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java +++ b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java @@ -8,10 +8,10 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; -import com.central.common.annotation.LoginUser; import com.central.common.constant.CommonConstant; import com.central.common.model.*; import com.central.common.utils.ExcelUtil; +import com.central.common.utils.LoginUserUtils; import com.central.log.annotation.AuditLog; import com.central.search.client.service.IQueryService; import com.central.search.model.LogicDelDto; @@ -65,8 +65,8 @@ public class SysUserController { */ @Operation(summary = "根据access_token当前登录用户") @GetMapping("/users/current") - public Result getLoginAppUser(@LoginUser(isFull = true) SysUser user) { - return Result.succeed(appUserService.getLoginAppUser(user)); + public Result getLoginAppUser() { + return Result.succeed(LoginUserUtils.getCurrentUser(true)); } /** @@ -84,7 +84,7 @@ public SysUser selectByUsername(@PathVariable String username) { */ @GetMapping(value = "/users-anon/login", params = "username") @Operation(summary = "根据用户名查询用户") - public LoginAppUser findByUsername(String username) { + public SysUser findByUsername(String username) { return appUserService.findByUsername(username); } @@ -95,7 +95,7 @@ public LoginAppUser findByUsername(String username) { */ @GetMapping(value = "/users-anon/mobile", params = "mobile") @Operation(summary = "根据手机号查询用户") - public LoginAppUser findByMobile(String mobile) { + public SysUser findByMobile(String mobile) { return appUserService.findByMobile(mobile); } @@ -106,7 +106,7 @@ public LoginAppUser findByMobile(String mobile) { */ @GetMapping(value = "/users-anon/openId", params = "openId") @Operation(summary = "根据OpenId查询用户") - public LoginAppUser findByOpenId(String openId) { + public SysUser findByOpenId(String openId) { return appUserService.findByOpenId(openId); } diff --git a/zlt-business/user-center/src/main/java/com/central/user/mapper/SysMenuMapper.java b/zlt-business/user-center/src/main/java/com/central/user/mapper/SysMenuMapper.java index 3d86269df..300bb67b1 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/mapper/SysMenuMapper.java +++ b/zlt-business/user-center/src/main/java/com/central/user/mapper/SysMenuMapper.java @@ -3,6 +3,9 @@ import com.central.db.mapper.SuperMapper; import com.central.common.model.SysMenu; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; /** * 菜单 @@ -11,5 +14,5 @@ */ @Mapper public interface SysMenuMapper extends SuperMapper { - + List findByUserId(@Param("userId") Long userId, @Param("type") Integer type); } diff --git a/zlt-business/user-center/src/main/java/com/central/user/service/ISysMenuService.java b/zlt-business/user-center/src/main/java/com/central/user/service/ISysMenuService.java index 39e94b891..8fa713c6f 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/service/ISysMenuService.java +++ b/zlt-business/user-center/src/main/java/com/central/user/service/ISysMenuService.java @@ -34,6 +34,8 @@ public interface ISysMenuService extends ISuperService { */ List findByRoles(Set roleIds); + List findByUserId(Long userId, Integer type); + /** * 角色菜单列表 * @param roleIds 角色ids diff --git a/zlt-business/user-center/src/main/java/com/central/user/service/ISysUserService.java b/zlt-business/user-center/src/main/java/com/central/user/service/ISysUserService.java index 813c02ef4..bd1a301ea 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/service/ISysUserService.java +++ b/zlt-business/user-center/src/main/java/com/central/user/service/ISysUserService.java @@ -8,7 +8,6 @@ import com.central.user.model.SysUserExcel; import com.central.common.model.PageResult; import com.central.common.model.Result; -import com.central.common.model.LoginAppUser; import com.central.common.model.SysRole; import com.central.common.model.SysUser; @@ -24,18 +23,18 @@ public interface ISysUserService extends ISuperService { * @param username * @return */ - LoginAppUser findByUsername(String username); + SysUser findByUsername(String username); - LoginAppUser findByOpenId(String username); + SysUser findByOpenId(String username); - LoginAppUser findByMobile(String username); + SysUser findByMobile(String username); /** - * 通过SysUser 转换为 LoginAppUser,把roles和permissions也查询出来 + * 通过SysUser 把roles和permissions也查询出来 * @param sysUser * @return */ - LoginAppUser getLoginAppUser(SysUser sysUser); + void setUserPermission(SysUser sysUser); /** * 根据用户名查询用户 diff --git a/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysMenuServiceImpl.java b/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysMenuServiceImpl.java index 7501b3299..6dcc8f3df 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysMenuServiceImpl.java +++ b/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysMenuServiceImpl.java @@ -66,6 +66,10 @@ public List findByRoles(Set roleIds, Integer type) { public List findByRoleCodes(Set roleCodes, Integer type) { return roleMenuService.findMenusByRoleCodes(roleCodes, type); } + @Override + public List findByUserId(Long userId, Integer type) { + return baseMapper.findByUserId(userId, type); + } /** * 查询所有菜单 diff --git a/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java b/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java index 10d8966dd..47cfa2333 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java +++ b/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java @@ -21,8 +21,6 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -55,48 +53,43 @@ public class SysUserServiceImpl extends SuperServiceImpl private DistributedLock lock; @Override - public LoginAppUser findByUsername(String username) { + public SysUser findByUsername(String username) { SysUser sysUser = this.selectByUsername(username); - return getLoginAppUser(sysUser); + setUserPermission(sysUser); + return sysUser; } @Override - public LoginAppUser findByOpenId(String username) { + public SysUser findByOpenId(String username) { SysUser sysUser = this.selectByOpenId(username); - return getLoginAppUser(sysUser); + setUserPermission(sysUser); + return sysUser; } @Override - public LoginAppUser findByMobile(String username) { + public SysUser findByMobile(String username) { SysUser sysUser = this.selectByMobile(username); - return getLoginAppUser(sysUser); + setUserPermission(sysUser); + return sysUser; } @Override - public LoginAppUser getLoginAppUser(SysUser sysUser) { + public void setUserPermission(SysUser sysUser) { if (sysUser != null) { List sysRoles = roleUserService.findRolesByUserId(sysUser.getId()); - Collection authorities = new HashSet<>(); - if (sysRoles != null) { - sysRoles.forEach(role -> authorities.add(new SimpleGrantedAuthority(role.getCode()))); - } + sysUser.setRoles(sysRoles); - Set permissions = null; + Set permissions; if (!CollectionUtils.isEmpty(sysRoles)) { Set roleIds = sysRoles.stream().map(SuperEntity::getId).collect(Collectors.toSet()); List menus = roleMenuMapper.findMenusByRoleIds(roleIds, CommonConstant.PERMISSION); if (!CollectionUtils.isEmpty(menus)) { permissions = menus.stream().map(p -> p.getPath()) .collect(Collectors.toSet()); + sysUser.setPermissions(permissions); } } - return new LoginAppUser(sysUser.getId() - , sysUser.getUsername(), sysUser.getPassword() - , sysUser.getMobile(), permissions - , sysUser.getEnabled(), true, true, true - , authorities); } - return null; } /** diff --git a/zlt-business/user-center/src/main/resources/mapper/SysMenuMapper.xml b/zlt-business/user-center/src/main/resources/mapper/SysMenuMapper.xml index d8e799b58..6ef39518d 100644 --- a/zlt-business/user-center/src/main/resources/mapper/SysMenuMapper.xml +++ b/zlt-business/user-center/src/main/resources/mapper/SysMenuMapper.xml @@ -2,5 +2,15 @@ - + \ No newline at end of file diff --git a/zlt-business/user-center/src/test/java/com/central/user/service/SysUserServiceTest.java b/zlt-business/user-center/src/test/java/com/central/user/service/SysUserServiceTest.java index 372d793aa..55782585f 100644 --- a/zlt-business/user-center/src/test/java/com/central/user/service/SysUserServiceTest.java +++ b/zlt-business/user-center/src/test/java/com/central/user/service/SysUserServiceTest.java @@ -1,6 +1,5 @@ package com.central.user.service; -import com.central.common.model.LoginAppUser; import static org.assertj.core.api.Assertions.*; import com.central.common.model.PageResult; @@ -27,8 +26,8 @@ public class SysUserServiceTest { @Test public void testFindByUsername() { - LoginAppUser loginAppUser = sysUserService.findByUsername("admin"); - assertThat(loginAppUser).isNotNull(); + SysUser sysUser = sysUserService.findByUsername("admin"); + assertThat(sysUser).isNotNull(); } @Test diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java index 8ef191f8e..9fb0101c3 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/config/DefaultResourceServerConf.java @@ -56,6 +56,7 @@ public SecurityFilterChain springSecurityFilterChain(HttpSecurity http) throws E // 避免iframe同源无法登录许iframe .frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin) ).csrf(AbstractHttpConfigurer::disable) + .cors(AbstractHttpConfigurer::disable) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)); diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/exception/CustomOAuth2AuthorizationException.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/exception/CustomOAuth2AuthorizationException.java new file mode 100644 index 000000000..7f58baf14 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/exception/CustomOAuth2AuthorizationException.java @@ -0,0 +1,17 @@ +package com.central.oauth2.common.exception; + +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2Error; + +/** + * @author: zlt + * @date: 2023/12/10 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class CustomOAuth2AuthorizationException extends OAuth2AuthenticationException { + public CustomOAuth2AuthorizationException(String msg) { + super(new OAuth2Error(msg), msg); + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java index 22fb003fb..18ea9897e 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java @@ -35,14 +35,11 @@ public class ClientDto implements Serializable { private Integer refreshTokenValiditySeconds = 28800; private String additionalInformation = "{}"; private String autoapprove = "true"; + /** - * 是否支持id_token - */ - private Boolean supportIdToken = true; - /** - * id_token有效时间(s) + * token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt)) */ - private Integer idTokenValiditySeconds = 60; + private String tokenFormat = "reference"; private Long creatorId; } diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/PermitProperties.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/PermitProperties.java index c861a3092..1d547b1af 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/PermitProperties.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/PermitProperties.java @@ -1,5 +1,6 @@ package com.central.oauth2.common.properties; +import com.central.common.constant.SecurityConstants; import lombok.Getter; import lombok.Setter; @@ -23,11 +24,11 @@ public class PermitProperties { * 监控中心和swagger需要访问的url */ private static final String[] ENDPOINTS = { - "/login.html", "/validata/code/**", - "/v3/api-docs/**", "/*/v3/api-docs/**", - "/doc.html", "/swagger-ui.html", "/swagger-ui/**", + SecurityConstants.LOGIN_PAGE, + SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX + "/**", + "/doc.html", "/swagger-ui.html", "/v3/api-docs/**", "/swagger-ui/**", "/actuator/**", "/webjars/**", "/druid/**", - "/css/**", "/js/**", "/images/**", "/favicon.ico", "/error", + "/css/**", "/js/**", "/images/**", "/favicon.ico", "/error" }; /** diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/RedisOAuth2AuthorizationService.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/RedisOAuth2AuthorizationService.java index 666baeece..509dd632c 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/RedisOAuth2AuthorizationService.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/service/impl/RedisOAuth2AuthorizationService.java @@ -6,6 +6,7 @@ import com.central.oauth2.common.token.CustomAccessToken; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.redisson.api.ExpiredObjectListener; import org.redisson.api.RBucket; import org.redisson.api.RList; import org.redisson.api.RedissonClient; @@ -28,6 +29,11 @@ import java.util.*; /** + * 实现 Redis 存储 OAuth2Authorization 对象 + * 1. 自动续签token(可配置是否开启) + * 2. 增加 client_id_to_access 和 uname_to_access 两个集合,用于查看在线用户 + * 3. 增加过期监听,删除 client_id_to_access 和 uname_to_access 集合的值 + * * @author: zlt * @date: 2023/11/9 *

@@ -38,7 +44,7 @@ @RequiredArgsConstructor public class RedisOAuth2AuthorizationService implements OAuth2AuthorizationService { private final static SerializationCodec AUTH_CODEC = new SerializationCodec(); - private final static Long TIMEOUT = 10L; + private final static Long STATE_TIMEOUT_MINUTES = 10L; private static final String AUTHORIZATION = "token"; @@ -46,11 +52,32 @@ public class RedisOAuth2AuthorizationService implements OAuth2AuthorizationServi private final RedissonClient redisson; + private final ExpiredObjectListener expiredObjectListener = new ExpiredObjectListener() { + private final static String KEY_SPLIT = "::"; + /** + * redis 失效监听,删除集合里的值 + * 在 redis.conf 文件中,确保以下设置是启用的:notify-keyspace-events Ex + * 监听的key格式为:token::access_token::${clientId}::${username}::${access_token} + * 例如:token::access_token::webApp::admin::q7ySjsjZoinAx0zUJADqV9P1VmCwYmQDdemwOuhDHjNXVmkzkvquMk_vUBX_Yz40JModOhUwixu-ICH5hti50-KXngBgkn_V1pxu-PZ1YGNkBIDXneE0z4WYx6uFIVHS + */ + @Override + public void onExpired(String name) { + String[] keyArr = name.split(KEY_SPLIT); + if (keyArr.length == 5) { + String clientId = keyArr[2]; + String username = keyArr[3]; + String accessToken = keyArr[4]; + redisListDelete(getClientIdListKey(clientId), accessToken); + redisListDelete(getUnameListKey(clientId, username), accessToken); + } + } + }; + @Override public void save(OAuth2Authorization authorization) { if (isState(authorization)) { String token = authorization.getAttribute("state"); - this.redisBucketSet(OAuth2ParameterNames.STATE, token, authorization, Duration.ofMinutes(TIMEOUT)); + this.redisBucketSet(OAuth2ParameterNames.STATE, token, authorization, Duration.ofMinutes(STATE_TIMEOUT_MINUTES)); } if (isCode(authorization)) { @@ -76,9 +103,22 @@ public void save(OAuth2Authorization authorization) { } private Duration saveAccessToken(OAuth2Authorization authorization) { + return this.saveAccessToken(authorization, false); + } + + private Duration saveAccessToken(OAuth2Authorization authorization, boolean isRenew) { OAuth2AccessToken accessToken = authorization.getAccessToken().getToken(); Duration duration = this.getExpireSeconds(accessToken); this.redisBucketSet(OAuth2ParameterNames.ACCESS_TOKEN, accessToken.getTokenValue(), authorization, duration); + RBucket listenKeyBucket = redisson.getBucket(buildListenerKey( + OAuth2ParameterNames.ACCESS_TOKEN, authorization.getRegisteredClientId() + , authorization.getPrincipalName(), accessToken.getTokenValue())); + if (!isRenew) { + listenKeyBucket.set(1, duration); + listenKeyBucket.addListener(expiredObjectListener); + } else { + listenKeyBucket.expire(duration); + } return duration; } @@ -94,7 +134,7 @@ public void remove(OAuth2Authorization authorization) { if (isCode(authorization)) { OAuth2Authorization.Token authorizationCode = authorization - .getToken(OAuth2AuthorizationCode.class); + .getToken(OAuth2AuthorizationCode.class); OAuth2AuthorizationCode authorizationCodeToken = authorizationCode.getToken(); keys.add(buildKey(OAuth2ParameterNames.CODE, authorizationCodeToken.getTokenValue())); } @@ -154,13 +194,17 @@ private String buildKey(String type, String id) { return String.format("%s::%s::%s", AUTHORIZATION, type, id); } + private String buildListenerKey(String type, String clientId, String username, String tokenValue) { + return String.format("%s::%s::%s::%s::%s", AUTHORIZATION, type, clientId, username, tokenValue); + } + private static boolean isState(OAuth2Authorization authorization) { return Objects.nonNull(authorization.getAttribute("state")); } private static boolean isCode(OAuth2Authorization authorization) { OAuth2Authorization.Token authorizationCode = authorization - .getToken(OAuth2AuthorizationCode.class); + .getToken(OAuth2AuthorizationCode.class); return Objects.nonNull(authorizationCode); } @@ -228,10 +272,6 @@ private long getAccessTokenValiditySeconds(String clientId) { return SecurityConstants.ACCESS_TOKEN_VALIDITY_SECONDS; } - private String clientRedisKey(String clientId) { - return SecurityConstants.CACHE_CLIENT_KEY + ":" + clientId; - } - /** * 更新 access_token 的过期时间 */ @@ -247,7 +287,7 @@ private void updateAccessTokenExpiresAt(OAuth2Authorization authorization, long Map, OAuth2Authorization.Token> newTokens = new HashMap<>(tokens); newTokens.put(OAuth2AccessToken.class, newToken); tokensField.set(authorization, Collections.unmodifiableMap(newTokens)); - this.saveAccessToken(authorization); + this.saveAccessToken(authorization, true); // 更新集合中的过期时间 this.updateListExpiresAt(this.getClientIdListKey(authorization), Duration.ofSeconds(validitySeconds)); this.updateListExpiresAt(this.getUnameListKey(authorization), Duration.ofSeconds(validitySeconds)); @@ -286,7 +326,6 @@ private Duration getExpireSeconds(OAuth2Token oAuth2Token) { private RBucket redisBucketSet(String type, String id, OAuth2Authorization value, Duration duration) { RBucket rBucket = redisson.getBucket(buildKey(type, id), AUTH_CODEC); rBucket.set(value, duration); - return rBucket; } @@ -319,4 +358,8 @@ private RList redisListDelete(String key, String value) { rList.remove(value); return rList; } + + private String clientRedisKey(String clientId) { + return SecurityConstants.CACHE_CLIENT_KEY + ":" + clientId; + } } diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/MobileAuthenticationToken.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/MobileAuthenticationToken.java new file mode 100644 index 000000000..d51804c2d --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/MobileAuthenticationToken.java @@ -0,0 +1,36 @@ +package com.central.oauth2.common.token; + +import lombok.Getter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.AuthorizationGrantType; + +import java.util.Collection; + +/** + * @author: zlt + * @date: 2023/11/10 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Getter +public class MobileAuthenticationToken extends BaseAuthenticationToken { + public static final AuthorizationGrantType GRANT_TYPE = new AuthorizationGrantType("mobile_password"); + + private final Object principal; + private final String credentials; + + public MobileAuthenticationToken(String mobile, String password) { + super(GRANT_TYPE); + this.principal = mobile; + this.credentials = password; + super.setAuthenticated(true); + } + + public MobileAuthenticationToken(UserDetails user, String password, Collection authorities) { + super(authorities); + this.principal = user; + this.credentials = password; + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/OpenIdAuthenticationToken.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/OpenIdAuthenticationToken.java new file mode 100644 index 000000000..e1e7469d5 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/OpenIdAuthenticationToken.java @@ -0,0 +1,32 @@ +package com.central.oauth2.common.token; + +import lombok.Getter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.AuthorizationGrantType; + +import java.util.Collection; + +/** + * @author: zlt + * @date: 2023/11/18 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Getter +public class OpenIdAuthenticationToken extends BaseAuthenticationToken { + public static final AuthorizationGrantType GRANT_TYPE = new AuthorizationGrantType("openId"); + private final Object principal; + + public OpenIdAuthenticationToken(String openId) { + super(GRANT_TYPE); + this.principal = openId; + super.setAuthenticated(true); + } + + public OpenIdAuthenticationToken(UserDetails principal, Collection authorities) { + super(authorities); + this.principal = principal; + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/PasswordCodeAuthenticationToken.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/PasswordCodeAuthenticationToken.java new file mode 100644 index 000000000..e27c0e118 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/token/PasswordCodeAuthenticationToken.java @@ -0,0 +1,42 @@ +package com.central.oauth2.common.token; + +import lombok.Getter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.AuthorizationGrantType; + +import java.util.Collection; + +/** + * @author: zlt + * @date: 2023/11/18 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Getter +public class PasswordCodeAuthenticationToken extends BaseAuthenticationToken { + public static final AuthorizationGrantType GRANT_TYPE = new AuthorizationGrantType("password_code"); + private final Object principal; + private final String credentials; + private final String deviceId; + private final String validCode; + + public PasswordCodeAuthenticationToken(String username, String password, String deviceId, String validCode) { + super(GRANT_TYPE); + this.principal = username; + this.credentials = password; + this.deviceId = deviceId; + this.validCode = validCode; + super.setAuthenticated(true); + } + + public PasswordCodeAuthenticationToken(UserDetails user, String password, String deviceId + , Collection authorities) { + super(authorities); + this.principal = user; + this.credentials = password; + this.deviceId = deviceId; + this.validCode = null; + } +} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java index 75399d9ae..c9e8f050b 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/AuthUtils.java @@ -5,7 +5,7 @@ import com.central.common.constant.SecurityConstants; import com.central.common.model.LoginAppUser; import com.central.common.utils.LoginUserUtils; -import com.central.oauth2.common.exception.CustomOAuth2AuthenticationException; +import com.central.oauth2.common.exception.CustomOAuth2AuthorizationException; import com.central.oauth2.common.token.BaseAuthenticationToken; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; @@ -115,7 +115,7 @@ public static OAuth2Authorization checkAccessTokenToAuth(String accessTokenValue public static String[] extractClient(HttpServletRequest request) { String header = request.getHeader("Authorization"); if (header == null || !header.startsWith(BASIC_)) { - throw new CustomOAuth2AuthenticationException("The client information in the request header is empty"); + throw new CustomOAuth2AuthorizationException("The client information in the request header is empty"); } return extractHeaderClient(header); } @@ -123,7 +123,7 @@ public static String[] extractClient(HttpServletRequest request) { public static String extractClientId(HttpServletRequest request) { String header = request.getHeader("Authorization"); if (header == null || !header.startsWith(BASIC_)) { - throw new CustomOAuth2AuthenticationException("The client information in the request header is empty"); + throw new CustomOAuth2AuthorizationException("The client information in the request header is empty"); } String[] clientArr = extractHeaderClient(header); return clientArr[0]; @@ -140,7 +140,7 @@ public static String[] extractHeaderClient(String header) { String clientStr = new String(decoded, StandardCharsets.UTF_8); String[] clientArr = clientStr.split(":"); if (clientArr.length != 2) { - throw new CustomOAuth2AuthenticationException("Invalid basic authentication token"); + throw new CustomOAuth2AuthorizationException("Invalid basic authentication token"); } return clientArr; } diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/OAuth2ConfigurerUtils.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/OAuth2ConfigurerUtils.java new file mode 100644 index 000000000..08366b1d1 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/OAuth2ConfigurerUtils.java @@ -0,0 +1,197 @@ +package com.central.oauth2.common.util; + +import com.nimbusds.jose.jwk.source.JWKSource; +import com.nimbusds.jose.proc.SecurityContext; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.context.ApplicationContext; +import org.springframework.core.ResolvableType; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.core.OAuth2Token; +import org.springframework.security.oauth2.jwt.JwtEncoder; +import org.springframework.security.oauth2.jwt.NimbusJwtEncoder; +import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationConsentService; +import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository; +import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings; +import org.springframework.security.oauth2.server.authorization.token.*; +import org.springframework.util.StringUtils; + +import java.util.Map; + +/** + * @author: zlt + * @date: 2023/11/16 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class OAuth2ConfigurerUtils { + private OAuth2ConfigurerUtils() { + } + + public static RegisteredClientRepository getRegisteredClientRepository(HttpSecurity httpSecurity) { + RegisteredClientRepository registeredClientRepository = httpSecurity.getSharedObject(RegisteredClientRepository.class); + if (registeredClientRepository == null) { + registeredClientRepository = getBean(httpSecurity, RegisteredClientRepository.class); + httpSecurity.setSharedObject(RegisteredClientRepository.class, registeredClientRepository); + } + return registeredClientRepository; + } + + public static OAuth2AuthorizationService getAuthorizationService(HttpSecurity httpSecurity) { + OAuth2AuthorizationService authorizationService = httpSecurity.getSharedObject(OAuth2AuthorizationService.class); + if (authorizationService == null) { + authorizationService = getOptionalBean(httpSecurity, OAuth2AuthorizationService.class); + if (authorizationService == null) { + authorizationService = new InMemoryOAuth2AuthorizationService(); + } + httpSecurity.setSharedObject(OAuth2AuthorizationService.class, authorizationService); + } + return authorizationService; + } + + public static OAuth2AuthorizationConsentService getAuthorizationConsentService(HttpSecurity httpSecurity) { + OAuth2AuthorizationConsentService authorizationConsentService = httpSecurity.getSharedObject(OAuth2AuthorizationConsentService.class); + if (authorizationConsentService == null) { + authorizationConsentService = getOptionalBean(httpSecurity, OAuth2AuthorizationConsentService.class); + if (authorizationConsentService == null) { + authorizationConsentService = new InMemoryOAuth2AuthorizationConsentService(); + } + httpSecurity.setSharedObject(OAuth2AuthorizationConsentService.class, authorizationConsentService); + } + return authorizationConsentService; + } + + @SuppressWarnings("unchecked") + public static OAuth2TokenGenerator getTokenGenerator(HttpSecurity httpSecurity) { + OAuth2TokenGenerator tokenGenerator = httpSecurity.getSharedObject(OAuth2TokenGenerator.class); + if (tokenGenerator == null) { + tokenGenerator = getOptionalBean(httpSecurity, OAuth2TokenGenerator.class); + if (tokenGenerator == null) { + JwtGenerator jwtGenerator = getJwtGenerator(httpSecurity); + OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator(); + OAuth2TokenCustomizer accessTokenCustomizer = getAccessTokenCustomizer(httpSecurity); + if (accessTokenCustomizer != null) { + accessTokenGenerator.setAccessTokenCustomizer(accessTokenCustomizer); + } + OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator(); + if (jwtGenerator != null) { + tokenGenerator = new DelegatingOAuth2TokenGenerator( + jwtGenerator, accessTokenGenerator, refreshTokenGenerator); + } else { + tokenGenerator = new DelegatingOAuth2TokenGenerator( + accessTokenGenerator, refreshTokenGenerator); + } + } + httpSecurity.setSharedObject(OAuth2TokenGenerator.class, tokenGenerator); + } + return tokenGenerator; + } + + private static JwtGenerator getJwtGenerator(HttpSecurity httpSecurity) { + JwtGenerator jwtGenerator = httpSecurity.getSharedObject(JwtGenerator.class); + if (jwtGenerator == null) { + JwtEncoder jwtEncoder = getJwtEncoder(httpSecurity); + if (jwtEncoder != null) { + jwtGenerator = new JwtGenerator(jwtEncoder); + OAuth2TokenCustomizer jwtCustomizer = getJwtCustomizer(httpSecurity); + if (jwtCustomizer != null) { + jwtGenerator.setJwtCustomizer(jwtCustomizer); + } + httpSecurity.setSharedObject(JwtGenerator.class, jwtGenerator); + } + } + return jwtGenerator; + } + + private static JwtEncoder getJwtEncoder(HttpSecurity httpSecurity) { + JwtEncoder jwtEncoder = httpSecurity.getSharedObject(JwtEncoder.class); + if (jwtEncoder == null) { + jwtEncoder = getOptionalBean(httpSecurity, JwtEncoder.class); + if (jwtEncoder == null) { + JWKSource jwkSource = getJwkSource(httpSecurity); + if (jwkSource != null) { + jwtEncoder = new NimbusJwtEncoder(jwkSource); + } + } + if (jwtEncoder != null) { + httpSecurity.setSharedObject(JwtEncoder.class, jwtEncoder); + } + } + return jwtEncoder; + } + + @SuppressWarnings("unchecked") + public static JWKSource getJwkSource(HttpSecurity httpSecurity) { + JWKSource jwkSource = httpSecurity.getSharedObject(JWKSource.class); + if (jwkSource == null) { + ResolvableType type = ResolvableType.forClassWithGenerics(JWKSource.class, SecurityContext.class); + jwkSource = getOptionalBean(httpSecurity, type); + if (jwkSource != null) { + httpSecurity.setSharedObject(JWKSource.class, jwkSource); + } + } + return jwkSource; + } + + private static OAuth2TokenCustomizer getJwtCustomizer(HttpSecurity httpSecurity) { + ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2TokenCustomizer.class, JwtEncodingContext.class); + return getOptionalBean(httpSecurity, type); + } + + private static OAuth2TokenCustomizer getAccessTokenCustomizer(HttpSecurity httpSecurity) { + ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2TokenCustomizer.class, OAuth2TokenClaimsContext.class); + return getOptionalBean(httpSecurity, type); + } + + public static AuthorizationServerSettings getAuthorizationServerSettings(HttpSecurity httpSecurity) { + AuthorizationServerSettings authorizationServerSettings = httpSecurity.getSharedObject(AuthorizationServerSettings.class); + if (authorizationServerSettings == null) { + authorizationServerSettings = getBean(httpSecurity, AuthorizationServerSettings.class); + httpSecurity.setSharedObject(AuthorizationServerSettings.class, authorizationServerSettings); + } + return authorizationServerSettings; + } + + public static T getBean(HttpSecurity httpSecurity, Class type) { + return httpSecurity.getSharedObject(ApplicationContext.class).getBean(type); + } + + @SuppressWarnings("unchecked") + public static T getBean(HttpSecurity httpSecurity, ResolvableType type) { + ApplicationContext context = httpSecurity.getSharedObject(ApplicationContext.class); + String[] names = context.getBeanNamesForType(type); + if (names.length == 1) { + return (T) context.getBean(names[0]); + } + if (names.length > 1) { + throw new NoUniqueBeanDefinitionException(type, names); + } + throw new NoSuchBeanDefinitionException(type); + } + + public static T getOptionalBean(HttpSecurity httpSecurity, Class type) { + Map beansMap = BeanFactoryUtils.beansOfTypeIncludingAncestors( + httpSecurity.getSharedObject(ApplicationContext.class), type); + if (beansMap.size() > 1) { + throw new NoUniqueBeanDefinitionException(type, beansMap.size(), + "Expected single matching bean of type '" + type.getName() + "' but found " + + beansMap.size() + ": " + StringUtils.collectionToCommaDelimitedString(beansMap.keySet())); + } + return (!beansMap.isEmpty() ? beansMap.values().iterator().next() : null); + } + + @SuppressWarnings("unchecked") + public static T getOptionalBean(HttpSecurity httpSecurity, ResolvableType type) { + ApplicationContext context = httpSecurity.getSharedObject(ApplicationContext.class); + String[] names = context.getBeanNamesForType(type); + if (names.length > 1) { + throw new NoUniqueBeanDefinitionException(type, names); + } + return names.length == 1 ? (T) context.getBean(names[0]) : null; + } +} diff --git a/zlt-commons/zlt-common-core/pom.xml b/zlt-commons/zlt-common-core/pom.xml index f8d91b5bc..208312ac0 100644 --- a/zlt-commons/zlt-common-core/pom.xml +++ b/zlt-commons/zlt-common-core/pom.xml @@ -14,13 +14,10 @@ com.baomidou mybatis-plus-extension - - org.springframework.social - spring-social-security - + org.springframework.security - spring-security-core + spring-security-web @@ -101,5 +98,9 @@ org.springframework.security spring-security-oauth2-jose + + org.springframework + spring-webmvc + \ No newline at end of file diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/annotation/LoginClient.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/annotation/LoginClient.java deleted file mode 100644 index d1fa6266f..000000000 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/annotation/LoginClient.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.central.common.annotation; - -import java.lang.annotation.*; - -/** - * 请求的方法参数上添加该注解,则注入当前登录账号的应用id - * 例:public void test(@LoginClient String clientId) //注入webApp - * - * @author zlt - * @date 2018/7/24 16:44 - */ -@Target(ElementType.PARAMETER) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface LoginClient { -} diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/annotation/LoginUser.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/annotation/LoginUser.java deleted file mode 100644 index c18332e96..000000000 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/annotation/LoginUser.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.central.common.annotation; - -import java.lang.annotation.*; - -/** - * 请求的方法参数SysUser上添加该注解,则注入当前登录人信息 - * 例1:public void test(@LoginUser SysUser user) //只有username 和 roles - * 例2:public void test(@LoginUser(isFull = true) SysUser user) //能获取SysUser对象的所有信息 - * - * @author zlt - * @date 2018/7/24 16:44 - */ -@Target(ElementType.PARAMETER) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface LoginUser { - /** - * 是否查询SysUser对象所有信息,true则通过rpc接口查询 - */ - boolean isFull() default false; -} diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/config/DefaultWebMvcConfig.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/config/DefaultWebMvcConfig.java deleted file mode 100644 index f851076cb..000000000 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/config/DefaultWebMvcConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.central.common.config; - -import com.central.common.feign.UserService; -import com.central.common.resolver.ClientArgumentResolver; -import com.central.common.resolver.TokenArgumentResolver; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -import java.util.List; - -/** - * 默认SpringMVC拦截器 - * - * @author zlt - * @date 2019/8/5 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -public class DefaultWebMvcConfig implements WebMvcConfigurer { - @Lazy - @Autowired - private UserService userService; - - /** - * Token参数解析 - * - * @param argumentResolvers 解析类 - */ - @Override - public void addArgumentResolvers(List argumentResolvers) { - //注入用户信息 - argumentResolvers.add(new TokenArgumentResolver(userService)); - //注入应用信息 - argumentResolvers.add(new ClientArgumentResolver()); - } -} diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java index e8e22c023..5c9a0f6ec 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java @@ -9,6 +9,8 @@ * Github: https://github.com/zlt2000 */ public interface SecurityConstants { + String PROJECT_LICENSE= "http://zlt2000.gitee.io/"; + /** * 用户信息分隔符 */ @@ -64,6 +66,8 @@ public interface SecurityConstants { */ String OAUTH_TOKEN_URL = "/oauth/token"; + String OAUTH_CHECK_TOKEN_URL = "/oauth/check_token"; + /** * 默认的处理验证码的url前缀 */ @@ -161,11 +165,11 @@ public interface SecurityConstants { /** * redis中应用对应的token集合的key */ - String REDIS_CLIENT_ID_TO_ACCESS = "client_id_to_access:"; + String REDIS_CLIENT_ID_TO_ACCESS = "client_id_to_access"; /** * redis中用户名对应的token集合的key */ - String REDIS_UNAME_TO_ACCESS = "uname_to_access:"; + String REDIS_UNAME_TO_ACCESS = "uname_to_access"; /** * rsa公钥 */ diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/UserService.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/UserService.java index c5d9b8971..fbef509d1 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/UserService.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/UserService.java @@ -2,7 +2,6 @@ import com.central.common.constant.ServiceNameConstants; import com.central.common.feign.fallback.UserServiceFallbackFactory; -import com.central.common.model.LoginAppUser; import com.central.common.model.SysRole; import com.central.common.model.SysUser; import org.springframework.cloud.openfeign.FeignClient; @@ -34,7 +33,7 @@ public interface UserService { * @return */ @GetMapping(value = "/users-anon/login", params = "username") - LoginAppUser findByUsername(@RequestParam("username") String username); + SysUser findByUsername(@RequestParam("username") String username); /** * 通过手机号查询用户、角色信息 @@ -42,7 +41,7 @@ public interface UserService { * @param mobile 手机号 */ @GetMapping(value = "/users-anon/mobile", params = "mobile") - LoginAppUser findByMobile(@RequestParam("mobile") String mobile); + SysUser findByMobile(@RequestParam("mobile") String mobile); /** * 根据OpenId查询用户信息 @@ -50,7 +49,7 @@ public interface UserService { * @param openId openId */ @GetMapping(value = "/users-anon/openId", params = "openId") - LoginAppUser findByOpenId(@RequestParam("openId") String openId); + SysUser findByOpenId(@RequestParam("openId") String openId); /** diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java index 4a249494f..eb83c6555 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/feign/fallback/UserServiceFallbackFactory.java @@ -1,7 +1,6 @@ package com.central.common.feign.fallback; import com.central.common.feign.UserService; -import com.central.common.model.LoginAppUser; import com.central.common.model.SysRole; import com.central.common.model.SysUser; import org.springframework.cloud.openfeign.FallbackFactory; @@ -28,21 +27,21 @@ public SysUser selectByUsername(String username) { } @Override - public LoginAppUser findByUsername(String username) { + public SysUser findByUsername(String username) { log.error("通过用户名查询用户异常:{}", username, throwable); - return new LoginAppUser(); + return new SysUser(); } @Override - public LoginAppUser findByMobile(String mobile) { + public SysUser findByMobile(String mobile) { log.error("通过手机号查询用户异常:{}", mobile, throwable); - return new LoginAppUser(); + return new SysUser(); } @Override - public LoginAppUser findByOpenId(String openId) { + public SysUser findByOpenId(String openId) { log.error("通过openId查询用户异常:{}", openId, throwable); - return new LoginAppUser(); + return new SysUser(); } /** diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/model/SysUser.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/model/SysUser.java index c7a67b5c0..bd90f82a8 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/model/SysUser.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/model/SysUser.java @@ -1,6 +1,7 @@ package com.central.common.model; import java.util.List; +import java.util.Set; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableLogic; @@ -39,4 +40,6 @@ public class SysUser extends SuperEntity { private String oldPassword; @TableField(exist = false) private String newPassword; + @TableField(exist = false) + private Set permissions; } diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/ClientArgumentResolver.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/ClientArgumentResolver.java deleted file mode 100644 index 63aa0adfe..000000000 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/ClientArgumentResolver.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.central.common.resolver; - -import cn.hutool.core.util.StrUtil; -import com.central.common.annotation.LoginClient; -import com.central.common.constant.SecurityConstants; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.MethodParameter; -import org.springframework.web.bind.support.WebDataBinderFactory; -import org.springframework.web.context.request.NativeWebRequest; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.method.support.ModelAndViewContainer; - -import jakarta.servlet.http.HttpServletRequest; - -/** - * head中的应用参数注入clientId中 - * - * @author zlt - * @date 2019/7/10 - */ -@Slf4j -public class ClientArgumentResolver implements HandlerMethodArgumentResolver { - /** - * 入参筛选 - * - * @param methodParameter 参数集合 - * @return 格式化后的参数 - */ - @Override - public boolean supportsParameter(MethodParameter methodParameter) { - return methodParameter.hasParameterAnnotation(LoginClient.class) && methodParameter.getParameterType().equals(String.class); - } - - /** - * @param methodParameter 入参集合 - * @param modelAndViewContainer model 和 view - * @param nativeWebRequest web相关 - * @param webDataBinderFactory 入参解析 - * @return 包装对象 - */ - @Override - public Object resolveArgument(MethodParameter methodParameter, - ModelAndViewContainer modelAndViewContainer, - NativeWebRequest nativeWebRequest, - WebDataBinderFactory webDataBinderFactory) { - HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class); - String clientId = request.getHeader(SecurityConstants.TENANT_HEADER); - if (StrUtil.isBlank(clientId)) { - log.warn("resolveArgument error clientId is empty"); - } - return clientId; - } -} diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/TokenArgumentResolver.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/TokenArgumentResolver.java deleted file mode 100644 index 566de8f83..000000000 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/resolver/TokenArgumentResolver.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.central.common.resolver; - -import com.central.common.annotation.LoginUser; -import com.central.common.constant.SecurityConstants; -import com.central.common.feign.UserService; -import com.central.common.model.SysUser; -import com.central.common.utils.LoginUserUtils; -import jakarta.servlet.http.HttpServletRequest; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.MethodParameter; -import org.springframework.web.bind.support.WebDataBinderFactory; -import org.springframework.web.context.request.NativeWebRequest; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.method.support.ModelAndViewContainer; - -/** - * Token转化SysUser - * - * @author zlt - * @date 2018/12/21 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Slf4j -public class TokenArgumentResolver implements HandlerMethodArgumentResolver { - private UserService userService; - - public TokenArgumentResolver(UserService userService) { - this.userService = userService; - } - - /** - * 入参筛选 - * - * @param methodParameter 参数集合 - * @return 格式化后的参数 - */ - @Override - public boolean supportsParameter(MethodParameter methodParameter) { - return methodParameter.hasParameterAnnotation(LoginUser.class) && methodParameter.getParameterType().equals(SysUser.class); - } - - /** - * @param methodParameter 入参集合 - * @param modelAndViewContainer model 和 view - * @param nativeWebRequest web相关 - * @param webDataBinderFactory 入参解析 - * @return 包装对象 - */ - @Override - public Object resolveArgument(MethodParameter methodParameter, - ModelAndViewContainer modelAndViewContainer, - NativeWebRequest nativeWebRequest, - WebDataBinderFactory webDataBinderFactory) { - LoginUser loginUser = methodParameter.getParameterAnnotation(LoginUser.class); - boolean isFull = loginUser.isFull(); - HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class); - //账号类型 - String accountType = request.getHeader(SecurityConstants.ACCOUNT_TYPE_HEADER); - - return LoginUserUtils.getCurrentUser(request, isFull); - } -} diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java index d8e91f06c..2f1c1d4fc 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java @@ -6,6 +6,8 @@ import com.central.common.context.LoginUserContextHolder; import com.central.common.feign.UserService; import com.central.common.model.LoginAppUser; +import com.central.common.model.SysRole; +import com.central.common.model.SysUser; import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; @@ -49,7 +51,10 @@ public static LoginAppUser getCurrentUser(HttpServletRequest request, boolean is if (StrUtil.isAllNotBlank(username, userId)) { if (isFull) { UserService userService = SpringUtil.getBean(UserService.class); - user = userService.findByUsername(username); + SysUser sysUser = userService.findByUsername(username); + if (sysUser != null) { + return getLoginAppUser(sysUser); + } } else { Collection authorities = new HashSet<>(); if (StrUtil.isNotBlank(roles)) { @@ -112,6 +117,20 @@ public static LoginAppUser setContext(Authentication authentication) { return user; } + public static LoginAppUser getLoginAppUser(SysUser sysUser) { + List sysRoles = sysUser.getRoles(); + Collection authorities = new HashSet<>(); + if (sysRoles != null) { + sysRoles.forEach(role -> authorities.add(new SimpleGrantedAuthority(role.getCode()))); + } + + return new LoginAppUser(sysUser.getId() + , sysUser.getUsername(), sysUser.getPassword() + , sysUser.getMobile(), sysUser.getPermissions() + , sysUser.getEnabled(), true, true, true + , authorities); + } + @SuppressWarnings("unchecked") public static LoginAppUser getLoginAppUser(Map userObj) { return new LoginAppUser( diff --git a/zlt-commons/zlt-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/zlt-commons/zlt-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 4b2316f26..1d4b07f46 100644 --- a/zlt-commons/zlt-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/zlt-commons/zlt-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,3 +1,2 @@ com.central.common.feign.fallback.UserServiceFallbackFactory -com.central.common.lock.LockAspect -com.central.common.utils.SpringUtil \ No newline at end of file +com.central.common.lock.LockAspect \ No newline at end of file diff --git a/zlt-demo/resources-server-demo/src/main/java/org/zlt/config/WebMvcConfig.java b/zlt-demo/resources-server-demo/src/main/java/org/zlt/config/WebMvcConfig.java deleted file mode 100644 index 6ba2a27b6..000000000 --- a/zlt-demo/resources-server-demo/src/main/java/org/zlt/config/WebMvcConfig.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.zlt.config; - -import com.central.common.config.DefaultWebMvcConfig; -import org.springframework.context.annotation.Configuration; - -/** - * web服务器配置 - * - * @author zlt - * @version 1.0 - * @date 2022/6/25 - *

- * Blog: http://zlt2000.gitee.io - * Github: https://github.com/zlt2000 - */ -@Configuration -public class WebMvcConfig extends DefaultWebMvcConfig { -} diff --git a/zlt-demo/resources-server-demo/src/main/java/org/zlt/controller/TestController.java b/zlt-demo/resources-server-demo/src/main/java/org/zlt/controller/TestController.java index 9654e14fa..4b936898a 100644 --- a/zlt-demo/resources-server-demo/src/main/java/org/zlt/controller/TestController.java +++ b/zlt-demo/resources-server-demo/src/main/java/org/zlt/controller/TestController.java @@ -1,8 +1,7 @@ package org.zlt.controller; -import com.central.common.annotation.LoginUser; import com.central.common.context.LoginUserContextHolder; -import com.central.common.model.SysUser; +import com.central.common.utils.LoginUserUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -18,18 +17,18 @@ @RestController public class TestController { /** - * 通过 @LoginUser 获取当前登录人 + * 通过 LoginUserUtils 获取当前登录人 */ @GetMapping("/test/auth") - public String auth(@LoginUser SysUser user) { - return "auth:" + user.getUsername(); + public String auth() { + return "auth:" + LoginUserUtils.getCurrentUser(false).getUsername(); } /** * 通过 LoginUserContextHolder 获取当前登录人 */ @GetMapping("/test/auth2") - public String auth() { + public String auth2() { return "auth2:" + LoginUserContextHolder.getUser().getUsername(); } diff --git a/zlt-gateway/sc-gateway/src/main/resources/application.yml b/zlt-gateway/sc-gateway/src/main/resources/application.yml index c5f14ed86..f4817fcc3 100644 --- a/zlt-gateway/sc-gateway/src/main/resources/application.yml +++ b/zlt-gateway/sc-gateway/src/main/resources/application.yml @@ -97,10 +97,6 @@ knife4j: context-path: /api-file zlt: - oauth2: - token: - store: - type: redis security: ignore: # 忽略认证的地址 @@ -111,7 +107,7 @@ zlt: /api-uaa/images/**, /api-uaa/js/**, /login.html, - /user/login, + /user/login, /oauth/authorize, /api-uaa/tokens/key auth: urlPermission: diff --git a/zlt-uaa/pom.xml b/zlt-uaa/pom.xml index 53d17a81f..fbd9c5e9c 100644 --- a/zlt-uaa/pom.xml +++ b/zlt-uaa/pom.xml @@ -50,14 +50,6 @@ com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery - - org.springframework.boot - spring-boot-starter-oauth2-authorization-server - - - org.springframework.social - spring-social-security - org.springframework.boot spring-boot-starter-web @@ -71,11 +63,6 @@ org.springframework.boot spring-boot-starter-actuator - - org.springframework.session - spring-session-data-redis - - mysql mysql-connector-java diff --git a/zlt-uaa/src/main/java/com/central/UaaServerApp.java b/zlt-uaa/src/main/java/com/central/UaaServerApp.java index a52b34e4b..04738baff 100644 --- a/zlt-uaa/src/main/java/com/central/UaaServerApp.java +++ b/zlt-uaa/src/main/java/com/central/UaaServerApp.java @@ -14,7 +14,6 @@ @MapperScan(basePackages = "com.central.oauth.mapper") @EnableFeignInterceptor @EnableDiscoveryClient -//@EnableRedisHttpSession @SpringBootApplication public class UaaServerApp { public static void main(String[] args) { diff --git a/zlt-uaa/src/main/java/com/central/oauth/component/CustomAccessTokenResponseHttpMessageConverter.java b/zlt-uaa/src/main/java/com/central/oauth/component/CustomAccessTokenResponseHttpMessageConverter.java new file mode 100644 index 000000000..8fe29bce4 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/component/CustomAccessTokenResponseHttpMessageConverter.java @@ -0,0 +1,48 @@ +package com.central.oauth.component; + +import com.central.common.model.Result; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.MediaType; +import org.springframework.http.converter.GenericHttpMessageConverter; +import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.security.oauth2.core.endpoint.DefaultOAuth2AccessTokenResponseMapConverter; +import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; +import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; + +import java.util.Map; + +/** + * @author zlt + * @version 1.0 + * @date 2023/12/6 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class CustomAccessTokenResponseHttpMessageConverter extends OAuth2AccessTokenResponseHttpMessageConverter { + private Converter> accessTokenResponseParametersConverter = new DefaultOAuth2AccessTokenResponseMapConverter(); + private static final ParameterizedTypeReference>> STRING_OBJECT_MAP = new ParameterizedTypeReference<>() {}; + + private final ObjectMapper objectMapper; + public CustomAccessTokenResponseHttpMessageConverter(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + @Override + protected void writeInternal(OAuth2AccessTokenResponse tokenResponse, HttpOutputMessage outputMessage) + throws HttpMessageNotWritableException { + try { + Map tokenResponseParameters = this.accessTokenResponseParametersConverter.convert(tokenResponse); + GenericHttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter(objectMapper); + jsonMessageConverter.write(Result.succeed(tokenResponseParameters), STRING_OBJECT_MAP.getType(), MediaType.APPLICATION_JSON, outputMessage); + } + catch (Exception ex) { + throw new HttpMessageNotWritableException( + "An error occurred writing the OAuth 2.0 Access Token Response: " + ex.getMessage(), ex); + } + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/component/CustomeOAuth2TokenCustomizer.java b/zlt-uaa/src/main/java/com/central/oauth/component/CustomeOAuth2TokenCustomizer.java new file mode 100644 index 000000000..7b5b29b76 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/component/CustomeOAuth2TokenCustomizer.java @@ -0,0 +1,35 @@ +package com.central.oauth.component; + +import com.central.common.constant.SecurityConstants; +import com.central.common.model.LoginAppUser; +import com.central.oauth2.common.token.BaseAuthenticationToken; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsSet; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer; + +/** + * token 输出增强 + * + * @author: zlt + * @date: 2023/12/2 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class CustomeOAuth2TokenCustomizer implements OAuth2TokenCustomizer { + @Override + public void customize(OAuth2TokenClaimsContext context) { + OAuth2TokenClaimsSet.Builder claims = context.getClaims(); + AbstractAuthenticationToken authenticationToken = context.getAuthorizationGrant(); + + if (authenticationToken instanceof BaseAuthenticationToken baseAuthenticationToken) { + LoginAppUser user = (LoginAppUser) context.getPrincipal().getPrincipal(); + claims.claim(SecurityConstants.DETAILS_USER_ID, user.getId()); + claims.claim(SecurityConstants.USERNAME, user.getUsername()); + + String account_type = (String)baseAuthenticationToken.getAdditionalParameters().get(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME); + claims.claim(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME, account_type); + } + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/component/LoginProcessSetTenantFilter.java b/zlt-uaa/src/main/java/com/central/oauth/component/LoginProcessSetTenantFilter.java new file mode 100644 index 000000000..356bed486 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/component/LoginProcessSetTenantFilter.java @@ -0,0 +1,66 @@ +package com.central.oauth.component; + +import cn.hutool.core.util.ArrayUtil; +import com.central.common.constant.SecurityConstants; +import com.central.common.context.TenantContextHolder; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpMethod; +import org.springframework.security.web.savedrequest.DefaultSavedRequest; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatcher; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; + +/** + * 设置租户id过滤器 + * + * @author zlt + * @date 2020/3/29 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class LoginProcessSetTenantFilter extends OncePerRequestFilter { + private static final String SAVED_REQUEST = "SPRING_SECURITY_SAVED_REQUEST"; + + private RequestMatcher requiresAuthenticationRequestMatcher; + public LoginProcessSetTenantFilter() { + requiresAuthenticationRequestMatcher = new AntPathRequestMatcher(SecurityConstants.OAUTH_LOGIN_PRO_URL, HttpMethod.POST.name()); + } + + /** + * 返回true代表不执行过滤器,false代表执行 + */ + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + if (requiresAuthentication(request)) { + return false; + } + return true; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { + try { + DefaultSavedRequest savedRequest = (DefaultSavedRequest)request.getSession().getAttribute(SAVED_REQUEST); + if (savedRequest != null) { + String[] clientIds = savedRequest.getParameterValues("client_id"); + if (ArrayUtil.isNotEmpty(clientIds)) { + //保存租户id + TenantContextHolder.setTenant(clientIds[0]); + } + } + chain.doFilter(request, response); + } finally { + TenantContextHolder.clear(); + } + } + + private boolean requiresAuthentication(HttpServletRequest request) { + return requiresAuthenticationRequestMatcher.matches(request); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java new file mode 100644 index 000000000..51c98439c --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java @@ -0,0 +1,151 @@ +package com.central.oauth.config; + +import com.central.common.config.DefaultPasswordConfig; +import com.central.oauth.component.LoginProcessSetTenantFilter; +import com.central.oauth.service.IValidateCodeService; +import com.central.oauth.service.impl.RedisSecurityContextRepository; +import com.central.oauth.service.impl.RegisteredClientService; +import com.central.oauth.service.impl.UserDetailServiceFactory; +import com.central.oauth.support.mobile.MobileAuthenticationConverter; +import com.central.oauth.support.mobile.MobileAuthenticationProvider; +import com.central.oauth.support.openid.OpenIdAuthenticationConverter; +import com.central.oauth.support.openid.OpenIdAuthenticationProvider; +import com.central.oauth.support.password.PasswordAuthenticationConverter; +import com.central.oauth.support.password.PasswordAuthenticationProvider; +import com.central.oauth.support.passwordCode.PasswordCodeAuthenticationConverter; +import com.central.oauth.support.passwordCode.PasswordCodeAuthenticationProvider; +import com.central.oauth2.common.component.CustomAuthorizationServiceIntrospector; +import com.central.oauth2.common.component.CustomBearerTokenResolver; +import com.central.oauth2.common.config.BaseSecurityConfig; +import com.central.oauth2.common.enums.TokenType; +import com.central.oauth2.common.properties.SecurityProperties; +import com.central.oauth2.common.util.OAuth2ConfigurerUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.core.OAuth2Token; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator; +import org.springframework.security.oauth2.server.authorization.web.authentication.DelegatingAuthenticationConverter; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.authentication.AuthenticationConverter; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; + +import java.util.Arrays; + +/** + * @author: zlt + * @date: 2023/11/16 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Configuration +@RequiredArgsConstructor +@EnableWebSecurity +@Import({BaseSecurityConfig.class, DefaultPasswordConfig.class}) +public class AuthorizationServerConfig { + private final UserDetailServiceFactory userDetailsServiceFactory; + private final PasswordEncoder passwordEncoder; + private final AuthenticationFailureHandler authenticationFailureHandler; + private final CustomBearerTokenResolver customBearerTokenResolver; + private final AuthenticationEntryPoint authenticationEntryPoint; + private final LogoutHandler logoutHandler; + private final LogoutSuccessHandler logoutSuccessHandler; + private final AccessDeniedHandler oAuth2AccessDeniedHandler; + private final SecurityProperties securityProperties; + private final IValidateCodeService validateCodeService; + private final RegisteredClientService registeredClientService; + private final RedisSecurityContextRepository securityContextRepository; + private final AuthenticationSuccessHandler authenticationSuccessHandler; + + /** + * spring security 默认的安全策略 + */ + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { + http.authorizeHttpRequests(authorizeRequests -> { + // 授权服务器关闭basic认证 + authorizeRequests + .requestMatchers(securityProperties.getIgnore().getUrls()).permitAll() + .anyRequest().authenticated(); + }); + // 登录登出配置 + http.apply(new FormIdentityLoginConfigurer(logoutSuccessHandler, logoutHandler)); + + // 登录的认证信息储存策略(redis) + http.securityContext(context -> context.securityContextRepository(securityContextRepository)); + + // 授权配置 + OAuth2AuthorizationService authorizationService = OAuth2ConfigurerUtils.getAuthorizationService(http); + OAuth2TokenGenerator tokenGenerator = OAuth2ConfigurerUtils.getTokenGenerator(http); + + OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer(); + http.apply(authorizationServerConfigurer.tokenEndpoint((tokenEndpoint) -> tokenEndpoint + // 注入自定义的授权认证Converter + .accessTokenRequestConverter(accessTokenRequestConverter()) + // 登录失败处理器 + .errorResponseHandler(authenticationFailureHandler) + // 登录成功处理器 + .accessTokenResponseHandler(authenticationSuccessHandler) + // 自定义授权类型 + .authenticationProvider(new PasswordAuthenticationProvider(authorizationService, tokenGenerator, userDetailsServiceFactory, passwordEncoder)) + .authenticationProvider(new PasswordCodeAuthenticationProvider(authorizationService, tokenGenerator, userDetailsServiceFactory, passwordEncoder, validateCodeService)) + .authenticationProvider(new OpenIdAuthenticationProvider(authorizationService, tokenGenerator, userDetailsServiceFactory)) + .authenticationProvider(new MobileAuthenticationProvider(authorizationService, tokenGenerator, userDetailsServiceFactory, passwordEncoder)) + ) + // 开启OpenID Connect 1.0协议相关端点 + .oidc(Customizer.withDefaults()) + ) + // 应用鉴权 + .clientAuthentication(clientConfig -> clientConfig.errorResponseHandler(authenticationFailureHandler)); + // 指定授权服务 + http.apply(authorizationServerConfigurer + .authorizationService(authorizationService) + .authorizationEndpoint(endpoint -> endpoint + .errorResponseHandler(authenticationFailureHandler) + )); + + // 资源服务配置 + http.oauth2ResourceServer(oauth2 -> { + oauth2.authenticationEntryPoint(authenticationEntryPoint) + .bearerTokenResolver(customBearerTokenResolver) + .accessDeniedHandler(oAuth2AccessDeniedHandler); + if (TokenType.JWT.getName().equals(securityProperties.getResourceServer().getTokenType())) { + oauth2.jwt(Customizer.withDefaults()); + } else { + oauth2.opaqueToken(token -> token.introspector(new CustomAuthorizationServiceIntrospector(authorizationService))); + } + }); + + http.addFilterBefore(new LoginProcessSetTenantFilter(), UsernamePasswordAuthenticationFilter.class); + + // 缓存应用 + registeredClientService.loadAllClientToCache(); + + return http.build(); + } + + private AuthenticationConverter accessTokenRequestConverter() { + return new DelegatingAuthenticationConverter(Arrays.asList( + new PasswordAuthenticationConverter(), + new PasswordCodeAuthenticationConverter(), + new OpenIdAuthenticationConverter(), + new MobileAuthenticationConverter())); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/FormIdentityLoginConfigurer.java b/zlt-uaa/src/main/java/com/central/oauth/config/FormIdentityLoginConfigurer.java new file mode 100644 index 000000000..54d59be26 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/config/FormIdentityLoginConfigurer.java @@ -0,0 +1,45 @@ +package com.central.oauth.config; + +import com.central.common.constant.SecurityConstants; +import lombok.RequiredArgsConstructor; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; + +/** + * @author: zlt + * @date: 2023/11/23 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@RequiredArgsConstructor +public class FormIdentityLoginConfigurer extends AbstractHttpConfigurer { + private final LogoutSuccessHandler logoutSuccessHandler; + private final LogoutHandler logoutHandler; + + @Override + public void init(HttpSecurity http) throws Exception { + http.formLogin(formLogin -> formLogin + .loginPage(SecurityConstants.LOGIN_PAGE) + .loginProcessingUrl(SecurityConstants.OAUTH_LOGIN_PRO_URL) + .successHandler(new SavedRequestAwareAuthenticationSuccessHandler())) + .logout(logout -> logout + .logoutUrl(SecurityConstants.LOGOUT_URL) + .logoutSuccessHandler(logoutSuccessHandler) + .addLogoutHandler(logoutHandler) + .deleteCookies("JSESSIONID") + .clearAuthentication(true) + .invalidateHttpSession(true)) + .headers(header -> header + // 避免iframe同源无法登录许iframe + .frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)) + .csrf(AbstractHttpConfigurer::disable) + .sessionManagement(session -> session + .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/RedisListenerConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/RedisListenerConfig.java deleted file mode 100644 index 9daa34aa1..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/config/RedisListenerConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.central.oauth.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.listener.RedisMessageListenerContainer; -/** - * - * redis过期key监听器配置类 - * @author zlt - * - */ -@Configuration -public class RedisListenerConfig { - @Bean - @Primary - public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory factory) { - RedisMessageListenerContainer container = new RedisMessageListenerContainer(); - container.setConnectionFactory(factory); - return container; - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java new file mode 100644 index 000000000..e52671f76 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java @@ -0,0 +1,144 @@ +package com.central.oauth.config; + +import cn.hutool.core.util.StrUtil; +import com.central.common.constant.SecurityConstants; +import com.central.common.utils.ResponseUtil; +import com.central.oauth.component.CustomAccessTokenResponseHttpMessageConverter; +import com.central.oauth.component.CustomeOAuth2TokenCustomizer; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.catalina.util.StandardSessionIdGenerator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.server.ServletServerHttpResponse; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2RefreshToken; +import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; +import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames; +import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames; +import org.springframework.security.oauth2.jwt.JwtClaimsSet; +import org.springframework.security.oauth2.jwt.JwtEncoder; +import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; +import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken; +import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings; +import org.springframework.security.oauth2.server.authorization.token.*; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.util.CollectionUtils; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.Map; + +/** + * 服务安全相关配置 + * + * @author: zlt + * @date: 2023/11/9 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Configuration +public class SecurityConfig { + /** + * token内容增强 + */ + @Bean + public OAuth2TokenCustomizer jwtTokenCustomizer(){ + return context -> { + JwtClaimsSet.Builder claims = context.getClaims(); + claims.claim(SecurityConstants.LICENSE_NAME, SecurityConstants.PROJECT_LICENSE); + // 客户端模式不返回具体用户信息 + if (AuthorizationGrantType.CLIENT_CREDENTIALS.equals(context.getAuthorizationGrantType().getValue())) { + return; + } + if (context.getTokenType().equals(OAuth2TokenType.ACCESS_TOKEN)) { + claims.claim(SecurityConstants.DETAILS_USER, context.getPrincipal().getPrincipal()); + } else if (context.getTokenType().getValue().equals(OidcParameterNames.ID_TOKEN)) { + claims.claim(IdTokenClaimNames.AUTH_TIME, Date.from(Instant.now())); + StandardSessionIdGenerator standardSessionIdGenerator = new StandardSessionIdGenerator(); + claims.claim("sid", standardSessionIdGenerator.generateSessionId()); + } + }; + } + + /** + * 令牌生成规则实现 + */ + @Bean + public OAuth2TokenGenerator oAuth2TokenGenerator(JwtEncoder jwtEncoder, OAuth2TokenCustomizer jwtTokenCustomizer) { + JwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder); + jwtGenerator.setJwtCustomizer(jwtTokenCustomizer); + + OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator(); + accessTokenGenerator.setAccessTokenCustomizer(new CustomeOAuth2TokenCustomizer()); + + return new DelegatingOAuth2TokenGenerator( + jwtGenerator, + accessTokenGenerator, + new OAuth2RefreshTokenGenerator() + ); + } + + /** + * 授权服务信息配置 + */ + @Bean + public AuthorizationServerSettings authorizationServerSettings() { + return AuthorizationServerSettings.builder() + .issuer(SecurityConstants.PROJECT_LICENSE) + .authorizationEndpoint(SecurityConstants.AUTH_CODE_URL) + .tokenEndpoint(SecurityConstants.OAUTH_TOKEN_URL) + .tokenIntrospectionEndpoint(SecurityConstants.OAUTH_CHECK_TOKEN_URL) + .build(); + } + + /** + * 授权错误处理 + */ + @Bean + public AuthenticationFailureHandler authenticationFailureHandler(ObjectMapper objectMapper) { + return (request, response, authException) -> { + String msg = null; + if (StrUtil.isNotEmpty(authException.getMessage())) { + msg = authException.getMessage(); + } else if (authException instanceof OAuth2AuthenticationException exception) { + msg = exception.getError().getErrorCode(); + } + ResponseUtil.responseFailed(objectMapper, response, msg); + }; + } + + @Bean + public AuthenticationSuccessHandler authenticationSuccessHandler(ObjectMapper objectMapper) { + return (request, response, authentication) -> { + OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = + (OAuth2AccessTokenAuthenticationToken) authentication; + + OAuth2AccessToken accessToken = accessTokenAuthentication.getAccessToken(); + OAuth2RefreshToken refreshToken = accessTokenAuthentication.getRefreshToken(); + Map additionalParameters = accessTokenAuthentication.getAdditionalParameters(); + + OAuth2AccessTokenResponse.Builder builder = + OAuth2AccessTokenResponse.withToken(accessToken.getTokenValue()) + .tokenType(accessToken.getTokenType()) + .scopes(accessToken.getScopes()); + if (accessToken.getIssuedAt() != null && accessToken.getExpiresAt() != null) { + builder.expiresIn(ChronoUnit.SECONDS.between(accessToken.getIssuedAt(), accessToken.getExpiresAt())); + } + if (refreshToken != null) { + builder.refreshToken(refreshToken.getTokenValue()); + } + if (!CollectionUtils.isEmpty(additionalParameters)) { + builder.additionalParameters(additionalParameters); + } + OAuth2AccessTokenResponse accessTokenResponse = builder.build(); + ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response); + CustomAccessTokenResponseHttpMessageConverter converter = new CustomAccessTokenResponseHttpMessageConverter(objectMapper); + converter.write(accessTokenResponse, null, httpResponse); + }; + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/WebMvcConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/WebMvcConfig.java deleted file mode 100644 index fd4b21a07..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/config/WebMvcConfig.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.central.oauth.config; - -/*import com.central.common.config.DefaultWebMvcConfig; -import org.springframework.context.annotation.Configuration;*/ - -/** - * @author zlt - * @date 2019/8/5 - */ -/* -@Configuration -public class WebMvcConfig extends DefaultWebMvcConfig { -} -*/ diff --git a/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java b/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java index 44efb4141..940556051 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java +++ b/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java @@ -2,13 +2,13 @@ import com.central.common.model.PageResult; import com.central.common.model.Result; -import com.central.oauth.dto.ClientDto; import com.central.oauth.model.Client; -import com.central.oauth.service.IClientService; +import com.central.oauth.service.impl.RegisteredClientService; +import com.central.oauth2.common.pojo.ClientDto; import com.google.common.collect.Maps; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -25,26 +25,26 @@ @Tag(name = "应用") @RestController @RequestMapping("/clients") +@RequiredArgsConstructor public class ClientController { - @Autowired - private IClientService clientService; + private final RegisteredClientService clientService; @GetMapping("/list") @Operation(summary = "应用列表") - public PageResult list(@RequestParam Map params) { + public PageResult list(@RequestParam Map params) { return clientService.listClient(params, true); } @GetMapping("/{id}") @Operation(summary = "根据id获取应用") - public Client get(@PathVariable Long id) { + public ClientDto get(@PathVariable Long id) { return clientService.getById(id); } @GetMapping("/all") @Operation(summary = "所有应用") - public Result> allClient() { - PageResult page = clientService.listClient(Maps.newHashMap(), false); + public Result> allClient() { + PageResult page = clientService.listClient(Maps.newHashMap(), false); return Result.succeed(page.getData()); } @@ -56,7 +56,8 @@ public void delete(@PathVariable Long id) { @PostMapping("/saveOrUpdate") @Operation(summary = "保存或者修改应用") - public Result saveOrUpdate(@RequestBody ClientDto clientDto) throws Exception { - return clientService.saveClient(clientDto); + public Result saveOrUpdate(@RequestBody Client client) throws Exception { + clientService.saveClient(client); + return Result.succeed("操作成功"); } } diff --git a/zlt-uaa/src/main/java/com/central/oauth/controller/TokensController.java b/zlt-uaa/src/main/java/com/central/oauth/controller/TokensController.java new file mode 100644 index 000000000..97aad393c --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/controller/TokensController.java @@ -0,0 +1,35 @@ +package com.central.oauth.controller; + +import com.central.common.model.PageResult; +import com.central.oauth.model.TokenVo; +import com.central.oauth.service.ITokensService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Map; + +/** + * token管理接口 + * + * @author zlt + */ +@Tag(name = "Token管理") +@Slf4j +@RestController +@RequestMapping("/tokens") +public class TokensController { + @Resource + private ITokensService tokensService; + + @GetMapping("") + @Operation(summary = "token列表") + public PageResult list(@RequestParam Map params, String tenantId) { + return tokensService.listTokens(params, tenantId); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/dto/ClientDto.java b/zlt-uaa/src/main/java/com/central/oauth/dto/ClientDto.java deleted file mode 100644 index 2b00c02ab..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/dto/ClientDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.central.oauth.dto; - -import com.central.oauth.model.Client; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; -import java.util.Set; - -@Setter -@Getter -public class ClientDto extends Client { - private static final long serialVersionUID = 1475637288060027265L; - - private List permissionIds; - - private Set serviceIds; -} diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/exception/CustomOAuth2AuthenticationException.java b/zlt-uaa/src/main/java/com/central/oauth/exception/CustomOAuth2AuthenticationException.java similarity index 91% rename from zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/exception/CustomOAuth2AuthenticationException.java rename to zlt-uaa/src/main/java/com/central/oauth/exception/CustomOAuth2AuthenticationException.java index 585ecc539..ee8d50970 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/exception/CustomOAuth2AuthenticationException.java +++ b/zlt-uaa/src/main/java/com/central/oauth/exception/CustomOAuth2AuthenticationException.java @@ -1,4 +1,4 @@ -package com.central.oauth2.common.exception; +package com.central.oauth.exception; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; diff --git a/zlt-uaa/src/main/java/com/central/oauth/exception/ValidateCodeException.java b/zlt-uaa/src/main/java/com/central/oauth/exception/ValidateCodeException.java deleted file mode 100644 index 3123b04cd..000000000 --- a/zlt-uaa/src/main/java/com/central/oauth/exception/ValidateCodeException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.central.oauth.exception; - -import org.springframework.security.core.AuthenticationException; - -/** - * 验证码异常 - * @author zlt - */ -public class ValidateCodeException extends AuthenticationException { - private static final long serialVersionUID = -7285211528095468156L; - - public ValidateCodeException(String msg) { - super(msg); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutHandler.java b/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutHandler.java new file mode 100644 index 000000000..c26f2928a --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutHandler.java @@ -0,0 +1,50 @@ +package com.central.oauth.handler; + +import cn.hutool.core.util.StrUtil; +import com.central.oauth.utils.UsernameHolder; +import com.central.oauth2.common.properties.SecurityProperties; +import com.central.oauth2.common.util.AuthUtils; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; +import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +/** + * @author zlt + * @date 2018/10/17 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Slf4j +@RequiredArgsConstructor +@Component +public class OauthLogoutHandler implements LogoutHandler { + private final OAuth2AuthorizationService oAuth2AuthorizationService; + private final SecurityProperties securityProperties; + @Override + public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { + Assert.notNull(oAuth2AuthorizationService, "oAuth2AuthorizationService must be set"); + String token = request.getParameter("token"); + if (StrUtil.isEmpty(token)) { + token = AuthUtils.extractToken(request); + } + if(StrUtil.isNotEmpty(token)){ + OAuth2Authorization existingAccessToken = oAuth2AuthorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); + if (existingAccessToken != null) { + if (securityProperties.getAuth().getUnifiedLogout()) { + UsernameHolder.setContext(existingAccessToken.getPrincipalName()); + } + oAuth2AuthorizationService.remove(existingAccessToken); + log.info("remove existingAccessToken!", existingAccessToken.getAccessToken().getToken().getTokenType()); + } + } + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutSuccessHandler.java b/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutSuccessHandler.java new file mode 100644 index 000000000..d2d7d17c3 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/handler/OauthLogoutSuccessHandler.java @@ -0,0 +1,51 @@ +package com.central.oauth.handler; + +import cn.hutool.core.util.StrUtil; +import com.central.common.utils.ResponseUtil; +import com.central.oauth.service.impl.UnifiedLogoutService; +import com.central.oauth2.common.properties.SecurityProperties; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.RedirectStrategy; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +/** + * @author zlt + * @date 2020/3/10 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Slf4j +@RequiredArgsConstructor +@Component +public class OauthLogoutSuccessHandler implements LogoutSuccessHandler { + private static final String REDIRECT_URL = "redirect_url"; + private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + private final UnifiedLogoutService unifiedLogoutService; + private final SecurityProperties securityProperties; + private final ObjectMapper objectMapper; + + @Override + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { + if (securityProperties.getAuth().getUnifiedLogout()) { + unifiedLogoutService.allLogout(); + } + + String redirectUri = request.getParameter(REDIRECT_URL); + if (StrUtil.isNotEmpty(redirectUri)) { + //重定向指定的地址 + redirectStrategy.sendRedirect(request, response, redirectUri); + } else { + ResponseUtil.responseWriter(objectMapper, response, "登出成功", 0); + } + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/model/Client.java b/zlt-uaa/src/main/java/com/central/oauth/model/Client.java index a8915966b..7fa296e31 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/model/Client.java +++ b/zlt-uaa/src/main/java/com/central/oauth/model/Client.java @@ -33,14 +33,9 @@ public class Client extends SuperEntity { private String additionalInformation = "{}"; private String autoapprove = "true"; /** - * 是否支持id_token + * token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt)) */ - private Boolean supportIdToken = true; - /** - * id_token有效时间(s) - */ - @TableField(value = "id_token_validity") - private Integer idTokenValiditySeconds = 60; + private String tokenFormat = "reference"; private Long creatorId; } diff --git a/zlt-uaa/src/main/java/com/central/oauth/model/SupplierDeferredSecurityContext.java b/zlt-uaa/src/main/java/com/central/oauth/model/SupplierDeferredSecurityContext.java new file mode 100644 index 000000000..b2d557d4b --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/model/SupplierDeferredSecurityContext.java @@ -0,0 +1,54 @@ +package com.central.oauth.model; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.core.log.LogMessage; +import org.springframework.security.core.context.DeferredSecurityContext; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolderStrategy; + +import java.util.function.Supplier; + +/** + * @author: zlt + * @date: 2023/12/06 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public final class SupplierDeferredSecurityContext implements DeferredSecurityContext { + private static final Log logger = LogFactory.getLog(SupplierDeferredSecurityContext.class); + private final Supplier supplier; + private final SecurityContextHolderStrategy strategy; + private SecurityContext securityContext; + private boolean missingContext; + public SupplierDeferredSecurityContext(Supplier supplier, SecurityContextHolderStrategy strategy) { + this.supplier = supplier; + this.strategy = strategy; + } + @Override + public SecurityContext get() { + init(); + return this.securityContext; + } + @Override + public boolean isGenerated() { + init(); + return this.missingContext; + } + private void init() { + if (this.securityContext != null) { + return; + } + + this.securityContext = this.supplier.get(); + this.missingContext = (this.securityContext == null); + if (this.missingContext) { + this.securityContext = this.strategy.createEmptyContext(); + if (logger.isTraceEnabled()) { + logger.trace(LogMessage.format("Created %s", this.securityContext)); + } + } + } + +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java b/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java index c9afe37e0..306f2c5ad 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java @@ -1,7 +1,6 @@ package com.central.oauth.service; import com.central.common.model.PageResult; -import com.central.common.model.Result; import com.central.common.service.ISuperService; import com.central.oauth.model.Client; @@ -14,7 +13,7 @@ * Github: https://github.com/zlt2000 */ public interface IClientService extends ISuperService { - Result saveClient(Client clientDto) throws Exception; + void saveClient(Client clientDto) throws Exception; /** * 查询应用列表 @@ -26,6 +25,4 @@ public interface IClientService extends ISuperService { void delClient(long id); Client loadClientByClientId(String clientId); - - void loadAllClientToCache(); } diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java index 7a7fa3e72..aaf43e818 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java @@ -3,11 +3,9 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.central.common.constant.SecurityConstants; import com.central.common.context.LoginUserContextHolder; import com.central.common.lock.DistributedLock; import com.central.common.model.PageResult; -import com.central.common.model.Result; import com.central.common.service.impl.SuperServiceImpl; import com.central.oauth.mapper.ClientMapper; import com.central.oauth.model.Client; @@ -15,9 +13,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.MapUtils; -import org.redisson.api.RBucket; -import org.redisson.api.RedissonClient; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @@ -36,14 +31,12 @@ public class ClientServiceImpl extends SuperServiceImpl implements IClientService { private final static String LOCK_KEY_CLIENTID = "clientId:"; - private final RedissonClient redisson; - private final PasswordEncoder passwordEncoder; private final DistributedLock lock; @Override - public Result saveClient(Client client) throws Exception { + public void saveClient(Client client) throws Exception { client.setClientSecret(passwordEncoder.encode(client.getClientSecretStr())); String clientId = client.getClientId(); if (client.getId() == null) { @@ -53,10 +46,6 @@ public Result saveClient(Client client) throws Exception { , LOCK_KEY_CLIENTID+clientId , new QueryWrapper().eq("client_id", clientId) , clientId + "已存在"); - - redisson.getBucket(clientRedisKey(clientId)).set(client); - - return Result.succeed("操作成功"); } @Override @@ -74,32 +63,13 @@ public PageResult listClient(Map params, boolean isPage) @Override public void delClient(long id) { - String clientId = baseMapper.selectById(id).getClientId(); baseMapper.deleteById(id); - redisson.getBucket(clientRedisKey(clientId)).delete(); } @Override public Client loadClientByClientId(String clientId) { - RBucket clientBucket = redisson.getBucket(clientRedisKey(clientId)); - Client client = clientBucket.get(); - if (client != null) { - return client; - } QueryWrapper wrapper = Wrappers.query(); wrapper.eq("client_id", clientId); - client = this.getOne(wrapper); - clientBucket.set(client); - return client; - } - - @Override - public void loadAllClientToCache() { - List clientList = this.list(); - clientList.forEach(c -> redisson.getBucket(clientRedisKey(c.getClientId())).set(c)); - } - - private String clientRedisKey(String clientId) { - return SecurityConstants.CACHE_CLIENT_KEY + ":" + clientId; + return this.getOne(wrapper); } } diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/CustomRegisteredClientRepository.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/CustomRegisteredClientRepository.java new file mode 100644 index 000000000..8fe79fe77 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/CustomRegisteredClientRepository.java @@ -0,0 +1,90 @@ +package com.central.oauth.service.impl; + +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.StrUtil; +import com.central.oauth2.common.pojo.ClientDto; +import lombok.RequiredArgsConstructor; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; +import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; +import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository; +import org.springframework.security.oauth2.server.authorization.settings.ClientSettings; +import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat; +import org.springframework.security.oauth2.server.authorization.settings.TokenSettings; +import org.springframework.stereotype.Component; + +import java.time.Duration; + +/** + * @author: zlt + * @date: 2023/08/04 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@RequiredArgsConstructor +@Component +public class CustomRegisteredClientRepository implements RegisteredClientRepository { + private final RegisteredClientService clientService; + @Override + public void save(RegisteredClient registeredClient) { + + } + + @Override + public RegisteredClient findById(String id) { + return this.findByClientId(id); + } + + @Override + public RegisteredClient findByClientId(String clientId) { + ClientDto clientObj = clientService.loadClientByClientId(clientId); + if (clientObj == null) { + return null; + } + RegisteredClient.Builder builder = RegisteredClient.withId(clientObj.getClientId()) + .clientId(clientObj.getClientId()) + .clientSecret(clientObj.getClientSecret()) + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC); + + if (StrUtil.isNotBlank(clientObj.getAuthorizedGrantTypes())) { + for (String authorizedGrantType : clientObj.getAuthorizedGrantTypes().split(StrUtil.COMMA)) { + builder.authorizationGrantType(new AuthorizationGrantType(authorizedGrantType)); + } + } + + if (StrUtil.isNotBlank(clientObj.getWebServerRedirectUri())) { + for (String redirectUri : clientObj.getWebServerRedirectUri().split(StrUtil.COMMA)) { + builder.redirectUri(redirectUri); + } + } + + if (StrUtil.isNotBlank(clientObj.getScope())) { + for (String scope : clientObj.getScope().split(StrUtil.COMMA)) { + builder.scope(scope); + } + } + + OAuth2TokenFormat tokenFormat; + if (OAuth2TokenFormat.SELF_CONTAINED.getValue().equals(clientObj.getTokenFormat())) { + tokenFormat = OAuth2TokenFormat.SELF_CONTAINED; + } else { + tokenFormat = OAuth2TokenFormat.REFERENCE; + } + + return builder + .tokenSettings( + TokenSettings.builder() + .accessTokenFormat(tokenFormat) + .accessTokenTimeToLive(Duration.ofSeconds(clientObj.getAccessTokenValiditySeconds())) + .refreshTokenTimeToLive(Duration.ofSeconds(clientObj.getRefreshTokenValiditySeconds())) + .build() + ) + .clientSettings( + ClientSettings.builder() + .requireAuthorizationConsent(!BooleanUtil.toBoolean(clientObj.getAutoapprove())) + .build() + ) + .build(); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisOAuth2AuthorizationConsentService.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisOAuth2AuthorizationConsentService.java new file mode 100644 index 000000000..f916675dd --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisOAuth2AuthorizationConsentService.java @@ -0,0 +1,55 @@ +package com.central.oauth.service.impl; + +import lombok.RequiredArgsConstructor; +import org.redisson.api.RedissonClient; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +import java.time.Duration; + +/** + * @author: zlt + * @date: 2023/11/10 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@RequiredArgsConstructor +@Component +public class RedisOAuth2AuthorizationConsentService implements OAuth2AuthorizationConsentService { + + private final RedissonClient redissonClient;; + + private final static Long TIMEOUT = 10L; + + @Override + public void save(OAuth2AuthorizationConsent authorizationConsent) { + Assert.notNull(authorizationConsent, "authorizationConsent cannot be null"); + + redissonClient.getBucket(buildKey(authorizationConsent)) + .set(authorizationConsent, Duration.ofMinutes(TIMEOUT)); + } + + @Override + public void remove(OAuth2AuthorizationConsent authorizationConsent) { + Assert.notNull(authorizationConsent, "authorizationConsent cannot be null"); + redissonClient.getBucket(buildKey(authorizationConsent)).delete(); + } + + @Override + public OAuth2AuthorizationConsent findById(String registeredClientId, String principalName) { + Assert.hasText(registeredClientId, "registeredClientId cannot be empty"); + Assert.hasText(principalName, "principalName cannot be empty"); + return (OAuth2AuthorizationConsent) redissonClient.getBucket(buildKey(registeredClientId, principalName)).get(); + } + + private static String buildKey(String registeredClientId, String principalName) { + return "token:consent:" + registeredClientId + ":" + principalName; + } + + private static String buildKey(OAuth2AuthorizationConsent authorizationConsent) { + return buildKey(authorizationConsent.getRegisteredClientId(), authorizationConsent.getPrincipalName()); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisSecurityContextRepository.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisSecurityContextRepository.java new file mode 100644 index 000000000..fce6a5590 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisSecurityContextRepository.java @@ -0,0 +1,138 @@ +package com.central.oauth.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.central.common.constant.SecurityConstants; +import com.central.oauth.model.SupplierDeferredSecurityContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import lombok.RequiredArgsConstructor; +import org.redisson.api.RBucket; +import org.redisson.api.RedissonClient; +import org.redisson.codec.SerializationCodec; +import org.springframework.security.core.context.DeferredSecurityContext; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.context.SecurityContextHolderStrategy; +import org.springframework.security.web.context.HttpRequestResponseHolder; +import org.springframework.security.web.context.SecurityContextRepository; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.util.function.Supplier; + +/** + * 基于redis存储认证信息,解决多节点uaa单点登录信息互通 + * + * @author: zlt + * @date: 2023/12/06 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Component +@RequiredArgsConstructor +public class RedisSecurityContextRepository implements SecurityContextRepository { + /** + * 认证信息存储前缀 + */ + public static final String SECURITY_CONTEXT_PREFIX_KEY = "security_context:"; + /** + * 随机字符串请求头名字 + */ + public static final String NONCE_HEADER_NAME = "nonceId"; + + private final static SerializationCodec AUTH_CODEC = new SerializationCodec(); + + private final SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder + .getContextHolderStrategy(); + private final RedissonClient redissonClient; + + @Override + public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) { + throw new UnsupportedOperationException("Method deprecated."); + } + + @Override + public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) { + String nonce = getNonce(request); + if (StrUtil.isEmpty(nonce)) { + return; + } + + // 如果当前的context是空的,则移除 + SecurityContext emptyContext = this.securityContextHolderStrategy.createEmptyContext(); + RBucket rBucket = this.getBucket(nonce); + if (emptyContext.equals(context)) { + rBucket.delete(); + } else { + // 保存认证信息 + rBucket.set(context, Duration.ofSeconds(SecurityConstants.ACCESS_TOKEN_VALIDITY_SECONDS)); + } + } + + @Override + public boolean containsContext(HttpServletRequest request) { + String nonce = getNonce(request); + if (StrUtil.isEmpty(nonce)) { + return false; + } + // 检验当前请求是否有认证信息 + return this.getBucket(nonce).get() != null; + } + + @Override + public DeferredSecurityContext loadDeferredContext(HttpServletRequest request) { + Supplier supplier = () -> readSecurityContextFromRedis(request); + return new SupplierDeferredSecurityContext(supplier, this.securityContextHolderStrategy); + } + + /** + * 从redis中获取认证信息 + * + * @param request 当前请求 + * @return 认证信息 + */ + private SecurityContext readSecurityContextFromRedis(HttpServletRequest request) { + if (request == null) { + return null; + } + String nonce = getNonce(request); + if (StrUtil.isEmpty(nonce)) { + return null; + } + // 根据缓存id获取认证信息 + RBucket rBucket = this.getBucket(nonce); + SecurityContext context = rBucket.get(); + if (context != null) { + rBucket.expire(Duration.ofSeconds(SecurityConstants.ACCESS_TOKEN_VALIDITY_SECONDS)); + } + return context; + } + + /** + * 先从请求头中找,找不到去请求参数中找,找不到获取当前session的id + * 2023-07-11新增逻辑:获取当前session的sessionId + * + * @param request 当前请求 + * @return 随机字符串(sessionId),这个字符串本来是前端生成,现在改为后端获取的sessionId + */ + private String getNonce(HttpServletRequest request) { + String nonce = request.getHeader(NONCE_HEADER_NAME); + if (StrUtil.isEmpty(nonce)) { + nonce = request.getParameter(NONCE_HEADER_NAME); + if (StrUtil.isEmpty(nonce)) { + HttpSession session = request.getSession(Boolean.FALSE); + if (session != null) { + nonce = session.getId(); + } + } + } + return nonce; + } + + private RBucket getBucket(String nonce) { + return redissonClient.getBucket(SECURITY_CONTEXT_PREFIX_KEY + nonce, AUTH_CODEC); + } + +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java new file mode 100644 index 000000000..83cf4776e --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java @@ -0,0 +1,102 @@ +package com.central.oauth.service.impl; + +import cn.hutool.core.util.PageUtil; +import cn.hutool.core.util.StrUtil; +import com.central.common.constant.SecurityConstants; +import com.central.common.model.PageResult; +import com.central.common.redis.template.RedisRepository; +import com.central.oauth.model.TokenVo; +import com.central.oauth.service.ITokensService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.MapUtils; +import org.redisson.api.RBucket; +import org.redisson.api.RList; +import org.redisson.api.RedissonClient; +import org.redisson.codec.SerializationCodec; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; +import org.springframework.stereotype.Service; + +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * token管理服务(redis token) + * + * @author zlt + * @date 2019/7/12 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class RedisTokensServiceImpl implements ITokensService { + private final static SerializationCodec AUTH_CODEC = new SerializationCodec(); + private static final String AUTHORIZATION = "token"; + private final RedissonClient redisson; + + @Override + public PageResult listTokens(Map params, String clientId) { + Integer page = MapUtils.getInteger(params, "page"); + Integer limit = MapUtils.getInteger(params, "limit"); + int[] startEnds = PageUtil.transToStartEnd(page-1, limit); + //根据请求参数生成redis的key + String redisKey = getRedisKey(params, clientId); + RList tokenList = redisson.getList(redisKey); + long size = tokenList.size(); + List result = new ArrayList<>(limit); + //查询token集合 + List tokens = tokenList.range(startEnds[0], startEnds[1]-1); + if (tokens != null) { + for (String token : tokens) { + //构造token对象 + TokenVo tokenVo = new TokenVo(); + tokenVo.setTokenValue(token); + //获取用户信息 + RBucket rBucket = redisson.getBucket(buildKey(OAuth2ParameterNames.ACCESS_TOKEN, token), AUTH_CODEC); + OAuth2Authorization authorization = rBucket.get(); + if (authorization != null) { + OAuth2AccessToken accessToken = authorization.getAccessToken().getToken(); + if (accessToken != null && accessToken.getExpiresAt() != null) { + tokenVo.setExpiration(Date.from(accessToken.getExpiresAt().plus(8, ChronoUnit.HOURS))); + } + tokenVo.setUsername(authorization.getPrincipalName()); + tokenVo.setClientId(authorization.getRegisteredClientId()); + tokenVo.setGrantType(authorization.getAuthorizationGrantType().getValue()); + + String accountType = (String)authorization.getAttributes().get(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME); + tokenVo.setAccountType(accountType); + } + result.add(tokenVo); + } + } + return PageResult.builder().data(result).code(0).count(size).build(); + } + + /** + * 根据请求参数生成redis的key + */ + private String getRedisKey(Map params, String clientId) { + String result; + String username = MapUtils.getString(params, "username"); + if (StrUtil.isNotEmpty(username)) { + result = this.buildKey(SecurityConstants.REDIS_UNAME_TO_ACCESS, clientId + "::" + username); + } else { + result = this.buildKey(SecurityConstants.REDIS_CLIENT_ID_TO_ACCESS, clientId); + } + return result; + } + + private String buildKey(String type, String id) { + return String.format("%s::%s::%s", AUTHORIZATION, type, id); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RegisteredClientService.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RegisteredClientService.java new file mode 100644 index 000000000..75c3cd928 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RegisteredClientService.java @@ -0,0 +1,89 @@ +package com.central.oauth.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.central.common.constant.SecurityConstants; +import com.central.common.model.PageResult; +import com.central.oauth.model.Client; +import com.central.oauth.service.IClientService; +import com.central.oauth2.common.pojo.ClientDto; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.redisson.api.RBucket; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * @author zlt + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class RegisteredClientService { + private final IClientService clientService; + private final RedissonClient redisson; + + public void saveClient(Client client) throws Exception { + clientService.saveClient(client); + redisson.getBucket(clientRedisKey(client.getClientId())).set(client); + } + + public PageResult listClient(Map params, boolean isPage) { + PageResult clientPage = clientService.listClient(params, isPage); + PageResult result = new PageResult<>(); + result.setCode(clientPage.getCode()); + result.setCount(clientPage.getCount()); + result.setData(BeanUtil.copyToList(clientPage.getData(), ClientDto.class)); + return result; + } + + public ClientDto getById(long id) { + return BeanUtil.copyProperties(clientService.getById(id), ClientDto.class); + } + + public void delClient(long id) { + Client client = clientService.getById(id); + if (client != null) { + clientService.delClient(id); + redisson.getBucket(clientRedisKey(client.getClientId())).delete(); + } + } + + public ClientDto loadClientByClientId(String clientId) { + RBucket clientBucket = redisson.getBucket(clientRedisKey(clientId)); + ClientDto clientDto = clientBucket.get(); + if (clientDto != null) { + return clientDto; + } + Client clientObj = clientService.loadClientByClientId(clientId); + clientDto = BeanUtil.copyProperties(clientObj, ClientDto.class); + clientBucket.set(clientDto); + return clientDto; + } + + public void loadAllClientToCache() { + List clientList = clientService.list(); + clientList.forEach(c -> { + ClientDto clientDto = BeanUtil.copyProperties(c, ClientDto.class);; + redisson.getBucket(clientRedisKey(c.getClientId())).set(clientDto); + }); + } + + public List list() { + return BeanUtil.copyToList(clientService.list(), ClientDto.class); + } + + public ClientDto getRegisteredClientByClientId(String clientId) { + Client clientObj = clientService.loadClientByClientId(clientId); + return BeanUtil.copyProperties(clientObj, ClientDto.class); + } + + private String clientRedisKey(String clientId) { + return SecurityConstants.CACHE_CLIENT_KEY + ":" + clientId; + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UnifiedLogoutService.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/UnifiedLogoutService.java new file mode 100644 index 000000000..b8c66921e --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/UnifiedLogoutService.java @@ -0,0 +1,125 @@ +package com.central.oauth.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.central.oauth.utils.UsernameHolder; +import com.central.oauth2.common.pojo.ClientDto; +import com.central.oauth2.common.service.impl.RedisOAuth2AuthorizationService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.task.TaskExecutor; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 统一登出服务 + * + * @author zlt + * @version 1.0 + * @date 2023/11/18 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Slf4j +@Service +public class UnifiedLogoutService { + private final static String LOGOUT_NOTIFY_URL_KEY = "LOGOUT_NOTIFY_URL_LIST"; + + private final RestTemplate restTemplate; + + private final TaskExecutor taskExecutor; + + private final RegisteredClientService clientService; + + private final RedisOAuth2AuthorizationService authorizationService; + + public UnifiedLogoutService(RestTemplate restTemplate, TaskExecutor taskExecutor + , RegisteredClientService clientService + , @Autowired(required = false) RedisOAuth2AuthorizationService authorizationService) { + this.restTemplate = restTemplate; + this.taskExecutor = taskExecutor; + this.clientService = clientService; + this.authorizationService = authorizationService; + } + + public void allLogout() { + if (authorizationService == null) { + throw new RuntimeException("the 'zlt.oauth2.token.store' parameter must be redis"); + } + + Set urls = this.getLogoutNotifyUrl(); + for (String url : urls) { + taskExecutor.execute(() -> { + try { + restTemplate.getForObject(url, Void.class); + } catch (Exception e) { + log.warn(e.getMessage()); + } + }); + } + } + + /** + * 获取登出需要通知的地址集合 + */ + private Set getLogoutNotifyUrl() { + String username = UsernameHolder.getContext(); + Set logoutNotifyUrls = new HashSet<>(); + try { + List clientDetails = clientService.list(); + Map informationMap; + for (ClientDto client : clientDetails) { + informationMap = this.getInfoMap(client.getAdditionalInformation()); + String urls = (String)informationMap.get(LOGOUT_NOTIFY_URL_KEY); + if (StrUtil.isNotEmpty(urls)) { + List tokens = authorizationService.findTokensByClientIdAndUserName(client.getClientId(), username); + if (CollUtil.isNotEmpty(tokens)) { + //注销所有该用户名下的token + tokens.forEach(authorizationService::remove); + String tokenStr = getTokenValueStr(tokens); + logoutNotifyUrls.addAll(generateNotifyUrls(urls.split(","), tokenStr)); + } + } + } + } finally { + UsernameHolder.clearContext(); + } + return logoutNotifyUrls; + } + + private String getTokenValueStr(List tokens) { + if (CollUtil.isNotEmpty(tokens)) { + return StrUtil.join( ",", tokens); + } + return null; + } + + private Set generateNotifyUrls(String[] urls, String tokenStr) { + Set urlSet = new HashSet(urls.length); + for (String url : urls) { + StringBuilder urlBuilder = new StringBuilder(url); + if (url.contains("?")) { + urlBuilder.append("&"); + } else { + urlBuilder.append("?"); + } + urlBuilder.append("tokens=").append(tokenStr); + urlSet.add(urlBuilder.toString()); + } + return urlSet; + } + + private Map getInfoMap(String additionalInformation) { + if (StrUtil.isNotEmpty(additionalInformation)) { + return JSONUtil.toBean(additionalInformation, Map.class); + } + return Map.of(); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceFactory.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceFactory.java new file mode 100644 index 000000000..bc1bb2b5c --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceFactory.java @@ -0,0 +1,53 @@ +package com.central.oauth.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.central.common.constant.SecurityConstants; +import com.central.oauth.service.ZltUserDetailsService; +import com.central.oauth.exception.CustomOAuth2AuthenticationException; +import com.central.oauth2.common.util.AuthUtils; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 用户service工厂 + * + * @author zlt + * @version 1.0 + * @date 2021/7/24 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Slf4j +@Service +public class UserDetailServiceFactory { + private static final String ERROR_MSG = "Cannot find the implementation class for the account type {}"; + + @Resource + private List userDetailsServices; + + public ZltUserDetailsService getService(Authentication authentication) { + String accountType = AuthUtils.getAccountType(authentication); + return this.getService(accountType); + } + + public ZltUserDetailsService getService(String accountType) { + if (StrUtil.isEmpty(accountType)) { + accountType = SecurityConstants.DEF_ACCOUNT_TYPE; + } + log.info("UserDetailServiceFactory.getService:{}", accountType); + if (CollUtil.isNotEmpty(userDetailsServices)) { + for (ZltUserDetailsService userService : userDetailsServices) { + if (userService.supports(accountType)) { + return userService; + } + } + } + throw new CustomOAuth2AuthenticationException(StrUtil.format(ERROR_MSG, accountType)); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceImpl.java index 0f505921f..511593682 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceImpl.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/UserDetailServiceImpl.java @@ -2,7 +2,8 @@ import com.central.common.constant.SecurityConstants; import com.central.common.feign.UserService; -import com.central.common.model.LoginAppUser; +import com.central.common.model.SysUser; +import com.central.common.utils.LoginUserUtils; import com.central.oauth.service.ZltUserDetailsService; import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.DisabledException; @@ -33,29 +34,31 @@ public boolean supports(String accountType) { @Override public UserDetails loadUserByUsername(String username) { - LoginAppUser loginAppUser = userService.findByUsername(username); - if (loginAppUser == null) { + SysUser sysUser = userService.findByUsername(username); + if (sysUser == null) { throw new InternalAuthenticationServiceException("用户名或密码错误"); } - return checkUser(loginAppUser); + checkUser(sysUser); + return LoginUserUtils.getLoginAppUser(sysUser); } @Override public UserDetails loadUserByUserId(String openId) { - LoginAppUser loginAppUser = userService.findByOpenId(openId); - return checkUser(loginAppUser); + SysUser sysUser = userService.findByOpenId(openId); + checkUser(sysUser); + return LoginUserUtils.getLoginAppUser(sysUser); } @Override public UserDetails loadUserByMobile(String mobile) { - LoginAppUser loginAppUser = userService.findByMobile(mobile); - return checkUser(loginAppUser); + SysUser sysUser = userService.findByMobile(mobile); + checkUser(sysUser); + return LoginUserUtils.getLoginAppUser(sysUser); } - private LoginAppUser checkUser(LoginAppUser loginAppUser) { - if (loginAppUser != null && !loginAppUser.isEnabled()) { + private void checkUser(SysUser sysUser) { + if (sysUser != null && !sysUser.getEnabled()) { throw new DisabledException("用户已作废"); } - return loginAppUser; } } diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java index dae161a31..7504b902f 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java @@ -4,16 +4,17 @@ import cn.hutool.core.util.StrUtil; import com.central.common.constant.SecurityConstants; import com.central.common.feign.UserService; -import com.central.common.model.LoginAppUser; import com.central.common.model.Result; -import com.central.common.redis.template.RedisRepository; -import com.central.oauth.exception.ValidateCodeException; +import com.central.common.model.SysUser; import com.central.oauth.service.IValidateCodeService; +import com.central.oauth.exception.CustomOAuth2AuthenticationException; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; +import org.redisson.api.RBucket; +import org.redisson.api.RedissonClient; import org.springframework.stereotype.Service; -import javax.annotation.Resource; +import java.time.Duration; /** * @author zlt @@ -23,13 +24,12 @@ * Github: https://github.com/zlt2000 */ @Slf4j +@RequiredArgsConstructor @Service public class ValidateCodeServiceImpl implements IValidateCodeService { - @Autowired - private RedisRepository redisRepository; + private final RedissonClient redisson; - @Resource - private UserService userService; + private final UserService userService; /** * 保存用户验证码,和randomStr绑定 @@ -39,7 +39,8 @@ public class ValidateCodeServiceImpl implements IValidateCodeService { */ @Override public void saveImageCode(String deviceId, String imageCode) { - redisRepository.setExpire(buildKey(deviceId), imageCode, SecurityConstants.DEFAULT_IMAGE_EXPIRE); + this.getBucket(deviceId) + .set(imageCode, Duration.ofSeconds(SecurityConstants.DEFAULT_IMAGE_EXPIRE)); } /** @@ -55,13 +56,14 @@ public void saveImageCode(String deviceId, String imageCode) { */ @Override public Result sendSmsCode(String mobile) { - Object tempCode = redisRepository.get(buildKey(mobile)); + RBucket rBucket = this.getBucket(mobile); + Object tempCode = rBucket.get(); if (tempCode != null) { log.error("用户:{}验证码未失效{}", mobile, tempCode); return Result.failed("验证码未失效,请失效后再次申请"); } - LoginAppUser user = userService.findByMobile(mobile); + SysUser user = userService.findByMobile(mobile); if (user == null) { log.error("根据用户手机号{}查询用户为空", mobile); return Result.failed("手机号不存在"); @@ -69,7 +71,7 @@ public Result sendSmsCode(String mobile) { String code = RandomUtil.randomNumbers(4); log.info("短信发送请求消息中心 -> 手机号:{} -> 验证码:{}", mobile, code); - redisRepository.setExpire(buildKey(mobile), code, SecurityConstants.DEFAULT_IMAGE_EXPIRE); + rBucket.set(code, Duration.ofSeconds(SecurityConstants.DEFAULT_IMAGE_EXPIRE)); return Result.succeed("true"); } @@ -79,7 +81,7 @@ public Result sendSmsCode(String mobile) { */ @Override public String getCode(String deviceId) { - return (String)redisRepository.get(buildKey(deviceId)); + return this.getBucket(deviceId).get(); } /** @@ -88,7 +90,7 @@ public String getCode(String deviceId) { */ @Override public void remove(String deviceId) { - redisRepository.del(buildKey(deviceId)); + this.getBucket(deviceId).delete(); } /** @@ -97,19 +99,19 @@ public void remove(String deviceId) { @Override public void validate(String deviceId, String validCode) { if (StrUtil.isBlank(deviceId)) { - throw new ValidateCodeException("请在请求参数中携带deviceId参数"); + throw new CustomOAuth2AuthenticationException("请在请求参数中携带deviceId参数"); } String code = this.getCode(deviceId); if (StrUtil.isBlank(validCode)) { - throw new ValidateCodeException("请填写验证码"); + throw new CustomOAuth2AuthenticationException("请填写验证码"); } if (code == null) { - throw new ValidateCodeException("验证码不存在或已过期"); + throw new CustomOAuth2AuthenticationException("验证码不存在或已过期"); } if (!StrUtil.equals(code, validCode.toLowerCase())) { - throw new ValidateCodeException("验证码不正确"); + throw new CustomOAuth2AuthenticationException("验证码不正确"); } this.remove(deviceId); @@ -118,4 +120,8 @@ public void validate(String deviceId, String validCode) { private String buildKey(String deviceId) { return SecurityConstants.DEFAULT_CODE_KEY + ":" + deviceId; } + + private RBucket getBucket(String deviceId) { + return redisson.getBucket(buildKey(deviceId)); + } } diff --git a/zlt-uaa/src/main/java/com/central/oauth/support/base/BaseAuthenticationConverter.java b/zlt-uaa/src/main/java/com/central/oauth/support/base/BaseAuthenticationConverter.java new file mode 100644 index 000000000..2b6d20ebb --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/support/base/BaseAuthenticationConverter.java @@ -0,0 +1,88 @@ +package com.central.oauth.support.base; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import com.central.oauth.utils.OAuthEndpointUtils; +import com.central.oauth2.common.token.BaseAuthenticationToken; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.security.web.authentication.AuthenticationConverter; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; + +import java.util.*; + +/** + * @author: zlt + * @date: 2023/11/18 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public abstract class BaseAuthenticationConverter implements AuthenticationConverter { + @Override + public Authentication convert(HttpServletRequest request) { + String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE); + if (!this.supportGrantType().equals(grantType)) { + return null; + } + + MultiValueMap parameters = OAuthEndpointUtils.getParameters(request); + return this.getAuthentication(parameters); + } + + public Authentication getAuthentication(MultiValueMap parameters) { + Set requestScopes = this.getRequestScopes(parameters); + + Map additionalParameters = getAdditionalParameters(parameters, this.paramNames()); + + Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication(); + + BaseAuthenticationToken baseToken = this.getToken(parameters); + baseToken.setScopes(requestScopes); + baseToken.setAdditionalParameters(additionalParameters); + baseToken.setClientPrincipal(clientPrincipal); + return baseToken; + }; + + public Set getRequestScopes(MultiValueMap parameters) { + String scope = parameters.getFirst(OAuth2ParameterNames.SCOPE); + Set requestedScopes = null; + if (StrUtil.isNotEmpty(scope)) { + requestedScopes = new HashSet<>( + Arrays.asList(StringUtils.delimitedListToStringArray(scope, " "))); + } else { + requestedScopes = Collections.emptySet(); + } + return requestedScopes; + } + + public Map getAdditionalParameters(MultiValueMap parameters, List paramName) { + Map additionalParameters = new HashMap<>(); + parameters.forEach((key, value) -> { + if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) && + !key.equals(OAuth2ParameterNames.SCOPE)) { + boolean isAdd = true; + if (ArrayUtil.isNotEmpty(paramName)) { + for (String name : paramName) { + if (key.equals(name)) { + isAdd = false; + } + } + } + if (isAdd) { + additionalParameters.put(key, value.get(0)); + } + } + }); + return additionalParameters; + } + + protected abstract String supportGrantType(); + + protected abstract List paramNames(); + + protected abstract BaseAuthenticationToken getToken(MultiValueMap parameters); +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/support/base/BaseAuthenticationProvider.java b/zlt-uaa/src/main/java/com/central/oauth/support/base/BaseAuthenticationProvider.java new file mode 100644 index 000000000..42c129169 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/support/base/BaseAuthenticationProvider.java @@ -0,0 +1,201 @@ +package com.central.oauth.support.base; + +import cn.hutool.core.util.StrUtil; +import com.central.common.constant.SecurityConstants; +import com.central.oauth2.common.token.BaseAuthenticationToken; +import lombok.Getter; +import lombok.Setter; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.core.*; +import org.springframework.security.oauth2.core.oidc.OidcIdToken; +import org.springframework.security.oauth2.core.oidc.OidcScopes; +import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; +import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken; +import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken; +import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; +import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContextHolder; +import org.springframework.security.oauth2.server.authorization.token.DefaultOAuth2TokenContext; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenContext; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +import java.security.Principal; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * 基础provider + * + * @author zlt + * @version 1.0 + * @date 2023/11/18 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Setter +@Getter +public abstract class BaseAuthenticationProvider implements AuthenticationProvider { + private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-4.3"; + private static final OAuth2TokenType ID_TOKEN_TOKEN_TYPE = new OAuth2TokenType(OidcParameterNames.ID_TOKEN); + private final OAuth2AuthorizationService authorizationService; + private final OAuth2TokenGenerator tokenGenerator; + + public BaseAuthenticationProvider(OAuth2AuthorizationService authorizationService + , OAuth2TokenGenerator tokenGenerator) { + Assert.notNull(authorizationService, "authorizationService cannot be null"); + Assert.notNull(tokenGenerator, "tokenGenerator cannot be null"); + this.authorizationService = authorizationService; + this.tokenGenerator = tokenGenerator; + } + + @Override + public Authentication authenticate(Authentication authentication) { + BaseAuthenticationToken authToken = (BaseAuthenticationToken) authentication; + + OAuth2ClientAuthenticationToken clientPrincipal = getAuthenticatedClientElseThrowInvalidClient(authToken); + RegisteredClient registeredClient = clientPrincipal.getRegisteredClient(); + + Set authorizedScopes = authToken.getScopes(); + if (!CollectionUtils.isEmpty(authToken.getScopes())) { + for (String requestedScope : authToken.getScopes()) { + if (!registeredClient.getScopes().contains(requestedScope)) { + throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_SCOPE); + } + } + } + + // 执行登录验证逻辑 + Authentication principal = this.getPrincipal(authentication); + + String accountType = (String)authToken.getAdditionalParameters().get(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME); + if (StrUtil.isEmpty(accountType)) { + accountType = SecurityConstants.DEF_ACCOUNT_TYPE; + authToken.getAdditionalParameters().put(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME, accountType); + } + + // @formatter:off + DefaultOAuth2TokenContext.Builder tokenContextBuilder = DefaultOAuth2TokenContext.builder() + .registeredClient(registeredClient) + .principal(principal) + .authorizationServerContext(AuthorizationServerContextHolder.getContext()) + .authorizedScopes(authorizedScopes) + .authorizationGrantType(this.grantType()) + .authorizationGrant(authToken); + // @formatter:on + + OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization + .withRegisteredClient(registeredClient) + .principalName(principal.getName()) + .attribute(Principal.class.getName(), principal) + .attribute(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME, accountType) + .authorizationGrantType(this.grantType()) + .authorizedScopes(authorizedScopes); + + // ----- Access token ----- + OAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.ACCESS_TOKEN).build(); + OAuth2Token generatedAccessToken = this.tokenGenerator.generate(tokenContext); + if (generatedAccessToken == null) { + OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, + "The token generator failed to generate the access token.", ERROR_URI); + throw new OAuth2AuthenticationException(error); + } + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(), + generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes()); + authorizationBuilder.id(accessToken.getTokenValue()); + if (generatedAccessToken instanceof ClaimAccessor) { + authorizationBuilder.token(accessToken, (metadata) -> + metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, ((ClaimAccessor) generatedAccessToken).getClaims())); + } else { + authorizationBuilder.accessToken(accessToken); + } + + // ----- Refresh token ----- + OAuth2RefreshToken refreshToken = null; + if (registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.REFRESH_TOKEN) && + // Do not issue refresh token to public client + !clientPrincipal.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.NONE)) { + + tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.REFRESH_TOKEN).build(); + OAuth2Token generatedRefreshToken = this.tokenGenerator.generate(tokenContext); + if (!(generatedRefreshToken instanceof OAuth2RefreshToken)) { + OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, + "The token generator failed to generate the refresh token.", ERROR_URI); + throw new OAuth2AuthenticationException(error); + } + refreshToken = (OAuth2RefreshToken) generatedRefreshToken; + authorizationBuilder.refreshToken(refreshToken); + } + + // ----- ID token ----- + OidcIdToken idToken; + if (authorizedScopes.contains(OidcScopes.OPENID)) { + // @formatter:off + tokenContext = tokenContextBuilder + .tokenType(ID_TOKEN_TOKEN_TYPE) + .authorization(authorizationBuilder.build()) // ID token customizer may need access to the access token and/or refresh token + .build(); + // @formatter:on + OAuth2Token generatedIdToken = this.tokenGenerator.generate(tokenContext); + if (!(generatedIdToken instanceof Jwt)) { + OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, + "The token generator failed to generate the ID token.", ERROR_URI); + throw new OAuth2AuthenticationException(error); + } + + idToken = new OidcIdToken(generatedIdToken.getTokenValue(), generatedIdToken.getIssuedAt(), + generatedIdToken.getExpiresAt(), ((Jwt) generatedIdToken).getClaims()); + authorizationBuilder.token(idToken, (metadata) -> + metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, idToken.getClaims())); + } else { + idToken = null; + } + + OAuth2Authorization authorization = authorizationBuilder.build(); + this.authorizationService.save(authorization); + + Map additionalParameters = Collections.emptyMap(); + if (idToken != null) { + additionalParameters = new HashMap<>(); + additionalParameters.put(OidcParameterNames.ID_TOKEN, idToken.getTokenValue()); + } + + return new OAuth2AccessTokenAuthenticationToken( + registeredClient, clientPrincipal, accessToken, refreshToken, additionalParameters); + } + + private OAuth2ClientAuthenticationToken getAuthenticatedClientElseThrowInvalidClient( + BaseAuthenticationToken authentication) { + + OAuth2ClientAuthenticationToken clientPrincipal = null; + + if (OAuth2ClientAuthenticationToken.class.isAssignableFrom(authentication.getClientPrincipal().getClass())) { + clientPrincipal = (OAuth2ClientAuthenticationToken) authentication.getClientPrincipal(); + } + + if (clientPrincipal != null && clientPrincipal.isAuthenticated()) { + return clientPrincipal; + } + + throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_CLIENT); + } + + /** + * 执行登录验证逻辑 + */ + protected abstract Authentication getPrincipal(Authentication authentication); + + /** + * 获取 GrantType + */ + protected abstract AuthorizationGrantType grantType(); +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/support/mobile/MobileAuthenticationConverter.java b/zlt-uaa/src/main/java/com/central/oauth/support/mobile/MobileAuthenticationConverter.java new file mode 100644 index 000000000..7e5d33d7b --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/support/mobile/MobileAuthenticationConverter.java @@ -0,0 +1,38 @@ +package com.central.oauth.support.mobile; + +import com.central.oauth.support.base.BaseAuthenticationConverter; +import com.central.oauth.utils.OAuthEndpointUtils; +import com.central.oauth2.common.token.BaseAuthenticationToken; +import com.central.oauth2.common.token.MobileAuthenticationToken; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.util.MultiValueMap; + +import java.util.List; + +/** + * @author: zlt + * @date: 2023/11/18 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class MobileAuthenticationConverter extends BaseAuthenticationConverter { + private final static String PARAM_MOBILE= "mobile"; + + @Override + protected String supportGrantType() { + return MobileAuthenticationToken.GRANT_TYPE.getValue(); + } + + @Override + protected List paramNames() { + return List.of(PARAM_MOBILE, OAuth2ParameterNames.PASSWORD); + } + + @Override + protected BaseAuthenticationToken getToken(MultiValueMap parameters) { + String mobile = OAuthEndpointUtils.getParam(parameters, PARAM_MOBILE); + String password = OAuthEndpointUtils.getParam(parameters, OAuth2ParameterNames.PASSWORD); + return new MobileAuthenticationToken(mobile, password); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/support/mobile/MobileAuthenticationProvider.java b/zlt-uaa/src/main/java/com/central/oauth/support/mobile/MobileAuthenticationProvider.java new file mode 100644 index 000000000..8323e34a4 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/support/mobile/MobileAuthenticationProvider.java @@ -0,0 +1,67 @@ +package com.central.oauth.support.mobile; + +import com.central.oauth.service.impl.UserDetailServiceFactory; +import com.central.oauth.support.base.BaseAuthenticationProvider; +import com.central.oauth.exception.CustomOAuth2AuthenticationException; +import com.central.oauth2.common.token.MobileAuthenticationToken; +import lombok.Getter; +import lombok.Setter; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.OAuth2Token; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator; +import org.springframework.util.Assert; + +/** + * @author zlt + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Setter +@Getter +public class MobileAuthenticationProvider extends BaseAuthenticationProvider { + private UserDetailServiceFactory userDetailsServiceFactory; + private PasswordEncoder passwordEncoder; + + public MobileAuthenticationProvider(OAuth2AuthorizationService authorizationService + , OAuth2TokenGenerator tokenGenerator + , UserDetailServiceFactory userDetailsServiceFactory, PasswordEncoder passwordEncoder) { + super(authorizationService, tokenGenerator); + Assert.notNull(userDetailsServiceFactory, "userDetailsServiceFactory cannot be null"); + Assert.notNull(passwordEncoder, "passwordEncoder cannot be null"); + this.userDetailsServiceFactory = userDetailsServiceFactory; + this.passwordEncoder = passwordEncoder; + } + + @Override + public boolean supports(Class authentication) { + return MobileAuthenticationToken.class.isAssignableFrom(authentication); + } + + @Override + protected Authentication getPrincipal(Authentication authentication) { + MobileAuthenticationToken authToken = (MobileAuthenticationToken) authentication; + String mobile = (String) authToken.getPrincipal(); + String password = authToken.getCredentials(); + UserDetails userDetails; + try { + userDetails = userDetailsServiceFactory.getService(authToken).loadUserByMobile(mobile); + } catch (AuthenticationException e) { + throw new CustomOAuth2AuthenticationException(e.getMessage()); + } + if (userDetails == null || !passwordEncoder.matches(password, userDetails.getPassword())) { + throw new CustomOAuth2AuthenticationException("手机号或密码错误"); + } + return new MobileAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities()); + } + + @Override + protected AuthorizationGrantType grantType() { + return MobileAuthenticationToken.GRANT_TYPE; + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/support/openid/OpenIdAuthenticationConverter.java b/zlt-uaa/src/main/java/com/central/oauth/support/openid/OpenIdAuthenticationConverter.java new file mode 100644 index 000000000..82127a802 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/support/openid/OpenIdAuthenticationConverter.java @@ -0,0 +1,36 @@ +package com.central.oauth.support.openid; + +import com.central.oauth.support.base.BaseAuthenticationConverter; +import com.central.oauth.utils.OAuthEndpointUtils; +import com.central.oauth2.common.token.BaseAuthenticationToken; +import com.central.oauth2.common.token.OpenIdAuthenticationToken; +import org.springframework.util.MultiValueMap; + +import java.util.List; + +/** + * @author: zlt + * @date: 2023/11/18 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class OpenIdAuthenticationConverter extends BaseAuthenticationConverter { + private final static String PARAM_OPENID = "openId"; + + @Override + protected String supportGrantType() { + return OpenIdAuthenticationToken.GRANT_TYPE.getValue(); + } + + @Override + protected List paramNames() { + return List.of(PARAM_OPENID); + } + + @Override + protected BaseAuthenticationToken getToken(MultiValueMap parameters) { + String openId = OAuthEndpointUtils.getParam(parameters, PARAM_OPENID); + return new OpenIdAuthenticationToken(openId); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/support/openid/OpenIdAuthenticationProvider.java b/zlt-uaa/src/main/java/com/central/oauth/support/openid/OpenIdAuthenticationProvider.java new file mode 100644 index 000000000..151d9b0d9 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/support/openid/OpenIdAuthenticationProvider.java @@ -0,0 +1,63 @@ +package com.central.oauth.support.openid; + +import com.central.oauth.service.impl.UserDetailServiceFactory; +import com.central.oauth.support.base.BaseAuthenticationProvider; +import com.central.oauth.exception.CustomOAuth2AuthenticationException; +import com.central.oauth2.common.token.OpenIdAuthenticationToken; +import lombok.Getter; +import lombok.Setter; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.OAuth2Token; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator; +import org.springframework.util.Assert; + +/** + * @author: zlt + * @date: 2023/11/18 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Setter +@Getter +public class OpenIdAuthenticationProvider extends BaseAuthenticationProvider { + private UserDetailServiceFactory userDetailsServiceFactory; + + public OpenIdAuthenticationProvider(OAuth2AuthorizationService authorizationService + , OAuth2TokenGenerator tokenGenerator + , UserDetailServiceFactory userDetailsServiceFactory) { + super(authorizationService, tokenGenerator); + Assert.notNull(userDetailsServiceFactory, "userDetailsServiceFactory cannot be null"); + this.userDetailsServiceFactory = userDetailsServiceFactory; + } + + @Override + public boolean supports(Class authentication) { + return OpenIdAuthenticationToken.class.isAssignableFrom(authentication); + } + + @Override + protected Authentication getPrincipal(Authentication authentication) { + OpenIdAuthenticationToken authToken = (OpenIdAuthenticationToken) authentication; + String openId = (String) authToken.getPrincipal(); + UserDetails userDetails; + try { + userDetails = userDetailsServiceFactory.getService(authToken).loadUserByUserId(openId); + } catch (AuthenticationException e) { + throw new CustomOAuth2AuthenticationException(e.getMessage()); + } + if (userDetails == null) { + throw new CustomOAuth2AuthenticationException("openId错误"); + } + return new OpenIdAuthenticationToken(userDetails, userDetails.getAuthorities()); + } + + @Override + protected AuthorizationGrantType grantType() { + return OpenIdAuthenticationToken.GRANT_TYPE; + } +} \ No newline at end of file diff --git a/zlt-uaa/src/main/java/com/central/oauth/support/password/PasswordAuthenticationConverter.java b/zlt-uaa/src/main/java/com/central/oauth/support/password/PasswordAuthenticationConverter.java new file mode 100644 index 000000000..80630a7de --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/support/password/PasswordAuthenticationConverter.java @@ -0,0 +1,36 @@ +package com.central.oauth.support.password; + +import com.central.oauth.support.base.BaseAuthenticationConverter; +import com.central.oauth.utils.OAuthEndpointUtils; +import com.central.oauth2.common.token.BaseAuthenticationToken; +import com.central.oauth2.common.token.PasswordAuthenticationToken; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.util.MultiValueMap; + +import java.util.List; + +/** + * @author: zlt + * @date: 2023/11/18 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class PasswordAuthenticationConverter extends BaseAuthenticationConverter { + @Override + protected String supportGrantType() { + return PasswordAuthenticationToken.GRANT_TYPE.getValue(); + } + + @Override + protected List paramNames() { + return List.of(OAuth2ParameterNames.USERNAME, OAuth2ParameterNames.PASSWORD); + } + + @Override + protected BaseAuthenticationToken getToken(MultiValueMap parameters) { + String username = OAuthEndpointUtils.getParam(parameters, OAuth2ParameterNames.USERNAME); + String password = OAuthEndpointUtils.getParam(parameters, OAuth2ParameterNames.PASSWORD); + return new PasswordAuthenticationToken(username, password); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/support/password/PasswordAuthenticationProvider.java b/zlt-uaa/src/main/java/com/central/oauth/support/password/PasswordAuthenticationProvider.java new file mode 100644 index 000000000..fbb82caea --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/support/password/PasswordAuthenticationProvider.java @@ -0,0 +1,71 @@ +package com.central.oauth.support.password; + +import com.central.oauth.service.impl.UserDetailServiceFactory; +import com.central.oauth.support.base.BaseAuthenticationProvider; +import com.central.oauth.exception.CustomOAuth2AuthenticationException; +import com.central.oauth2.common.token.PasswordAuthenticationToken; +import lombok.Getter; +import lombok.Setter; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.OAuth2Token; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator; +import org.springframework.util.Assert; + +/** + * 用户名密码 provider + * + * @author zlt + * @version 1.0 + * @date 2023/11/18 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Setter +@Getter +public class PasswordAuthenticationProvider extends BaseAuthenticationProvider { + private final UserDetailServiceFactory userDetailsServiceFactory; + private final PasswordEncoder passwordEncoder; + + public PasswordAuthenticationProvider(OAuth2AuthorizationService authorizationService + , OAuth2TokenGenerator tokenGenerator + , UserDetailServiceFactory userDetailsServiceFactory, PasswordEncoder passwordEncoder) { + super(authorizationService, tokenGenerator); + Assert.notNull(userDetailsServiceFactory, "userDetailsServiceFactory cannot be null"); + Assert.notNull(passwordEncoder, "passwordEncoder cannot be null"); + this.userDetailsServiceFactory = userDetailsServiceFactory; + this.passwordEncoder = passwordEncoder; + } + + @Override + public boolean supports(Class authentication) { + return PasswordAuthenticationToken.class.isAssignableFrom(authentication); + } + + @Override + protected Authentication getPrincipal(Authentication authentication) { + PasswordAuthenticationToken authToken = (PasswordAuthenticationToken) authentication; + String username = (String) authToken.getPrincipal(); + String password = authToken.getCredentials(); + UserDetails userDetails; + try { + userDetails = userDetailsServiceFactory.getService(authToken).loadUserByUsername(username); + } catch (AuthenticationException e) { + throw new CustomOAuth2AuthenticationException(e.getMessage()); + } + if (userDetails == null || !passwordEncoder.matches(password, userDetails.getPassword())) { + throw new CustomOAuth2AuthenticationException("用户名或密码错误"); + } + return new PasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities()); + } + + @Override + protected AuthorizationGrantType grantType() { + return PasswordAuthenticationToken.GRANT_TYPE; + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/support/passwordCode/PasswordCodeAuthenticationConverter.java b/zlt-uaa/src/main/java/com/central/oauth/support/passwordCode/PasswordCodeAuthenticationConverter.java new file mode 100644 index 000000000..4aeca5d68 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/support/passwordCode/PasswordCodeAuthenticationConverter.java @@ -0,0 +1,41 @@ +package com.central.oauth.support.passwordCode; + +import com.central.oauth.support.base.BaseAuthenticationConverter; +import com.central.oauth.utils.OAuthEndpointUtils; +import com.central.oauth2.common.token.BaseAuthenticationToken; +import com.central.oauth2.common.token.PasswordCodeAuthenticationToken; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.util.MultiValueMap; + +import java.util.List; + +/** + * @author: zlt + * @date: 2023/11/18 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class PasswordCodeAuthenticationConverter extends BaseAuthenticationConverter { + private final static String PARAM_DEVICEID = "deviceId"; + private final static String PARAM_VALIDCODE = "validCode"; + @Override + protected String supportGrantType() { + return PasswordCodeAuthenticationToken.GRANT_TYPE.getValue(); + } + + @Override + protected List paramNames() { + return List.of(OAuth2ParameterNames.USERNAME, OAuth2ParameterNames.PASSWORD + , PARAM_DEVICEID, PARAM_VALIDCODE); + } + + @Override + protected BaseAuthenticationToken getToken(MultiValueMap parameters) { + String username = OAuthEndpointUtils.getParam(parameters, OAuth2ParameterNames.USERNAME); + String password = OAuthEndpointUtils.getParam(parameters, OAuth2ParameterNames.PASSWORD); + String deviceId = OAuthEndpointUtils.getParam(parameters, PARAM_DEVICEID); + String validCode = OAuthEndpointUtils.getParam(parameters, PARAM_VALIDCODE); + return new PasswordCodeAuthenticationToken(username, password, deviceId, validCode); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/support/passwordCode/PasswordCodeAuthenticationProvider.java b/zlt-uaa/src/main/java/com/central/oauth/support/passwordCode/PasswordCodeAuthenticationProvider.java new file mode 100644 index 000000000..f6ef5ba81 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/support/passwordCode/PasswordCodeAuthenticationProvider.java @@ -0,0 +1,81 @@ +package com.central.oauth.support.passwordCode; + +import com.central.oauth.service.IValidateCodeService; +import com.central.oauth.service.impl.UserDetailServiceFactory; +import com.central.oauth.support.base.BaseAuthenticationProvider; +import com.central.oauth.exception.CustomOAuth2AuthenticationException; +import com.central.oauth2.common.token.PasswordCodeAuthenticationToken; +import lombok.Getter; +import lombok.Setter; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.OAuth2Token; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator; +import org.springframework.util.Assert; + +/** + * 用户名密码+图像验证码 provider + * + * @author zlt + * @version 1.0 + * @date 2023/11/25 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Setter +@Getter +public class PasswordCodeAuthenticationProvider extends BaseAuthenticationProvider { + private final UserDetailServiceFactory userDetailsServiceFactory; + private final PasswordEncoder passwordEncoder; + private final IValidateCodeService validateCodeService; + + public PasswordCodeAuthenticationProvider(OAuth2AuthorizationService authorizationService + , OAuth2TokenGenerator tokenGenerator + , UserDetailServiceFactory userDetailsServiceFactory, PasswordEncoder passwordEncoder + , IValidateCodeService validateCodeService) { + super(authorizationService, tokenGenerator); + Assert.notNull(userDetailsServiceFactory, "userDetailsServiceFactory cannot be null"); + Assert.notNull(passwordEncoder, "passwordEncoder cannot be null"); + this.userDetailsServiceFactory = userDetailsServiceFactory; + this.passwordEncoder = passwordEncoder; + this.validateCodeService = validateCodeService; + } + + @Override + public boolean supports(Class authentication) { + return PasswordCodeAuthenticationToken.class.isAssignableFrom(authentication); + } + + @Override + protected Authentication getPrincipal(Authentication authentication) { + PasswordCodeAuthenticationToken authToken = (PasswordCodeAuthenticationToken) authentication; + String deviceId = authToken.getDeviceId(); + String validCode = authToken.getValidCode(); + + //校验图形验证码 + validateCodeService.validate(deviceId, validCode); + + String username = (String) authToken.getPrincipal(); + String password = authToken.getCredentials(); + UserDetails userDetails; + try { + userDetails = userDetailsServiceFactory.getService(authToken).loadUserByUsername(username); + } catch (AuthenticationException e) { + throw new CustomOAuth2AuthenticationException(e.getMessage()); + } + if (userDetails == null || !passwordEncoder.matches(password, userDetails.getPassword())) { + throw new CustomOAuth2AuthenticationException("用户名或密码错误"); + } + return new PasswordCodeAuthenticationToken(userDetails, userDetails.getPassword(), deviceId, userDetails.getAuthorities()); + } + + @Override + protected AuthorizationGrantType grantType() { + return PasswordCodeAuthenticationToken.GRANT_TYPE; + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/utils/OAuth2ConfigurerUtils.java b/zlt-uaa/src/main/java/com/central/oauth/utils/OAuth2ConfigurerUtils.java new file mode 100644 index 000000000..010bcaabb --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/utils/OAuth2ConfigurerUtils.java @@ -0,0 +1,197 @@ +package com.central.oauth.utils; + +import com.nimbusds.jose.jwk.source.JWKSource; +import com.nimbusds.jose.proc.SecurityContext; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.context.ApplicationContext; +import org.springframework.core.ResolvableType; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.core.OAuth2Token; +import org.springframework.security.oauth2.jwt.JwtEncoder; +import org.springframework.security.oauth2.jwt.NimbusJwtEncoder; +import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationConsentService; +import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService; +import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; +import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository; +import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings; +import org.springframework.security.oauth2.server.authorization.token.*; +import org.springframework.util.StringUtils; + +import java.util.Map; + +/** + * @author: zlt + * @date: 2023/11/16 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class OAuth2ConfigurerUtils { + private OAuth2ConfigurerUtils() { + } + + public static RegisteredClientRepository getRegisteredClientRepository(HttpSecurity httpSecurity) { + RegisteredClientRepository registeredClientRepository = httpSecurity.getSharedObject(RegisteredClientRepository.class); + if (registeredClientRepository == null) { + registeredClientRepository = getBean(httpSecurity, RegisteredClientRepository.class); + httpSecurity.setSharedObject(RegisteredClientRepository.class, registeredClientRepository); + } + return registeredClientRepository; + } + + public static OAuth2AuthorizationService getAuthorizationService(HttpSecurity httpSecurity) { + OAuth2AuthorizationService authorizationService = httpSecurity.getSharedObject(OAuth2AuthorizationService.class); + if (authorizationService == null) { + authorizationService = getOptionalBean(httpSecurity, OAuth2AuthorizationService.class); + if (authorizationService == null) { + authorizationService = new InMemoryOAuth2AuthorizationService(); + } + httpSecurity.setSharedObject(OAuth2AuthorizationService.class, authorizationService); + } + return authorizationService; + } + + public static OAuth2AuthorizationConsentService getAuthorizationConsentService(HttpSecurity httpSecurity) { + OAuth2AuthorizationConsentService authorizationConsentService = httpSecurity.getSharedObject(OAuth2AuthorizationConsentService.class); + if (authorizationConsentService == null) { + authorizationConsentService = getOptionalBean(httpSecurity, OAuth2AuthorizationConsentService.class); + if (authorizationConsentService == null) { + authorizationConsentService = new InMemoryOAuth2AuthorizationConsentService(); + } + httpSecurity.setSharedObject(OAuth2AuthorizationConsentService.class, authorizationConsentService); + } + return authorizationConsentService; + } + + @SuppressWarnings("unchecked") + public static OAuth2TokenGenerator getTokenGenerator(HttpSecurity httpSecurity) { + OAuth2TokenGenerator tokenGenerator = httpSecurity.getSharedObject(OAuth2TokenGenerator.class); + if (tokenGenerator == null) { + tokenGenerator = getOptionalBean(httpSecurity, OAuth2TokenGenerator.class); + if (tokenGenerator == null) { + JwtGenerator jwtGenerator = getJwtGenerator(httpSecurity); + OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator(); + OAuth2TokenCustomizer accessTokenCustomizer = getAccessTokenCustomizer(httpSecurity); + if (accessTokenCustomizer != null) { + accessTokenGenerator.setAccessTokenCustomizer(accessTokenCustomizer); + } + OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator(); + if (jwtGenerator != null) { + tokenGenerator = new DelegatingOAuth2TokenGenerator( + jwtGenerator, accessTokenGenerator, refreshTokenGenerator); + } else { + tokenGenerator = new DelegatingOAuth2TokenGenerator( + accessTokenGenerator, refreshTokenGenerator); + } + } + httpSecurity.setSharedObject(OAuth2TokenGenerator.class, tokenGenerator); + } + return tokenGenerator; + } + + private static JwtGenerator getJwtGenerator(HttpSecurity httpSecurity) { + JwtGenerator jwtGenerator = httpSecurity.getSharedObject(JwtGenerator.class); + if (jwtGenerator == null) { + JwtEncoder jwtEncoder = getJwtEncoder(httpSecurity); + if (jwtEncoder != null) { + jwtGenerator = new JwtGenerator(jwtEncoder); + OAuth2TokenCustomizer jwtCustomizer = getJwtCustomizer(httpSecurity); + if (jwtCustomizer != null) { + jwtGenerator.setJwtCustomizer(jwtCustomizer); + } + httpSecurity.setSharedObject(JwtGenerator.class, jwtGenerator); + } + } + return jwtGenerator; + } + + private static JwtEncoder getJwtEncoder(HttpSecurity httpSecurity) { + JwtEncoder jwtEncoder = httpSecurity.getSharedObject(JwtEncoder.class); + if (jwtEncoder == null) { + jwtEncoder = getOptionalBean(httpSecurity, JwtEncoder.class); + if (jwtEncoder == null) { + JWKSource jwkSource = getJwkSource(httpSecurity); + if (jwkSource != null) { + jwtEncoder = new NimbusJwtEncoder(jwkSource); + } + } + if (jwtEncoder != null) { + httpSecurity.setSharedObject(JwtEncoder.class, jwtEncoder); + } + } + return jwtEncoder; + } + + @SuppressWarnings("unchecked") + public static JWKSource getJwkSource(HttpSecurity httpSecurity) { + JWKSource jwkSource = httpSecurity.getSharedObject(JWKSource.class); + if (jwkSource == null) { + ResolvableType type = ResolvableType.forClassWithGenerics(JWKSource.class, SecurityContext.class); + jwkSource = getOptionalBean(httpSecurity, type); + if (jwkSource != null) { + httpSecurity.setSharedObject(JWKSource.class, jwkSource); + } + } + return jwkSource; + } + + private static OAuth2TokenCustomizer getJwtCustomizer(HttpSecurity httpSecurity) { + ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2TokenCustomizer.class, JwtEncodingContext.class); + return getOptionalBean(httpSecurity, type); + } + + private static OAuth2TokenCustomizer getAccessTokenCustomizer(HttpSecurity httpSecurity) { + ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2TokenCustomizer.class, OAuth2TokenClaimsContext.class); + return getOptionalBean(httpSecurity, type); + } + + public static AuthorizationServerSettings getAuthorizationServerSettings(HttpSecurity httpSecurity) { + AuthorizationServerSettings authorizationServerSettings = httpSecurity.getSharedObject(AuthorizationServerSettings.class); + if (authorizationServerSettings == null) { + authorizationServerSettings = getBean(httpSecurity, AuthorizationServerSettings.class); + httpSecurity.setSharedObject(AuthorizationServerSettings.class, authorizationServerSettings); + } + return authorizationServerSettings; + } + + public static T getBean(HttpSecurity httpSecurity, Class type) { + return httpSecurity.getSharedObject(ApplicationContext.class).getBean(type); + } + + @SuppressWarnings("unchecked") + public static T getBean(HttpSecurity httpSecurity, ResolvableType type) { + ApplicationContext context = httpSecurity.getSharedObject(ApplicationContext.class); + String[] names = context.getBeanNamesForType(type); + if (names.length == 1) { + return (T) context.getBean(names[0]); + } + if (names.length > 1) { + throw new NoUniqueBeanDefinitionException(type, names); + } + throw new NoSuchBeanDefinitionException(type); + } + + public static T getOptionalBean(HttpSecurity httpSecurity, Class type) { + Map beansMap = BeanFactoryUtils.beansOfTypeIncludingAncestors( + httpSecurity.getSharedObject(ApplicationContext.class), type); + if (beansMap.size() > 1) { + throw new NoUniqueBeanDefinitionException(type, beansMap.size(), + "Expected single matching bean of type '" + type.getName() + "' but found " + + beansMap.size() + ": " + StringUtils.collectionToCommaDelimitedString(beansMap.keySet())); + } + return (!beansMap.isEmpty() ? beansMap.values().iterator().next() : null); + } + + @SuppressWarnings("unchecked") + public static T getOptionalBean(HttpSecurity httpSecurity, ResolvableType type) { + ApplicationContext context = httpSecurity.getSharedObject(ApplicationContext.class); + String[] names = context.getBeanNamesForType(type); + if (names.length > 1) { + throw new NoUniqueBeanDefinitionException(type, names); + } + return names.length == 1 ? (T) context.getBean(names[0]) : null; + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/utils/OAuthEndpointUtils.java b/zlt-uaa/src/main/java/com/central/oauth/utils/OAuthEndpointUtils.java new file mode 100644 index 000000000..96d0ed1a8 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/utils/OAuthEndpointUtils.java @@ -0,0 +1,94 @@ +package com.central.oauth.utils; + +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.core.OAuth2ErrorCodes; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.security.oauth2.core.endpoint.PkceParameterNames; +import org.springframework.util.Assert; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @author: zlt + * @date: 2023/11/14 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class OAuthEndpointUtils { + public static final String ACCESS_TOKEN_REQUEST_ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"; + private OAuthEndpointUtils() { + } + + public static MultiValueMap getParameters(HttpServletRequest request) { + Map parameterMap = request.getParameterMap(); + MultiValueMap parameters = new LinkedMultiValueMap<>(parameterMap.size()); + parameterMap.forEach((key, values) -> { + if (values.length > 0) { + for (String value : values) { + parameters.add(key, value); + } + } + }); + return parameters; + } + + public static String getParam(MultiValueMap parameters, String paramName) { + String paramValue = parameters.getFirst(paramName); + if (!StringUtils.hasText(paramValue) || parameters.get(paramName).size() != 1) { + OAuthEndpointUtils.throwError( + OAuth2ErrorCodes.INVALID_REQUEST, + paramName, + OAuthEndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); + } + return paramValue; + } + + public static Map getParametersIfMatchesAuthorizationCodeGrantRequest(HttpServletRequest request, String... exclusions) { + if (!matchesAuthorizationCodeGrantRequest(request)) { + return Collections.emptyMap(); + } + MultiValueMap multiValueParameters = getParameters(request); + for (String exclusion : exclusions) { + multiValueParameters.remove(exclusion); + } + + Map parameters = new HashMap<>(); + multiValueParameters.forEach((key, value) -> + parameters.put(key, (value.size() == 1) ? value.get(0) : value.toArray(new String[0]))); + + return parameters; + } + + public static boolean matchesAuthorizationCodeGrantRequest(HttpServletRequest request) { + return AuthorizationGrantType.AUTHORIZATION_CODE.getValue().equals( + request.getParameter(OAuth2ParameterNames.GRANT_TYPE)) && + request.getParameter(OAuth2ParameterNames.CODE) != null; + } + + public static boolean matchesPkceTokenRequest(HttpServletRequest request) { + return matchesAuthorizationCodeGrantRequest(request) && + request.getParameter(PkceParameterNames.CODE_VERIFIER) != null; + } + + public static void throwError(String errorCode, String parameterName, String errorUri) { + OAuth2Error error = new OAuth2Error(errorCode, "OAuth 2.0 Parameter: " + parameterName, errorUri); + throw new OAuth2AuthenticationException(error); + } + + public static String normalizeUserCode(String userCode) { + Assert.hasText(userCode, "userCode cannot be empty"); + StringBuilder sb = new StringBuilder(userCode.toUpperCase().replaceAll("[^A-Z\\d]+", "")); + Assert.isTrue(sb.length() == 8, "userCode must be exactly 8 alpha/numeric characters"); + sb.insert(4, '-'); + return sb.toString(); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/utils/UsernameHolder.java b/zlt-uaa/src/main/java/com/central/oauth/utils/UsernameHolder.java new file mode 100644 index 000000000..954d63a3d --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/utils/UsernameHolder.java @@ -0,0 +1,25 @@ +package com.central.oauth.utils; + +/** + * @author zlt + * @version 1.0 + * @date 2021/10/22 + *

+ * Blog: http://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class UsernameHolder { + private static final ThreadLocal contextHolder = new ThreadLocal(); + + public static String getContext() { + return contextHolder.get(); + } + + public static void setContext(String username) { + contextHolder.set(username); + } + + public static void clearContext() { + contextHolder.remove(); + } +} diff --git a/zlt-uaa/src/main/resources/application.yml b/zlt-uaa/src/main/resources/application.yml index 0952ae434..88511b4d4 100644 --- a/zlt-uaa/src/main/resources/application.yml +++ b/zlt-uaa/src/main/resources/application.yml @@ -33,10 +33,6 @@ knife4j: swagger-model-name: 认证中心接口文档 zlt: - oauth2: - token: - store: - type: redis security: code: # 忽略验证码的应用编号 From 99c2b90aa22b55999b31ca443b8d686ac2c547f1 Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Wed, 13 Dec 2023 22:19:55 +0800 Subject: [PATCH 15/23] =?UTF-8?q?feat:=20layui=E5=89=8D=E7=AB=AF=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E7=AE=A1=E7=90=86=E5=A2=9E=E5=8A=A0=E2=80=9C=E4=BB=A4?= =?UTF-8?q?=E7=89=8C=E7=B1=BB=E5=9E=8B=E2=80=9D=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/SysUserController.java | 4 ++-- .../central/oauth2/common/pojo/ClientDto.java | 3 ++- .../properties/ResourceServerProperties.java | 2 +- .../central/common/utils/LoginUserUtils.java | 16 ++++++++++++++-- zlt-doc/sql/oauth-center.sql | 2 +- ...6\234\254\345\215\207\347\272\247v6.0.0.sql" | 2 +- .../java/com/central/oauth/model/Client.java | 2 +- .../service/impl/RedisTokensServiceImpl.java | 2 +- .../service/impl/RegisteredClientService.java | 3 ++- .../src/main/resources/mapper/ClientMapper.xml | 2 +- .../resources/static/pages/attestation/app.html | 17 +++++------------ 11 files changed, 31 insertions(+), 24 deletions(-) diff --git a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java index 55c1e86f6..1cf9759af 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java +++ b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java @@ -65,8 +65,8 @@ public class SysUserController { */ @Operation(summary = "根据access_token当前登录用户") @GetMapping("/users/current") - public Result getLoginAppUser() { - return Result.succeed(LoginUserUtils.getCurrentUser(true)); + public Result getLoginAppUser() { + return Result.succeed(LoginUserUtils.getCurrentSysUser()); } /** diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java index 18ea9897e..111d21ae9 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/pojo/ClientDto.java @@ -17,6 +17,7 @@ public class ClientDto implements Serializable { @Serial private static final long serialVersionUID = 1L; + private String id; private String clientId; /** * 应用名称 @@ -37,7 +38,7 @@ public class ClientDto implements Serializable { private String autoapprove = "true"; /** - * token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt)) + * 令牌类型: reference 引用令牌(不透明), self-contained 自包含令牌(jwt)) */ private String tokenFormat = "reference"; diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java index 8b9567c16..03498c619 100644 --- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/properties/ResourceServerProperties.java @@ -16,7 +16,7 @@ @Getter public class ResourceServerProperties { /** - * token格式: + * 令牌类型: * - redis: 通过 redis 来验证 * - inMemory: 通过本地内存来验证 * - jwt: 自包含令牌,自己解析内容 diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java index 2f1c1d4fc..ff0236889 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/LoginUserUtils.java @@ -50,8 +50,7 @@ public static LoginAppUser getCurrentUser(HttpServletRequest request, boolean is if (StrUtil.isAllNotBlank(username, userId)) { if (isFull) { - UserService userService = SpringUtil.getBean(UserService.class); - SysUser sysUser = userService.findByUsername(username); + SysUser sysUser = getSysUser(username); if (sysUser != null) { return getLoginAppUser(sysUser); } @@ -77,6 +76,14 @@ public static LoginAppUser getCurrentUser(boolean isFull) { return null; } + public static SysUser getCurrentSysUser() { + LoginAppUser appUser = getCurrentUser(false); + if (appUser != null) { + return getSysUser(appUser.getUsername()); + } + return null; + } + /** * 获取登陆的用户对象 */ @@ -151,4 +158,9 @@ private static Collection getGrantedAuthoritys(List< } return null; } + + private static SysUser getSysUser(String username) { + UserService userService = SpringUtil.getBean(UserService.class); + return userService.findByUsername(username); + } } diff --git a/zlt-doc/sql/oauth-center.sql b/zlt-doc/sql/oauth-center.sql index 8211ce8f3..7c2b59736 100644 --- a/zlt-doc/sql/oauth-center.sql +++ b/zlt-doc/sql/oauth-center.sql @@ -22,7 +22,7 @@ CREATE TABLE `oauth_client_details` ( `create_time` datetime(0) NULL DEFAULT NULL, `update_time` datetime(0) NULL DEFAULT NULL, `client_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '应用名称', - `token_format` varchar(10) not null DEFAULT 'reference' COMMENT 'token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt))', + `token_format` varchar(20) not null DEFAULT 'reference' COMMENT 'token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt))', `creator_id` int(11) COMMENT '创建人id', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; diff --git "a/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v6.0.0.sql" "b/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v6.0.0.sql" index 4085eef7a..21d830c55 100644 --- "a/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v6.0.0.sql" +++ "b/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v6.0.0.sql" @@ -1,5 +1,5 @@ ------------更新语句 Use `oauth-center`; -alter table oauth_client_details add token_format varchar(10) not null DEFAULT 'reference' COMMENT 'token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt))'; +alter table oauth_client_details add token_format varchar(20) not null DEFAULT 'reference' COMMENT 'token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt))'; alter table oauth_client_details drop column support_id_token; alter table oauth_client_details drop column id_token_validity; \ No newline at end of file diff --git a/zlt-uaa/src/main/java/com/central/oauth/model/Client.java b/zlt-uaa/src/main/java/com/central/oauth/model/Client.java index 7fa296e31..0d268b4b6 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/model/Client.java +++ b/zlt-uaa/src/main/java/com/central/oauth/model/Client.java @@ -33,7 +33,7 @@ public class Client extends SuperEntity { private String additionalInformation = "{}"; private String autoapprove = "true"; /** - * token格式: reference 引用令牌(不透明), self-contained 自包含令牌(jwt)) + * 令牌类型: reference 引用令牌(不透明), self-contained 自包含令牌(jwt)) */ private String tokenFormat = "reference"; diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java index 83cf4776e..5877d0d22 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java @@ -67,7 +67,7 @@ public PageResult listTokens(Map params, String clientI if (authorization != null) { OAuth2AccessToken accessToken = authorization.getAccessToken().getToken(); if (accessToken != null && accessToken.getExpiresAt() != null) { - tokenVo.setExpiration(Date.from(accessToken.getExpiresAt().plus(8, ChronoUnit.HOURS))); + tokenVo.setExpiration(Date.from(accessToken.getExpiresAt())); } tokenVo.setUsername(authorization.getPrincipalName()); tokenVo.setClientId(authorization.getRegisteredClientId()); diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RegisteredClientService.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RegisteredClientService.java index 75c3cd928..857765b27 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/RegisteredClientService.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/RegisteredClientService.java @@ -30,7 +30,8 @@ public class RegisteredClientService { public void saveClient(Client client) throws Exception { clientService.saveClient(client); - redisson.getBucket(clientRedisKey(client.getClientId())).set(client); + ClientDto clientDto = BeanUtil.copyProperties(client, ClientDto.class); + redisson.getBucket(clientRedisKey(client.getClientId())).set(clientDto); } public PageResult listClient(Map params, boolean isPage) { diff --git a/zlt-uaa/src/main/resources/mapper/ClientMapper.xml b/zlt-uaa/src/main/resources/mapper/ClientMapper.xml index 3c00e8d47..7eca3b29c 100644 --- a/zlt-uaa/src/main/resources/mapper/ClientMapper.xml +++ b/zlt-uaa/src/main/resources/mapper/ClientMapper.xml @@ -50,7 +50,7 @@ , scope, authorized_grant_types, autoapprove , access_token_validity accessTokenValiditySeconds , refresh_token_validity refreshTokenValiditySeconds - , support_id_token, refresh_token_validity + , token_format from oauth_client_details diff --git a/zlt-web/layui-web/src/main/resources/static/pages/attestation/app.html b/zlt-web/layui-web/src/main/resources/static/pages/attestation/app.html index b87fd0d81..0e80a5d73 100644 --- a/zlt-web/layui-web/src/main/resources/static/pages/attestation/app.html +++ b/zlt-web/layui-web/src/main/resources/static/pages/attestation/app.html @@ -87,16 +87,10 @@

应用管理

- +
- - -
-
-
- -
- + +