anto: 初始化
This commit is contained in:
parent
191aea0ece
commit
9b9ed034d0
87
txw-sso/README.md
Normal file
87
txw-sso/README.md
Normal file
@ -0,0 +1,87 @@
|
||||
# 1、项目启动类
|
||||
|
||||
无需再编写启动类
|
||||
### 开发环境可使用
|
||||
`com.css.txw.sso.app.DevAppStarter`
|
||||
### 其他环境使用
|
||||
`com.css.ggzc.framework.app.ApplicationStarter`
|
||||
|
||||
# 2、目录结构
|
||||
|
||||
```
|
||||
│ .gitignore
|
||||
│ pom.xml
|
||||
│ README.md
|
||||
├─txw-sso-service-api api包
|
||||
│ │ pom.xml
|
||||
│ └─src
|
||||
│ └─main
|
||||
│ ├─java
|
||||
│ │ └─com.css.txw.sso 模块包
|
||||
│ │ ├─api api接口
|
||||
│ │ │ ISsoApi.java
|
||||
│ │ │
|
||||
│ │ ├─configuration 模块自动装配配置 需要在org.springframework.boot.autoconfigure.AutoConfiguration.imports中配置,基于插件化开发,各模块在该类中可指定要扫描的包等配置,启动类不会自动扫描
|
||||
│ │ │ SsoApiConfiguration.java
|
||||
│ │ │
|
||||
│ │ ├─constants api常量
|
||||
│ │ │ SsoConstants.java
|
||||
│ │ │
|
||||
│ │ └─pojo api pojo
|
||||
│ │
|
||||
│ └─resources 模块相关的配置说明,注意使用config类
|
||||
│ │ additional-spring-configuration-metadata.json
|
||||
│ │
|
||||
│ └─META-INF
|
||||
│ └─spring 模块自动装配配置
|
||||
│ org.springframework.boot.autoconfigure.AutoConfiguration.imports
|
||||
│
|
||||
└─txw-sso-service-biz service包
|
||||
│ pom.xml
|
||||
│
|
||||
└─src
|
||||
└─main
|
||||
├─java
|
||||
│ └─com.css.txw.sso 模块包
|
||||
│ ├─configuration 本模块自动装配设置 需要在org.springframework.boot.autoconfigure.AutoConfiguration.imports中配置,基于插件化开发,各模块在该类中可指定要扫描的包等配置,启动类不会自动扫描
|
||||
│ │ SsoServiceConfiguration.java
|
||||
│ │
|
||||
│ ├─constants
|
||||
│ │
|
||||
│ ├─consumer kafaka消费服务
|
||||
│ │
|
||||
│ ├─controller controller 建议按业务分包 注意:禁止在controller中写跟sql相关的逻辑,一律写到mapper中
|
||||
│ │
|
||||
│ ├─job 定时任务
|
||||
│ │
|
||||
│ ├─mapper mapper 建议按业务分包
|
||||
│ │
|
||||
│ ├─pojo
|
||||
│ │ ├─domain
|
||||
│ │ │
|
||||
│ │ ├─dto
|
||||
│ │ │
|
||||
│ │ └─vo
|
||||
│ │
|
||||
│ │-properties 配置类
|
||||
│ │
|
||||
│ ├─service service 建议按业务分包 注意:SQL相关内容写到mapper中,不要写在service中
|
||||
│ │
|
||||
│ └─util 本业务域工具类 跟业务相关的写在这里 公共类的请优先使用framework中有的,或者在framework中增加
|
||||
│
|
||||
└─resources
|
||||
│ additional-spring-configuration-metadata.json 模块相关的配置说明,注意使用config类
|
||||
│ application.yaml 模块主配置文件
|
||||
│ bootstrap-env.yml 模块env环境配置文件
|
||||
│ bootstrap-local.yml 模块开发环境配置文件
|
||||
│ bootstrap-nacos.yml 模块nacos配置文件
|
||||
│ bootstrap.yml 模块主配置文件
|
||||
│ logback-spring.xml 模块日志配置文件
|
||||
│
|
||||
├─mapper 模块mapper
|
||||
└─META-INF
|
||||
└─spring 模块自动装配配置
|
||||
org.springframework.boot.autoconfigure.AutoConfiguration.imports
|
||||
|
||||
```
|
||||
|
||||
40
txw-sso/pom.xml
Normal file
40
txw-sso/pom.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-dependencies</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>txw-sso</artifactId>
|
||||
<groupId>com.css.txw</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>sso</description>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<modules>
|
||||
<module>txw-sso-service-api</module>
|
||||
<module>txw-sso-service-biz</module>
|
||||
</modules>
|
||||
</project>
|
||||
61
txw-sso/settings.xml
Normal file
61
txw-sso/settings.xml
Normal file
@ -0,0 +1,61 @@
|
||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||
<!--<localRepository>[本地maven库目录]</localRepository>-->
|
||||
<!-- omitted xml -->
|
||||
<!-- 请妥善保管好您的配置,不要随意分享给他人 -->
|
||||
<servers>
|
||||
<server>
|
||||
<id>codingcorp-qyd_repo-mvn_public</id>
|
||||
<username>coding-user</username>
|
||||
<password>coding-pwd</password>
|
||||
</server>
|
||||
</servers>
|
||||
|
||||
<!-- omitted xml -->
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>Repository Proxy</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<!--必须与 settings.xml 的 id 一致-->
|
||||
<id>codingcorp-qyd_repo-mvn_public</id>
|
||||
<name>mvn_public</name>
|
||||
<url>http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>always</updatePolicy>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>codingcorp-qyd_repo-mvn_public</id>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<url>http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<mirrors>
|
||||
<mirror>
|
||||
<id>codingcorp-qyd_repo-mvn_public</id>
|
||||
<!-- 此配置避免了本仓库制品的拉取流量被切换到腾讯云镜像源,保证您在使用镜像加速的同时可以从本仓库拉取制品 -->
|
||||
<mirrorOf>central</mirrorOf>
|
||||
<name>mvn_public</name>
|
||||
<url>http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/</url>
|
||||
</mirror>
|
||||
</mirrors>
|
||||
</settings>
|
||||
88
txw-sso/txw-sso-service-api/pom.xml
Normal file
88
txw-sso/txw-sso-service-api/pom.xml
Normal file
@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<!--api的parent由于编译需要请自行修改 修改后需要调整 本模块groupId-->
|
||||
<parent>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-dependencies</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<groupId>com.css.txw</groupId>
|
||||
<artifactId>txw-sso-service-api</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>sso service api</description>
|
||||
|
||||
<properties>
|
||||
<version.ggzc-framework-dependencies>1.0.0-SNAPSHOT</version.ggzc-framework-dependencies>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter</artifactId>
|
||||
<version>${version.ggzc-framework-dependencies}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.swagger.core.v3</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<!--必须与 settings.xml 的 id 一致-->
|
||||
<id>codingcorp-qyd_repo-mvn_public</id>
|
||||
<name>mvn_public</name>
|
||||
<url>http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<attach>true</attach>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -0,0 +1,10 @@
|
||||
package com.css.txw.sso.api;
|
||||
|
||||
import com.css.txw.sso.constants.SsoApiConstants;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
|
||||
@FeignClient(name = SsoApiConstants.NAME)
|
||||
public interface ISsoApi {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.css.txw.sso.api.oauth2;
|
||||
|
||||
import com.css.txw.sso.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
|
||||
import com.css.txw.sso.api.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
|
||||
import com.css.txw.sso.api.oauth2.dto.OAuth2AccessTokenRespDTO;
|
||||
import com.css.txw.sso.constants.SsoApiConstants;
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
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.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
@FeignClient(name = SsoApiConstants.NAME,contextId = "token")
|
||||
@Tag(name = "RPC 服务 - OAuth2.0 令牌")
|
||||
public interface OAuth2TokenApi {
|
||||
|
||||
String PREFIX = SsoApiConstants.PREFIX + "/oauth2/token";
|
||||
|
||||
/**
|
||||
* 校验 Token 的 URL 地址,主要是提供给 Gateway 使用
|
||||
*/
|
||||
@SuppressWarnings("HttpUrlsUsage")
|
||||
String URL_CHECK = "http://" + SsoApiConstants.NAME + PREFIX + "/check";
|
||||
|
||||
@PostMapping(PREFIX + "/create")
|
||||
@Operation(summary = "创建访问令牌")
|
||||
CommonResult<OAuth2AccessTokenRespDTO> createAccessToken(@Valid @RequestBody OAuth2AccessTokenCreateReqDTO reqDTO);
|
||||
|
||||
@GetMapping(PREFIX + "/check")
|
||||
@Operation(summary = "校验访问令牌")
|
||||
@Parameter(name = "accessToken", description = "访问令牌", required = true, example = "tudou")
|
||||
CommonResult<OAuth2AccessTokenCheckRespDTO> checkAccessToken(@RequestParam("accessToken") String accessToken);
|
||||
|
||||
@DeleteMapping(PREFIX + "/remove")
|
||||
@Operation(summary = "移除访问令牌")
|
||||
@Parameter(name = "accessToken", description = "访问令牌", required = true, example = "tudou")
|
||||
CommonResult<OAuth2AccessTokenRespDTO> removeAccessToken(@RequestParam("accessToken") String accessToken);
|
||||
|
||||
@PutMapping(PREFIX + "/refresh")
|
||||
@Operation(summary = "刷新访问令牌")
|
||||
@Parameters({
|
||||
@Parameter(name = "refreshToken", description = "刷新令牌", required = true, example = "haha"),
|
||||
@Parameter(name = "clientId", description = "客户端编号", required = true, example = "yudaoyuanma")
|
||||
})
|
||||
CommonResult<OAuth2AccessTokenRespDTO> refreshAccessToken(@RequestParam("refreshToken") String refreshToken,
|
||||
@RequestParam("clientId") String clientId);
|
||||
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package com.css.txw.sso.api.oauth2.dto;
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "RPC 服务 - OAuth2 访问令牌的session信息")
|
||||
@Data
|
||||
public class AccessTokenSessionInfo implements Serializable {
|
||||
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*/
|
||||
@Schema(description = "用户UUID")
|
||||
private String yhUuid;
|
||||
@Schema(description = "真实姓名")
|
||||
private String zsxm;
|
||||
@Schema(description = "手机号码")
|
||||
private String sjhm;
|
||||
@Schema(description = "身份证件类型")
|
||||
private String sfzjlx;
|
||||
@Schema(description = "身份证件号码")
|
||||
private String sfzjhm;
|
||||
@Schema(description = "用户did")
|
||||
private String yhdid;
|
||||
/**
|
||||
* 机构信息
|
||||
*/
|
||||
@Schema(description = "机构UUID")
|
||||
private String qyuuid;
|
||||
@Schema(description = "机构名称")
|
||||
private String qymc;
|
||||
@Schema(description = "纳税人识别号")
|
||||
private String nsrsbh;
|
||||
@Schema(description = "社会信用代码")
|
||||
private String shxydm;
|
||||
@Schema(description = "登记序号")
|
||||
private String djxh;
|
||||
@Schema(description = "行政区划")
|
||||
private String xzqhszDm;
|
||||
@Schema(description = "用户类型")
|
||||
private String yhlx;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.css.txw.sso.api.oauth2.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "RPC 服务 - OAuth2 访问令牌的校验 Response DTO")
|
||||
@Data
|
||||
public class OAuth2AccessTokenCheckRespDTO implements Serializable {
|
||||
|
||||
@Schema(description = "是否刷新了访问令牌")
|
||||
private Boolean hasRefreshedToken;
|
||||
@Schema(description = "新的访问令牌")
|
||||
private String newAccessToken;
|
||||
@Schema(description = "新的过期时间")
|
||||
private LocalDateTime newExpireTime;
|
||||
|
||||
@Schema(description = "session信息")
|
||||
private AccessTokenSessionInfo sessionInfo;
|
||||
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.css.txw.sso.api.oauth2.dto;
|
||||
|
||||
import com.css.ggzc.framework.common.enums.UserTypeEnum;
|
||||
import com.css.ggzc.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "RPC 服务 - OAuth2 访问令牌创建 Request DTO")
|
||||
@Data
|
||||
public class OAuth2AccessTokenCreateReqDTO implements Serializable {
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private String userId;
|
||||
|
||||
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "用户类型不能为空")
|
||||
@InEnum(value = UserTypeEnum.class, message = "用户类型必须是 {value}")
|
||||
private Integer userType;
|
||||
|
||||
@Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma")
|
||||
@NotNull(message = "客户端编号不能为空")
|
||||
private String clientId;
|
||||
|
||||
@Schema(description = "授权范围的数组", example = "user_info")
|
||||
private List<String> scopes;
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.css.txw.sso.api.oauth2.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "RPC 服务 - OAuth2 访问令牌的信息 Response DTO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2AccessTokenRespDTO implements Serializable {
|
||||
|
||||
@Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou")
|
||||
private String accessToken;
|
||||
|
||||
@Schema(description = "刷新令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "haha")
|
||||
private String refreshToken;
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private String userId;
|
||||
|
||||
@Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime expiresTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.css.txw.sso.api.yhxx;
|
||||
|
||||
import com.css.txw.sso.constants.SsoApiConstants;
|
||||
import com.css.txw.sso.pojo.yhxx.SwitchCompanyResDTO;
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@FeignClient(name = SsoApiConstants.NAME,contextId = "switch")
|
||||
@Tag(name = "切换会话信息接口")
|
||||
public interface SwitchSessionApi {
|
||||
|
||||
String PREFIX = SsoApiConstants.PREFIX + "/switchSession";
|
||||
|
||||
|
||||
@PostMapping(PREFIX+"/company")
|
||||
@Operation(summary = "切换机构")
|
||||
CommonResult<SwitchCompanyResDTO> switchCompany(@RequestParam("token")String token, @RequestParam("jguuid")String jguuid);
|
||||
|
||||
@PostMapping(PREFIX+"/addCompany")
|
||||
@Operation(summary = "新增机构")
|
||||
CommonResult<String> addCompany(@RequestBody SwitchCompanyResDTO resDTO);
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.css.txw.sso.api.yhxx;
|
||||
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@FeignClient(name = "sso-service")
|
||||
@Tag(name = "用户信息接口")
|
||||
public interface YhxxApi {
|
||||
|
||||
@PostMapping("/sso/yhxx/getYhxx")
|
||||
@Operation(summary = "获取用户信息")
|
||||
CommonResult<String> getYhxx(@RequestParam("djxh") String djxh);
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.css.txw.sso.configuration;
|
||||
|
||||
import com.css.txw.sso.api.ISsoApi;
|
||||
import com.css.txw.sso.api.yhxx.SwitchSessionApi;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableFeignClients(clients = {
|
||||
ISsoApi.class,
|
||||
SwitchSessionApi.class
|
||||
})
|
||||
public class SsoApiConfiguration {
|
||||
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package com.css.txw.sso.constants;
|
||||
|
||||
public class SsoApiConstants {
|
||||
|
||||
private SsoApiConstants() {
|
||||
// 构造方法
|
||||
}
|
||||
|
||||
public static final String NAME = "txw-sso";
|
||||
|
||||
public static final String PREFIX = "/sso";
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.css.txw.sso.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 登录日志的类型枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum LoginLogTypeEnum {
|
||||
|
||||
LOGIN_USERNAME(100), // 使用账号登录
|
||||
LOGIN_SOCIAL(101), // 使用社交登录
|
||||
LOGIN_MOBILE(103), // 使用手机登陆
|
||||
LOGIN_SMS(104), // 使用短信登陆
|
||||
|
||||
LOGOUT_SELF(200), // 自己主动登出
|
||||
LOGOUT_DELETE(202), // 强制退出
|
||||
;
|
||||
|
||||
/**
|
||||
* 日志类型
|
||||
*/
|
||||
private final Integer type;
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.css.txw.sso.enums;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* OAuth2 授权类型(模式)的枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum OAuth2GrantTypeEnum {
|
||||
|
||||
PASSWORD("password"), // 密码模式
|
||||
AUTHORIZATION_CODE("authorization_code"), // 授权码模式
|
||||
IMPLICIT("implicit"), // 简化模式
|
||||
CLIENT_CREDENTIALS("client_credentials"), // 客户端模式
|
||||
REFRESH_TOKEN("refresh_token"), // 刷新模式
|
||||
;
|
||||
|
||||
private final String grantType;
|
||||
|
||||
public static OAuth2GrantTypeEnum getByGranType(String grantType) {
|
||||
return ArrayUtil.firstMatch(o -> o.getGrantType().equals(grantType), values());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package com.css.txw.sso.pojo.yhxx;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SwitchCompanyResDTO {
|
||||
|
||||
private String qyuuid;
|
||||
private String qymc;
|
||||
private String nsrsbh;
|
||||
private String yhuuid;
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
com.css.txw.sso.configuration.SsoApiConfiguration
|
||||
@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
com.css.txw.sso.configuration.SsoApiConfiguration
|
||||
@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
144
txw-sso/txw-sso-service-biz/pom.xml
Normal file
144
txw-sso/txw-sso-service-biz/pom.xml
Normal file
@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>txw-sso</artifactId>
|
||||
<groupId>com.css.txw</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>txw-sso-service-biz</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>sso service</description>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Cloud 基础 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-cache</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RPC 远程调用相关 -->
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-rpc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-trace</artifactId>
|
||||
</dependency>-->
|
||||
|
||||
<!-- Job 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-job</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Registry 注册中心相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Config 配置中心相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.css.txw</groupId>
|
||||
<artifactId>txw-sso-service-api</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.css.txw</groupId>
|
||||
<artifactId>txw-mhzc-service-api</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>dysmsapi20170525</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.css.txw</groupId>
|
||||
<artifactId>txw-common</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.dameng</groupId>
|
||||
<artifactId>DmJdbcDriver18</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.chainweaver</groupId>
|
||||
<artifactId>did-sdk-java</artifactId>
|
||||
<version>1.5.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
<version>2.0.60</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<!-- 设置构建的 jar 包名 -->
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<!-- 打包 -->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,20 @@
|
||||
package com.css.txw.sso.app;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
/**
|
||||
* 仅开发使用,正式环境不使用,写在此处的配置在生产环境不会生效
|
||||
*/
|
||||
@Slf4j
|
||||
@SpringBootApplication
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = true)
|
||||
public class DevAppStarter {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DevAppStarter.class, args);
|
||||
log.info("txw-sso 0.0.2");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.css.txw.sso.configuration;
|
||||
|
||||
|
||||
import com.aliyun.dysmsapi20170525.Client;
|
||||
import com.aliyun.teaopenapi.models.Config;
|
||||
import com.css.ggzc.framework.cache.utils.CacheUtils;
|
||||
|
||||
import static com.css.txw.sso.constants.SsoConstants.*;
|
||||
|
||||
public class SMSClient {
|
||||
public static Client createClient() throws Exception {
|
||||
Config config = new Config()
|
||||
.setAccessKeyId(CacheUtils.dm2mc("xt_xtcs",MHZC_SMS_KEY))
|
||||
.setAccessKeySecret(CacheUtils.dm2mc("xt_xtcs",MHZC_SMS_SECRET));
|
||||
// 配置 Endpoint
|
||||
config.endpoint = MHZC_SMS_ENDPOINT;
|
||||
return new Client(config);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package com.css.txw.sso.configuration;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@AutoConfiguration
|
||||
@ComponentScan("com.css.txw.sso")
|
||||
@MapperScan("com.css.txw.sso.mapper")
|
||||
public class SsoServiceConfiguration {
|
||||
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package com.css.txw.sso.constants;
|
||||
|
||||
|
||||
import com.css.ggzc.framework.common.exception.ErrorCode;
|
||||
|
||||
/**
|
||||
* System 错误码枚举类
|
||||
*
|
||||
* system 系统,使用 1-002-000-000 段
|
||||
*/
|
||||
public interface ErrorCodeConstants {
|
||||
|
||||
// ========== AUTH 模块 1-002-000-000 ==========
|
||||
ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004001, "登录失败,账号密码不正确");
|
||||
ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1004002, "登录失败,账号被禁用");
|
||||
ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1004003, "请重新滑动验证");
|
||||
|
||||
ErrorCode AUTH_LOGIN_PASSWORD_ERROR_LOCK = new ErrorCode(1004004, "密码输入错误次数过多,账户锁定,请稍后再试");
|
||||
|
||||
ErrorCode AUTH_LOGIN_ACCOUNT_LOCK = new ErrorCode(1004005, "密码输入错误次数过多,账户锁定,请联系管理员解锁");
|
||||
|
||||
|
||||
// ========== OAuth2 客户端 1-002-020-000 =========
|
||||
ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1004006, "OAuth2 客户端不存在");
|
||||
ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1004007, "OAuth2 客户端编号已存在");
|
||||
ErrorCode OAUTH2_CLIENT_DISABLE = new ErrorCode(1004008, "OAuth2 客户端已禁用");
|
||||
ErrorCode OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH = new ErrorCode(1004009, "无效 redirect_uri: {}");
|
||||
ErrorCode OAUTH2_CLIENT_CLIENT_SECRET_ERROR = new ErrorCode(1004010, "无效 client_secret: {}");
|
||||
|
||||
// ========== OAuth2 授权 1-002-021-000 =========
|
||||
ErrorCode OAUTH2_GRANT_CLIENT_ID_MISMATCH = new ErrorCode(1004011, "client_id 不匹配");
|
||||
ErrorCode OAUTH2_GRANT_REDIRECT_URI_MISMATCH = new ErrorCode(1004012, "redirect_uri 不匹配");
|
||||
ErrorCode OAUTH2_GRANT_STATE_MISMATCH = new ErrorCode(1004013, "state 不匹配");
|
||||
ErrorCode OAUTH2_GRANT_CODE_NOT_EXISTS = new ErrorCode(1004014, "code 不存在");
|
||||
|
||||
// ========== OAuth2 授权 1-002-022-000 =========
|
||||
ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1004015, "code 不存在");
|
||||
ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1004016, "code 已过期");
|
||||
ErrorCode OAUTH2_SJHM_NOT_EXISTS = new ErrorCode(1004017, "手机号码不存在");
|
||||
ErrorCode OAUTH2_LOGIN_SJHM_NOT_EXISTS = new ErrorCode(1004018, "登录失败,验证码无效");
|
||||
ErrorCode OAUTH2_SJHM_LOCK = new ErrorCode(1004019, "距离上次发送验证码不超过1分钟");
|
||||
ErrorCode OAUTH2_LOGIN_SMS_NOT_EXISTS = new ErrorCode(1004020, "验证码无效或已过期");
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,101 @@
|
||||
package com.css.txw.sso.constants;
|
||||
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2AccessTokenDO;
|
||||
|
||||
/**
|
||||
* System Redis Key 枚举类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface RedisKeyConstants {
|
||||
|
||||
/**
|
||||
* 指定部门的所有子部门编号数组的缓存
|
||||
* <p>
|
||||
* KEY 格式:dept_children_ids:{id}
|
||||
* VALUE 数据类型:String 子部门编号集合
|
||||
*/
|
||||
String DEPT_CHILDREN_ID_LIST = "dept_children_ids";
|
||||
|
||||
/**
|
||||
* 角色的缓存
|
||||
* <p>
|
||||
* KEY 格式:role:{id}
|
||||
* VALUE 数据类型:String 角色信息
|
||||
*/
|
||||
String ROLE = "role";
|
||||
|
||||
/**
|
||||
* 用户拥有的角色编号的缓存
|
||||
* <p>
|
||||
* KEY 格式:user_role_ids:{userId}
|
||||
* VALUE 数据类型:String 角色编号集合
|
||||
*/
|
||||
String USER_ROLE_ID_LIST = "user_role_ids";
|
||||
|
||||
/**
|
||||
* 拥有指定菜单的角色编号的缓存
|
||||
* <p>
|
||||
* KEY 格式:user_role_ids:{menuId}
|
||||
* VALUE 数据类型:String 角色编号集合
|
||||
*/
|
||||
String MENU_ROLE_ID_LIST = "menu_role_ids";
|
||||
|
||||
/**
|
||||
* 拥有权限对应的菜单编号数组的缓存
|
||||
* <p>
|
||||
* KEY 格式:permission_menu_ids:{permission}
|
||||
* VALUE 数据类型:String 菜单编号数组
|
||||
*/
|
||||
String PERMISSION_MENU_ID_LIST = "permission_menu_ids";
|
||||
|
||||
/**
|
||||
* OAuth2 客户端的缓存
|
||||
* <p>
|
||||
* KEY 格式:oauth_client:{id}
|
||||
* VALUE 数据类型:String 客户端信息
|
||||
*/
|
||||
String OAUTH_CLIENT = "oauth_client";
|
||||
|
||||
/**
|
||||
* 访问令牌的缓存
|
||||
* <p>
|
||||
* KEY 格式:oauth2_access_token:{token}
|
||||
* VALUE 数据类型:String 访问令牌信息 {@link OAuth2AccessTokenDO}
|
||||
* <p>
|
||||
* 由于动态过期时间,使用 RedisTemplate 操作
|
||||
*/
|
||||
String OAUTH2_ACCESS_TOKEN = "oauth2_access_token:%s";
|
||||
|
||||
/**
|
||||
* 站内信模版的缓存
|
||||
* <p>
|
||||
* KEY 格式:notify_template:{code}
|
||||
* VALUE 数据格式:String 模版信息
|
||||
*/
|
||||
String NOTIFY_TEMPLATE = "notify_template";
|
||||
|
||||
/**
|
||||
* 邮件账号的缓存
|
||||
* <p>
|
||||
* KEY 格式:mail_account:{id}
|
||||
* VALUE 数据格式:String 账号信息
|
||||
*/
|
||||
String MAIL_ACCOUNT = "mail_account";
|
||||
|
||||
/**
|
||||
* 邮件模版的缓存
|
||||
* <p>
|
||||
* KEY 格式:mail_template:{code}
|
||||
* VALUE 数据格式:String 模版信息
|
||||
*/
|
||||
String MAIL_TEMPLATE = "mail_template";
|
||||
|
||||
/**
|
||||
* 短信模版的缓存
|
||||
* <p>
|
||||
* KEY 格式:sms_template:{id}
|
||||
* VALUE 数据格式:String 模版信息
|
||||
*/
|
||||
String SMS_TEMPLATE = "sms_template";
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.css.txw.sso.constants;
|
||||
|
||||
public class SsoConstants {
|
||||
|
||||
public static final String COOKIE_TOKEN_KEY = "ACCESS_TOKEN";
|
||||
|
||||
public static final String ADMIN_COOKIE_TOKEN_KEY = "ACCESS_TOKEN_ADMIN";
|
||||
|
||||
public static final String COOKIE_PATH = "/";
|
||||
|
||||
public static final String CLIENT_DEFAULT = "default";
|
||||
|
||||
public static final String SMS_CLIENT_SIGNNAME = "智贸链";
|
||||
|
||||
public static final String SMS_TEMPLATE_CODE = "SMS_474450289";
|
||||
|
||||
public static final String MHZC_SMS_SECRET = "MHZC-SMS-SECRET";
|
||||
|
||||
public static final String MHZC_SMS_KEY = "MHZC-SMS-KEY";
|
||||
|
||||
public static final String MHZC_SMS_ENDPOINT = "dysmsapi.aliyuncs.com";
|
||||
|
||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
# kafaka消费服务
|
||||
@ -0,0 +1,67 @@
|
||||
package com.css.txw.sso.controller.auth;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
import com.css.ggzc.framework.common.util.servlet.ServletUtils;
|
||||
import com.css.txw.sso.constants.SsoApiConstants;
|
||||
import com.css.txw.sso.constants.SsoConstants;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginReqVO;
|
||||
import com.css.txw.sso.service.auth.AdminAuthService;
|
||||
import com.css.txw.sso.util.SecurityFrameworkUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static com.css.ggzc.framework.common.pojo.CommonResult.success;
|
||||
|
||||
|
||||
@Tag(name = "后台登录")
|
||||
@RestController
|
||||
@RequestMapping("/admin/auth")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class AdminAuthController {
|
||||
|
||||
@Resource
|
||||
private AdminAuthService adminAuthService;
|
||||
|
||||
@PostMapping("/login")
|
||||
@Operation(summary = "后台登录-账号密码登录")
|
||||
public CommonResult<Boolean> login(@RequestBody @Valid AuthLoginReqVO reqVO){
|
||||
final String token = adminAuthService.login(reqVO);
|
||||
final HttpServletResponse response = ServletUtils.getResponse();
|
||||
final Cookie cookie = new Cookie(SsoConstants.ADMIN_COOKIE_TOKEN_KEY,token);
|
||||
cookie.setPath(SsoConstants.COOKIE_PATH);
|
||||
cookie.setHttpOnly(true);
|
||||
response.addCookie(cookie);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PostMapping("/logout")
|
||||
@Operation(summary = "后台登录-退出登录")
|
||||
public CommonResult<Boolean> logout(HttpServletRequest request){
|
||||
String token = SecurityFrameworkUtils.obtainAuthorization(SsoConstants.ADMIN_COOKIE_TOKEN_KEY,request);
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
adminAuthService.logout(token);
|
||||
final HttpServletResponse response = ServletUtils.getResponse();
|
||||
final Cookie cookie = new Cookie(SsoConstants.ADMIN_COOKIE_TOKEN_KEY,token);
|
||||
cookie.setPath(SsoConstants.COOKIE_PATH);
|
||||
cookie.setHttpOnly(true);
|
||||
cookie.setMaxAge(0);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,147 @@
|
||||
package com.css.txw.sso.controller.auth;
|
||||
|
||||
|
||||
import static com.css.ggzc.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.css.ggzc.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
import com.css.ggzc.framework.common.util.gy.GyUtils;
|
||||
import com.css.ggzc.framework.common.util.servlet.ServletUtils;
|
||||
import com.css.txw.sso.constants.SsoConstants;
|
||||
import com.css.txw.sso.enums.LoginLogTypeEnum;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginRespVO;
|
||||
import com.css.txw.sso.pojo.vo.DidBindPhoneReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SMSLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SendMsgReqVO;
|
||||
import com.css.txw.sso.pojo.vo.oauth2.LogoutVO;
|
||||
import com.css.txw.sso.pojo.vo.thirdparty.did.QrCodeInfo;
|
||||
import com.css.txw.sso.service.auth.AuthService;
|
||||
import com.css.txw.sso.util.SecurityFrameworkUtils;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
@Tag(name = "管理后台 - 认证")
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class AuthController {
|
||||
|
||||
@Resource
|
||||
private AuthService authService;
|
||||
|
||||
|
||||
@PostMapping("/login")
|
||||
@PermitAll
|
||||
@Operation(summary = "使用账号密码登录")
|
||||
public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
|
||||
final HttpServletResponse response = ServletUtils.getResponse();
|
||||
final AuthLoginRespVO login = authService.login(reqVO);
|
||||
|
||||
final Cookie cookie = new Cookie(SsoConstants.COOKIE_TOKEN_KEY,login.getAccessToken());
|
||||
cookie.setPath(SsoConstants.COOKIE_PATH);
|
||||
cookie.setHttpOnly(true);
|
||||
//cookie.setMaxAge(-1);
|
||||
response.addCookie(cookie);
|
||||
return success(login);
|
||||
}
|
||||
|
||||
@PostMapping("/logout")
|
||||
@PermitAll
|
||||
@Operation(summary = "登出系统")
|
||||
public CommonResult<List<LogoutVO>> logout(HttpServletRequest request) {
|
||||
List<LogoutVO> logout = new ArrayList<>();
|
||||
String token = SecurityFrameworkUtils.obtainAuthorization(SsoConstants.COOKIE_TOKEN_KEY,request);
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
logout = authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
|
||||
final HttpServletResponse response = ServletUtils.getResponse();
|
||||
final Cookie cookie = new Cookie(SsoConstants.COOKIE_TOKEN_KEY,token);
|
||||
cookie.setPath(SsoConstants.COOKIE_PATH);
|
||||
cookie.setHttpOnly(true);
|
||||
cookie.setMaxAge(0);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
log.info("ssologout返回结果:{}",logout);
|
||||
return success(logout);
|
||||
}
|
||||
|
||||
@PostMapping("/refresh-token")
|
||||
@PermitAll
|
||||
@Operation(summary = "刷新令牌")
|
||||
@Parameter(name = "refreshToken", description = "刷新令牌", required = true)
|
||||
public CommonResult<AuthLoginRespVO> refreshToken(@RequestParam("refreshToken") String refreshToken) {
|
||||
return success(authService.refreshToken(refreshToken));
|
||||
}
|
||||
|
||||
@PostMapping("/sendMsg")
|
||||
@PermitAll
|
||||
@Operation(summary = "发送手机验证码")
|
||||
public CommonResult<Integer> sendMsg(@RequestBody @Valid SendMsgReqVO reqVO) throws Exception{
|
||||
return success(authService.sendMsg(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/loginBySMS")
|
||||
@PermitAll
|
||||
@Operation(summary = "发送手机验证码")
|
||||
public CommonResult<AuthLoginRespVO> loginBySMS(@RequestBody @Valid SMSLoginReqVO reqVO) {
|
||||
final HttpServletResponse response = ServletUtils.getResponse();
|
||||
final AuthLoginRespVO login = authService.loginBySMS(reqVO);
|
||||
final Cookie cookie = new Cookie(SsoConstants.COOKIE_TOKEN_KEY,login.getAccessToken());
|
||||
cookie.setPath(SsoConstants.COOKIE_PATH);
|
||||
cookie.setHttpOnly(true);
|
||||
//cookie.setMaxAge(-1);
|
||||
response.addCookie(cookie);
|
||||
return success(login);
|
||||
}
|
||||
|
||||
@PostMapping("/didBindPhone")
|
||||
@PermitAll
|
||||
@Operation(summary = "绑定手机号")
|
||||
public CommonResult<AuthLoginRespVO> didBindPhone(@RequestBody @Valid DidBindPhoneReqVO reqVO) {
|
||||
if (GyUtils.isNull(reqVO)) {
|
||||
CommonResult<AuthLoginRespVO> result = CommonResult.success(null);
|
||||
String msg = "入参为空!";
|
||||
result.setMsg(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
return result;
|
||||
}
|
||||
if (GyUtils.isNull(reqVO.getReqId())) {
|
||||
CommonResult<AuthLoginRespVO> result = CommonResult.success(null);
|
||||
String msg = "入参reqId为空!";
|
||||
result.setMsg(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
return result;
|
||||
}
|
||||
final HttpServletResponse response = ServletUtils.getResponse();
|
||||
final AuthLoginRespVO login = authService.didBindPhone(reqVO);
|
||||
final Cookie cookie = new Cookie(SsoConstants.COOKIE_TOKEN_KEY,login.getAccessToken());
|
||||
cookie.setPath(SsoConstants.COOKIE_PATH);
|
||||
cookie.setHttpOnly(true);
|
||||
//cookie.setMaxAge(-1);
|
||||
response.addCookie(cookie);
|
||||
return success(login);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,216 @@
|
||||
package com.css.txw.sso.controller.oauth2;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
import com.css.ggzc.framework.common.util.gy.GyUtils;
|
||||
import com.css.txw.sso.constants.SsoApiConstants;
|
||||
import com.css.txw.sso.constants.SsoConstants;
|
||||
import com.css.txw.sso.convert.OAuth2OpenConvert;
|
||||
import com.css.txw.sso.enums.OAuth2GrantTypeEnum;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2AccessTokenDO;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2ClientDO;
|
||||
import com.css.txw.sso.pojo.dto.session.SessionInfo;
|
||||
import com.css.txw.sso.pojo.vo.oauth2.OAuth2OpenAccessTokenRespVO;
|
||||
import com.css.txw.sso.pojo.vo.oauth2.OAuth2OpenCheckTokenRespVO;
|
||||
import com.css.txw.sso.service.oauth2.OAuth2ClientService;
|
||||
import com.css.txw.sso.service.oauth2.OAuth2GrantService;
|
||||
import com.css.txw.sso.service.oauth2.OAuth2TokenService;
|
||||
import com.css.txw.sso.util.HttpUtils;
|
||||
import com.css.txw.sso.util.OAuth2Utils;
|
||||
import com.css.txw.sso.util.SecurityFrameworkUtils;
|
||||
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.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import static com.css.ggzc.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static com.css.ggzc.framework.common.exception.util.ServiceExceptionUtil.exception0;
|
||||
import static com.css.ggzc.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "基础OAuth2授权")
|
||||
@RestController
|
||||
@RequestMapping("/oauth2")
|
||||
@Slf4j
|
||||
public class OAuth2BasicController {
|
||||
|
||||
@Resource
|
||||
private OAuth2GrantService oauth2GrantService;
|
||||
@Resource
|
||||
private OAuth2ClientService oauth2ClientService;
|
||||
|
||||
@Resource
|
||||
private OAuth2TokenService oauth2TokenService;
|
||||
|
||||
|
||||
@PostMapping("/authorize")
|
||||
@Operation(summary = "申请授权", description = "OAuth2授权码模式第一步-获取授权码")
|
||||
@Parameters({
|
||||
@Parameter(name = "response_type", required = true, description = "响应类型", example = "code"),
|
||||
@Parameter(name = "client_id", required = true, description = "客户端编号", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
@Parameter(name = "redirect_uri", required = true, description = "重定向 URI", example = "http://127.0.0.1"),
|
||||
@Parameter(name = "state", example = "1")
|
||||
})
|
||||
public CommonResult<String> authorize(HttpServletRequest request,
|
||||
@RequestParam("Response_type") String responseType,
|
||||
@RequestParam("Client_id") String clientId,
|
||||
@RequestParam("Redirect_uri") String redirectUri,
|
||||
@RequestParam(value = "State", required = false) String state) {
|
||||
// 校验 responseType 是否满足 code 或者 token 值
|
||||
OAuth2GrantTypeEnum grantTypeEnum = getGrantTypeEnum(responseType);
|
||||
//校验 redirectUri 重定向域名是否合法
|
||||
log.info("authorize开始验证redirectUri:{}",redirectUri);
|
||||
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientId, null,
|
||||
grantTypeEnum.getGrantType(), null, redirectUri);
|
||||
String currentToken = SecurityFrameworkUtils.obtainAuthorization(SsoConstants.COOKIE_TOKEN_KEY,request);
|
||||
return success(getAuthorizationCodeRedirect(client, redirectUri, state,currentToken));
|
||||
}
|
||||
|
||||
@PostMapping("/token")
|
||||
@PermitAll
|
||||
@Operation(summary = "获得访问令牌", description = "OAuth2授权码模式第二步-获取访问令牌")
|
||||
@Parameters({
|
||||
@Parameter(name = "grant_type", required = true, description = "授权类型", example = "authorization_code"),
|
||||
@Parameter(name = "code", description = "授权码", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
@Parameter(name = "redirect_uri", description = "重定向 URI", example = "http://127.0.0.1"),
|
||||
@Parameter(name = "client_id", description = "客户端ID", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
@Parameter(name = "client_secret", description = "客户端密钥", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
@Parameter(name = "refresh_token", example = "2f54a1f113d84130a867f559b7279365")
|
||||
})
|
||||
public CommonResult<OAuth2OpenAccessTokenRespVO> postAccessToken(@RequestParam("grant_type") String grantType,
|
||||
@RequestParam(value = "code", required = false) String code,
|
||||
@RequestParam(value = "redirect_uri", required = false) String redirectUri,
|
||||
@RequestParam(value = "client_id") String clientId,
|
||||
@RequestParam(value = "client_secret") String clientSecret,
|
||||
@RequestParam(value = "refresh_token", required = false) String refreshToken) {
|
||||
log.info("postAccessToken方法开启,grant_type为"+grantType+"code="+code+"redirect_uri="+redirectUri+"client_id="+clientId+"client_secret="+clientSecret+"refresh_token="+refreshToken);
|
||||
//校验授权类型
|
||||
OAuth2GrantTypeEnum grantTypeEnum = OAuth2GrantTypeEnum.getByGranType(grantType);
|
||||
log.info("授权类型"+ grantTypeEnum);
|
||||
if (grantTypeEnum == null) {
|
||||
throw exception0(BAD_REQUEST.getCode(), StrUtil.format("未知授权类型({})", grantType));
|
||||
}
|
||||
if (grantTypeEnum == OAuth2GrantTypeEnum.IMPLICIT) {
|
||||
throw exception0(BAD_REQUEST.getCode(), "Token 接口不支持 implicit 授权模式");
|
||||
}
|
||||
log.info("开始校验客户端");
|
||||
//校验客户端
|
||||
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientId, clientSecret, grantType, null, redirectUri);
|
||||
log.info("client返回值为"+client);
|
||||
// 2. 根据授权模式,获取访问令牌
|
||||
OAuth2AccessTokenDO accessTokenDO;
|
||||
switch (grantTypeEnum) {
|
||||
case AUTHORIZATION_CODE:
|
||||
accessTokenDO = oauth2GrantService.grantAuthorizationCodeForAccessToken(client, code, redirectUri);
|
||||
log.info("授权类型为AUTHORIZATION_CODE,accessTokenDO返回值为"+accessTokenDO);
|
||||
break;
|
||||
case REFRESH_TOKEN:
|
||||
accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, client.getClientid());
|
||||
log.info("授权类型为REFRESH_TOKEN,accessTokenDO返回值为"+accessTokenDO);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("未知授权类型:" + grantType);
|
||||
}
|
||||
return success(OAuth2OpenConvert.INSTANCE.convert(accessTokenDO));
|
||||
}
|
||||
|
||||
@PostMapping("/check-token")
|
||||
@PermitAll
|
||||
@Operation(summary = "校验访问令牌")
|
||||
@Parameters({
|
||||
@Parameter(name = "token", required = true, description = "访问令牌", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
@Parameter(name = "client_id", description = "客户端ID", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
@Parameter(name = "client_secret", description = "客户端密钥", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
})
|
||||
public CommonResult<OAuth2OpenCheckTokenRespVO> checkToken(@RequestParam("token") String token,
|
||||
@RequestParam(value = "client_id") String clientId,
|
||||
@RequestParam(value = "client_secret") String clientSecret) {
|
||||
// 校验客户端
|
||||
oauth2ClientService.validOAuthClientFromCache(clientId,clientSecret, null, null, null);
|
||||
|
||||
// 校验令牌
|
||||
final SessionInfo sessionInfo = oauth2TokenService.checkAccessToken(token);
|
||||
Assert.notNull(sessionInfo, "访问令牌不能为空"); // 防御性检查
|
||||
return success(OAuth2OpenConvert.INSTANCE.convert2(sessionInfo.getTokenInfo()));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/remove-token")
|
||||
@PermitAll
|
||||
@Operation(summary = "删除访问令牌")
|
||||
@Parameters({
|
||||
@Parameter(name = "access_token", required = false, description = "访问令牌", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
@Parameter(name = "client_id", description = "客户端ID", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
@Parameter(name = "client_secret", description = "客户端密钥", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
})
|
||||
public CommonResult<Boolean> revokeToken(HttpServletRequest request,
|
||||
@RequestParam(value = "access_token", required = false) String token,
|
||||
@RequestParam(value = "client_id") String clientId,
|
||||
@RequestParam(value = "client_secret") String clientSecret) {
|
||||
if (GyUtils.isNull(token)){
|
||||
token = SecurityFrameworkUtils.obtainAuthorization(SsoConstants.COOKIE_TOKEN_KEY,request);
|
||||
}
|
||||
// 校验客户端
|
||||
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientId, clientSecret, null, null, null);
|
||||
// 删除访问令牌
|
||||
return success(oauth2GrantService.revokeToken(client.getClientid(), token));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@PostMapping("/refresh-token")
|
||||
@PermitAll
|
||||
@Operation(summary = "刷新访问令牌", description = "根据刷新令牌获取新的访问令牌")
|
||||
@Parameters({
|
||||
@Parameter(name = "redirect_uri", description = "重定向 URI", example = "http://127.0.0.1"),
|
||||
@Parameter(name = "client_id", description = "客户端ID", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
@Parameter(name = "client_secret", description = "客户端密钥", example = "2f54a1f113d84130a867f559b7279365"),
|
||||
@Parameter(name = "refresh_token", description = "刷新令牌", example = "2f54a1f113d84130a867f559b7279365")
|
||||
})
|
||||
public CommonResult<OAuth2OpenAccessTokenRespVO> refreshAccessToken(@RequestParam(value = "redirect_uri") String redirectUri,
|
||||
@RequestParam(value = "client_id") String clientId,
|
||||
@RequestParam(value = "client_secret") String clientSecret,
|
||||
@RequestParam(value = "refresh_token") String refreshToken){
|
||||
|
||||
//校验客户端
|
||||
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientId, clientSecret, null, null, redirectUri);
|
||||
//获取访问令牌
|
||||
final OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, client.getClientid());
|
||||
return success(OAuth2OpenConvert.INSTANCE.convert(accessTokenDO));
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
private static OAuth2GrantTypeEnum getGrantTypeEnum(String responseType) {
|
||||
if (StrUtil.equals(responseType, "code")) {
|
||||
return OAuth2GrantTypeEnum.AUTHORIZATION_CODE;
|
||||
}
|
||||
if (StrUtil.equalsAny(responseType, "token")) {
|
||||
return OAuth2GrantTypeEnum.IMPLICIT;
|
||||
}
|
||||
throw exception0(BAD_REQUEST.getCode(), "response_type 参数值只允许 code 和 token");
|
||||
}
|
||||
|
||||
private String getAuthorizationCodeRedirect(OAuth2ClientDO client,String redirectUri, String state,String currentToken) {
|
||||
// 1. 创建 code 授权码
|
||||
String authorizationCode = oauth2GrantService.grantAuthorizationCodeForCode(client.getClientid(), redirectUri, state,currentToken);
|
||||
// 2. 拼接重定向的 URL
|
||||
return OAuth2Utils.buildAuthorizationCodeRedirectUri(redirectUri, authorizationCode, state);
|
||||
}
|
||||
|
||||
private String[] obtainBasicAuthorization(HttpServletRequest request) {
|
||||
return HttpUtils.obtainBasicAuthorization(request);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,214 @@
|
||||
package com.css.txw.sso.controller.oauth2;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.css.txw.sso.convert.OAuth2OpenConvert;
|
||||
import com.css.txw.sso.enums.OAuth2GrantTypeEnum;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2AccessTokenDO;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2ClientDO;
|
||||
import com.css.txw.sso.pojo.dto.session.SessionInfo;
|
||||
import com.css.txw.sso.pojo.vo.oauth2.OAuth2OpenAccessTokenRespVO;
|
||||
import com.css.txw.sso.pojo.vo.oauth2.OAuth2OpenCheckTokenRespVO;
|
||||
import com.css.txw.sso.service.oauth2.OAuth2ClientService;
|
||||
import com.css.txw.sso.service.oauth2.OAuth2GrantService;
|
||||
import com.css.txw.sso.service.oauth2.OAuth2TokenService;
|
||||
import com.css.txw.sso.util.HttpUtils;
|
||||
import com.css.txw.sso.util.OAuth2Utils;
|
||||
import com.css.ggzc.framework.common.enums.UserTypeEnum;
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
import com.css.ggzc.framework.common.util.json.JsonUtils;
|
||||
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.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.css.ggzc.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
|
||||
import static com.css.ggzc.framework.common.exception.util.ServiceExceptionUtil.exception0;
|
||||
import static com.css.ggzc.framework.common.pojo.CommonResult.success;
|
||||
import static com.css.ggzc.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static com.css.ggzc.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
|
||||
|
||||
|
||||
/**
|
||||
* 提供给外部应用调用为主
|
||||
*/
|
||||
@Tag(name = "管理后台 - OAuth2.0 授权")
|
||||
@RestController
|
||||
@RequestMapping("/open/oauth2")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class OAuth2OpenController {
|
||||
|
||||
@Resource
|
||||
private OAuth2GrantService oauth2GrantService;
|
||||
@Resource
|
||||
private OAuth2ClientService oauth2ClientService;
|
||||
|
||||
@Resource
|
||||
private OAuth2TokenService oauth2TokenService;
|
||||
|
||||
/**
|
||||
* 对应 Spring Security OAuth 的 TokenEndpoint 类的 postAccessToken 方法
|
||||
*
|
||||
* 授权码 authorization_code 模式时:code + redirectUri + state 参数
|
||||
* 密码 password 模式时:username + password + scope 参数
|
||||
* 刷新 refresh_token 模式时:refreshToken 参数
|
||||
* 客户端 client_credentials 模式:scope 参数
|
||||
* 简化 implicit 模式时:不支持
|
||||
*
|
||||
* 注意,默认需要传递 client_id + client_secret 参数
|
||||
*/
|
||||
@PostMapping("/token")
|
||||
@PermitAll
|
||||
@Operation(summary = "获得访问令牌", description = "code 授权码模式")
|
||||
@Parameters({
|
||||
@Parameter(name = "grant_type", required = true, description = "授权类型", example = "code"),
|
||||
@Parameter(name = "code", description = "授权范围", example = "userinfo.read"),
|
||||
@Parameter(name = "redirect_uri", description = "重定向 URI", example = "https://www.iocoder.cn"),
|
||||
@Parameter(name = "state", description = "状态", example = "1"),
|
||||
@Parameter(name = "username", example = "tudou"),
|
||||
@Parameter(name = "password", example = "cai"), // 多个使用空格分隔
|
||||
@Parameter(name = "scope", example = "user_info"),
|
||||
@Parameter(name = "refresh_token", example = "123424233"),
|
||||
})
|
||||
public CommonResult<OAuth2OpenAccessTokenRespVO> postAccessToken(HttpServletRequest request,
|
||||
@RequestParam("grant_type") String grantType,
|
||||
@RequestParam(value = "code", required = false) String code, // 授权码模式
|
||||
@RequestParam(value = "redirect_uri", required = false) String redirectUri, // 授权码模式
|
||||
@RequestParam(value = "state", required = false) String state, // 授权码模式
|
||||
@RequestParam(value = "username", required = false) String username, // 密码模式
|
||||
@RequestParam(value = "password", required = false) String password, // 密码模式
|
||||
@RequestParam(value = "scope", required = false) String scope, // 密码模式
|
||||
@RequestParam(value = "refresh_token", required = false) String refreshToken) { // 刷新模式
|
||||
List<String> scopes = OAuth2Utils.buildScopes(scope);
|
||||
// 1.1 校验授权类型
|
||||
OAuth2GrantTypeEnum grantTypeEnum = OAuth2GrantTypeEnum.getByGranType(grantType);
|
||||
if (grantTypeEnum == null) {
|
||||
throw exception0(BAD_REQUEST.getCode(), StrUtil.format("未知授权类型({})", grantType));
|
||||
}
|
||||
|
||||
// 1.2 校验客户端
|
||||
String[] clientIdAndSecret = obtainBasicAuthorization(request);
|
||||
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1],
|
||||
grantType, scopes, redirectUri);
|
||||
|
||||
// 2. 根据授权模式,获取访问令牌
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2GrantService.grantAuthorizationCodeForAccessToken(client.getClientid(), code, redirectUri, state);
|
||||
Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查
|
||||
return success(OAuth2OpenConvert.INSTANCE.convert(accessTokenDO));
|
||||
}
|
||||
|
||||
@DeleteMapping("/token")
|
||||
@PermitAll
|
||||
@Operation(summary = "删除访问令牌")
|
||||
@Parameter(name = "token", required = true, description = "访问令牌", example = "biu")
|
||||
public CommonResult<Boolean> revokeToken(HttpServletRequest request,
|
||||
@RequestParam("token") String token) {
|
||||
// 校验客户端
|
||||
String[] clientIdAndSecret = obtainBasicAuthorization(request);
|
||||
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1],
|
||||
null, null, null);
|
||||
|
||||
// 删除访问令牌
|
||||
return success(oauth2GrantService.revokeToken(client.getClientid(), token));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对应 Spring Security OAuth 的 CheckTokenEndpoint 类的 checkToken 方法
|
||||
*/
|
||||
@PostMapping("/check-token")
|
||||
@PermitAll
|
||||
@Operation(summary = "校验访问令牌")
|
||||
@Parameter(name = "token", required = true, description = "访问令牌", example = "biu")
|
||||
public CommonResult<OAuth2OpenCheckTokenRespVO> checkToken(HttpServletRequest request,
|
||||
@RequestParam("token") String token) {
|
||||
// 校验客户端
|
||||
String[] clientIdAndSecret = obtainBasicAuthorization(request);
|
||||
oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1],
|
||||
null, null, null);
|
||||
|
||||
// 校验令牌
|
||||
final SessionInfo sessionInfo = oauth2TokenService.checkAccessToken(token);
|
||||
Assert.notNull(sessionInfo, "访问令牌不能为空"); // 防御性检查
|
||||
return success(OAuth2OpenConvert.INSTANCE.convert2(sessionInfo.getTokenInfo()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 对应 Spring Security OAuth 的 AuthorizationEndpoint 类的 approveOrDeny 方法
|
||||
* 因为前后端分离,Axios 无法很好的处理 302 重定向,所以和 Spring Security OAuth 略有不同,返回结果是重定向的 URL,剩余交给前端处理
|
||||
*/
|
||||
@PostMapping("/authorize")
|
||||
@Operation(summary = "申请授权", description = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【提交】调用")
|
||||
@Parameters({
|
||||
@Parameter(name = "response_type", required = true, description = "响应类型", example = "code"),
|
||||
@Parameter(name = "client_id", required = true, description = "客户端编号", example = "tudou"),
|
||||
@Parameter(name = "scope", description = "授权范围", example = "userinfo.read"), // 使用 Map<String, Boolean> 格式,Spring MVC 暂时不支持这么接收参数
|
||||
@Parameter(name = "redirect_uri", required = true, description = "重定向 URI", example = "https://www.iocoder.cn"),
|
||||
@Parameter(name = "auto_approve", required = true, description = "用户是否接受", example = "true"),
|
||||
@Parameter(name = "state", example = "1")
|
||||
})
|
||||
public CommonResult<String> approveOrDeny(@RequestParam("Response_type") String responseType,
|
||||
@RequestParam("Client_id") String clientId,
|
||||
@RequestParam(value = "Scope", required = false) String scope,
|
||||
@RequestParam("Redirect_uri") String redirectUri,
|
||||
@RequestParam(value = "Auto_approve") Boolean autoApprove,
|
||||
@RequestParam(value = "State", required = false) String state) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Boolean> scopes = JsonUtils.toBean(scope, Map.class);
|
||||
scopes = ObjectUtil.defaultIfNull(scopes, new HashMap<String,Boolean>());
|
||||
// 校验 responseType 是否满足 code 或者 token 值
|
||||
OAuth2GrantTypeEnum grantTypeEnum = getGrantTypeEnum(responseType);
|
||||
//校验 redirectUri 重定向域名是否合法 + 校验 scope 是否在 Client 授权范围内
|
||||
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientId, null,
|
||||
grantTypeEnum.getGrantType(), scopes.keySet(), redirectUri);
|
||||
|
||||
// code 授权码模式,则发放 code 授权码,并重定向
|
||||
List<String> approveScopes = convertList(scopes.entrySet(), Map.Entry::getKey, Map.Entry::getValue);
|
||||
return success(getAuthorizationCodeRedirect(String.valueOf(getLoginUserId()), client, approveScopes, redirectUri, state));
|
||||
}
|
||||
|
||||
private static OAuth2GrantTypeEnum getGrantTypeEnum(String responseType) {
|
||||
if (StrUtil.equals(responseType, "code")) {
|
||||
return OAuth2GrantTypeEnum.AUTHORIZATION_CODE;
|
||||
}
|
||||
if (StrUtil.equalsAny(responseType, "token")) {
|
||||
return OAuth2GrantTypeEnum.IMPLICIT;
|
||||
}
|
||||
throw exception0(BAD_REQUEST.getCode(), "response_type 参数值只允许 code 和 token");
|
||||
}
|
||||
|
||||
private String getAuthorizationCodeRedirect(String userId, OAuth2ClientDO client,
|
||||
List<String> scopes, String redirectUri, String state) {
|
||||
// 1. 创建 code 授权码
|
||||
String authorizationCode = oauth2GrantService.grantAuthorizationCodeForCode(userId, getUserType(), client.getClientid(), scopes,
|
||||
redirectUri, state);
|
||||
// 2. 拼接重定向的 URL
|
||||
return OAuth2Utils.buildAuthorizationCodeRedirectUri(redirectUri, authorizationCode, state);
|
||||
}
|
||||
|
||||
private Integer getUserType() {
|
||||
return UserTypeEnum.ADMIN.getValue();
|
||||
}
|
||||
|
||||
private String[] obtainBasicAuthorization(HttpServletRequest request) {
|
||||
String[] clientIdAndSecret = HttpUtils.obtainBasicAuthorization(request);
|
||||
if (ArrayUtil.isEmpty(clientIdAndSecret) || clientIdAndSecret.length != 2) {
|
||||
throw exception0(BAD_REQUEST.getCode(), "client_id 或 client_secret 未正确传递");
|
||||
}
|
||||
return clientIdAndSecret;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
package com.css.txw.sso.controller.oauth2;
|
||||
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.css.ggzc.framework.common.util.gy.GyUtils;
|
||||
import com.css.txw.sso.api.oauth2.OAuth2TokenApi;
|
||||
import com.css.txw.sso.api.oauth2.dto.AccessTokenSessionInfo;
|
||||
import com.css.txw.sso.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
|
||||
import com.css.txw.sso.api.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
|
||||
import com.css.txw.sso.api.oauth2.dto.OAuth2AccessTokenRespDTO;
|
||||
import com.css.txw.sso.constants.SsoApiConstants;
|
||||
import com.css.txw.sso.constants.SsoConstants;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2AccessTokenDO;
|
||||
import com.css.txw.sso.pojo.dto.session.*;
|
||||
import com.css.txw.sso.service.oauth2.OAuth2TokenService;
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
import com.css.ggzc.framework.common.util.object.BeanUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static com.css.ggzc.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@RequestMapping("/oauth2/token")
|
||||
@RestController
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class OAuth2TokenController implements OAuth2TokenApi {
|
||||
|
||||
@Resource
|
||||
private OAuth2TokenService oauth2TokenService;
|
||||
|
||||
@Override
|
||||
@PostMapping("/create")
|
||||
@Operation(description = "创建访问令牌")
|
||||
public CommonResult<OAuth2AccessTokenRespDTO> createAccessToken(@Valid @RequestBody OAuth2AccessTokenCreateReqDTO reqDTO) {
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(
|
||||
reqDTO.getUserId(), reqDTO.getClientId(), reqDTO.getScopes());
|
||||
final OAuth2AccessTokenRespDTO bean = BeanUtils.toBean(accessTokenDO, OAuth2AccessTokenRespDTO.class);
|
||||
bean.setUserId(accessTokenDO.getYhUuid());
|
||||
bean.setExpiresTime(accessTokenDO.getGqsj());
|
||||
return success(bean);
|
||||
}
|
||||
|
||||
@GetMapping("/check")
|
||||
@Override
|
||||
public CommonResult<OAuth2AccessTokenCheckRespDTO> checkAccessToken(@RequestParam("accessToken") String accessToken) {
|
||||
final SessionInfo sessionInfo = oauth2TokenService.checkAccessToken(accessToken);
|
||||
log.info("/check getSessionfromRedis:{}",sessionInfo);
|
||||
return success(covertSessionInfo(accessToken,sessionInfo));
|
||||
}
|
||||
|
||||
@DeleteMapping("/remove")
|
||||
@Override
|
||||
public CommonResult<OAuth2AccessTokenRespDTO> removeAccessToken(@RequestParam("accessToken") String accessToken) {
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.removeAccessToken(SsoConstants.CLIENT_DEFAULT,accessToken);
|
||||
final OAuth2AccessTokenRespDTO bean = BeanUtils.toBean(accessTokenDO, OAuth2AccessTokenRespDTO.class);
|
||||
bean.setUserId(accessTokenDO.getYhUuid());
|
||||
bean.setExpiresTime(accessTokenDO.getGqsj());
|
||||
return success(bean);
|
||||
}
|
||||
|
||||
@PutMapping("/refresh")
|
||||
@Override
|
||||
public CommonResult<OAuth2AccessTokenRespDTO> refreshAccessToken(@RequestParam("refreshToken") String refreshToken,
|
||||
@RequestParam("clientId") String clientId) {
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, clientId);
|
||||
final OAuth2AccessTokenRespDTO bean = BeanUtils.toBean(accessTokenDO, OAuth2AccessTokenRespDTO.class);
|
||||
bean.setUserId(accessTokenDO.getYhUuid());
|
||||
bean.setExpiresTime(accessTokenDO.getGqsj());
|
||||
return success(BeanUtils.toBean(accessTokenDO, OAuth2AccessTokenRespDTO.class));
|
||||
}
|
||||
|
||||
private OAuth2AccessTokenCheckRespDTO covertSessionInfo(String accessToken,SessionInfo sessionInfo){
|
||||
final OAuth2AccessTokenCheckRespDTO respDTO = new OAuth2AccessTokenCheckRespDTO();
|
||||
|
||||
final AccessTokenInfo tokenInfo = sessionInfo.getTokenInfo();
|
||||
if (!accessToken.equals(tokenInfo.getAccessToken())){
|
||||
respDTO.setHasRefreshedToken(true);
|
||||
respDTO.setNewAccessToken(tokenInfo.getAccessToken());
|
||||
respDTO.setNewExpireTime(tokenInfo.getGqsj());
|
||||
}else {
|
||||
respDTO.setHasRefreshedToken(false);
|
||||
}
|
||||
|
||||
final AccessTokenSessionInfo accessTokenSessionInfo = new AccessTokenSessionInfo();
|
||||
YhInfo yhxx = sessionInfo.getYhxx();
|
||||
BeanUtil.copyProperties(yhxx,accessTokenSessionInfo,false);
|
||||
accessTokenSessionInfo.setYhUuid(yhxx.getYhuuid());
|
||||
String yhlx = sessionInfo.getCurrentYhlx();
|
||||
if (!GyUtils.isNull(yhlx)){
|
||||
accessTokenSessionInfo.setYhlx(yhlx);
|
||||
}
|
||||
accessTokenSessionInfo.setQyuuid(sessionInfo.getQyuuid());
|
||||
accessTokenSessionInfo.setQymc(sessionInfo.getQymc());
|
||||
accessTokenSessionInfo.setNsrsbh(sessionInfo.getNsrsbh());
|
||||
log.info("/check接口返回sessionInfo:,{}",accessTokenSessionInfo);
|
||||
respDTO.setSessionInfo(accessTokenSessionInfo);
|
||||
return respDTO;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.css.txw.sso.controller.oauth2;
|
||||
|
||||
import com.css.txw.sso.pojo.vo.oauth2.OAuth2UserInfoRespVO;
|
||||
import com.css.txw.sso.service.yhxx.YhxxService;
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
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.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static com.css.ggzc.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "OAuth2用户信息")
|
||||
@RestController
|
||||
@RequestMapping("/userinfo")
|
||||
@Slf4j
|
||||
public class OAuth2UserController {
|
||||
|
||||
@Resource
|
||||
private YhxxService yhxxService;
|
||||
|
||||
@PostMapping("/get")
|
||||
@Operation(summary = "获得用户信息")
|
||||
public CommonResult<OAuth2UserInfoRespVO> getUserInfo(HttpServletRequest request) {
|
||||
return success(yhxxService.getUserInfo(request));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.css.txw.sso.controller.session;
|
||||
|
||||
import com.css.txw.sso.api.yhxx.SwitchSessionApi;
|
||||
import com.css.txw.sso.pojo.yhxx.SwitchCompanyResDTO;
|
||||
import com.css.txw.sso.service.session.SwitchSessionService;
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
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.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
|
||||
@Tag(name = "切换session信息")
|
||||
@RestController
|
||||
@RequestMapping("/switchSession")
|
||||
@Slf4j
|
||||
public class SwitchSessionController implements SwitchSessionApi {
|
||||
|
||||
@Resource
|
||||
private SwitchSessionService switchSessionService;
|
||||
|
||||
|
||||
@PostMapping("/company")
|
||||
@Operation(summary = "切换机构")
|
||||
@Override
|
||||
public CommonResult<SwitchCompanyResDTO> switchCompany(@RequestParam("token")String token,@RequestParam("jguuid")String jguuid) {
|
||||
return CommonResult.success(switchSessionService.switchCompany(token,jguuid));
|
||||
}
|
||||
|
||||
@PostMapping("/addCompany")
|
||||
@Operation(summary = "新增机构")
|
||||
@Override
|
||||
public CommonResult<String> addCompany(@RequestBody SwitchCompanyResDTO resDTO) {
|
||||
return CommonResult.success(switchSessionService.addCompany(resDTO));
|
||||
}
|
||||
|
||||
}
|
||||
860
txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/controller/thirdparty/DidController.java
vendored
Normal file
860
txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/controller/thirdparty/DidController.java
vendored
Normal file
@ -0,0 +1,860 @@
|
||||
package com.css.txw.sso.controller.thirdparty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.chainweaver.did.sdk.DidClient;
|
||||
import org.chainweaver.did.sdk.IDidClient;
|
||||
import org.chainweaver.did.sdk.model.AccessToken;
|
||||
import org.chainweaver.did.sdk.model.Proof;
|
||||
import org.chainweaver.did.sdk.model.VerifiableCredential;
|
||||
import org.chainweaver.did.sdk.model.VerifiablePresentation;
|
||||
import org.chainweaver.did.sdk.model.VerifiablePresentation.VerifiablePresentationBuilder;
|
||||
import org.chainweaver.did.sdk.model.req.ApplyBusinessLicenseExtend;
|
||||
import org.chainweaver.did.sdk.model.req.LoginExtend;
|
||||
import org.chainweaver.did.sdk.model.resp.Response;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.css.ggzc.framework.cache.utils.CacheUtils;
|
||||
import com.css.ggzc.framework.cache.utils.XtcsUtils;
|
||||
import com.css.ggzc.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
import com.css.ggzc.framework.common.pojo.R;
|
||||
import com.css.ggzc.framework.common.util.gy.GyUtils;
|
||||
import com.css.ggzc.framework.common.util.json.JsonUtils;
|
||||
import com.css.ggzc.framework.common.util.object.BeanUtils;
|
||||
import com.css.ggzc.framework.common.util.servlet.ServletUtils;
|
||||
import com.css.ggzc.framework.session.SessionUtils;
|
||||
import com.css.txw.mhzc.pojo.YhxxbDTO;
|
||||
import com.css.txw.sso.constants.SsoConstants;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2AccessTokenDO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginRespVO;
|
||||
import com.css.txw.sso.pojo.vo.thirdparty.did.DidCallbackExtendInfo;
|
||||
import com.css.txw.sso.pojo.vo.thirdparty.did.DidCredentialSubject;
|
||||
import com.css.txw.sso.pojo.vo.thirdparty.did.DidExtendVcsInfo;
|
||||
import com.css.txw.sso.pojo.vo.thirdparty.did.DidLoginExtend;
|
||||
import com.css.txw.sso.pojo.vo.thirdparty.did.QrCodeInfo;
|
||||
import com.css.txw.sso.service.oauth2.OAuth2TokenService;
|
||||
import com.css.txw.sso.service.yhxx.YhxxService;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/did")
|
||||
@Tag(name = "did接口对接")
|
||||
@Slf4j
|
||||
public class DidController {
|
||||
|
||||
/** 请求登录凭证的地址 */
|
||||
public static final String XTCS_CODE_TXW_DID_LOGIN_VP_URL = "TXW_DID_LOGIN_VP_URL";
|
||||
/** 请求企业实名凭证的地址 */
|
||||
public static final String XTCS_CODE_TXW_DID_BUSI_LICE_VP_URL = "TXW_DID_BUSI_LICE_VP_URL";
|
||||
/** 登录回调地址 */
|
||||
public static final String XTCS_CODE_TXW_DID_LOGIN_CALLBACK_URL = "TXW_DID_LOGIN_CALLBACK_URL";
|
||||
/** 企业实名认证回调地址 */
|
||||
public static final String XTCS_CODE_TXW_DID_BUSI_LICE_CALLBACK_URL = "TXW_DID_BUSI_LICE_CALLBACK_URL";
|
||||
/** DID控制台地址 */
|
||||
public static final String XTCS_CODE_TXW_DID_CONSOLE_LOGIN_URL = "TXW_DID_CONSOLE_LOGIN_URL";
|
||||
/** DID控制台登录用户名 */
|
||||
public static final String XTCS_CODE_TXW_DID_CONSOLE_USERNAME = "TXW_DID_CONSOLE_USERNAME";
|
||||
/** DID控制台登录密码 */
|
||||
public static final String XTCS_CODE_TXW_DID_CONSOLE_PASSWORD = "TXW_DID_CONSOLE_PASSWORD";
|
||||
|
||||
/** 请求授权的平台的名称 */
|
||||
public static final String XTCS_CODE_TXW_DID_AUTH_NAME = "TXW_DID_AUTH_NAME";
|
||||
/** 请求授权的平台的英文名称 */
|
||||
public static final String XTCS_CODE_TXW_DID_AUTH_EN_NAME = "TXW_DID_AUTH_EN_NAME";
|
||||
public static final String XTCS_CODE_TXW_DID_LOGIN_TEMPLATE_ID = "TXW_DID_LOGIN_TEMPLATE_ID";
|
||||
|
||||
public static final String XTCS_CODE_TXW_DID_LOGIN_TEMPLATE_VERSION = "TXW_DID_LOGIN_TEMPLATE_VERSION";
|
||||
|
||||
|
||||
/**
|
||||
* 运营中心的 DID
|
||||
*/
|
||||
public static final String XTCS_CODE_TXW_DID_CONSOLE_DIDCODE="TXW_DID_CONSOLE_DIDCODE";
|
||||
|
||||
// TXW:DID:REQ:ID: 缓存请求标识前缀
|
||||
/** 缓存请求标识前缀 */
|
||||
public static final String REQ_ID_PREFIX = "TXW:DID:REQ:ID:";
|
||||
|
||||
/**
|
||||
* 缓存用户信息前缀
|
||||
*/
|
||||
public static final String REQ_USER_DATA_PREFIX = "TXW:DID:USER:Data:";
|
||||
/**
|
||||
* 缓存用户did前缀
|
||||
*/
|
||||
public static final String REQ_USER_DID_PREFIX = "TXW:DID:USER:DID:";
|
||||
/**
|
||||
* 缓存did返回的用户信息前缀
|
||||
*/
|
||||
public static final String REQ_USER_DID_DATA_PREFIX = "TXW:DID:USER:DID:Data:";
|
||||
|
||||
public static final String REQ_USER_DID_DLZH_PREFIX = "TXW:DID:USER:DLZH:";
|
||||
|
||||
/**
|
||||
* 页面请求
|
||||
*/
|
||||
public static final String DID_REQ_STATUS_PAGE = "1";
|
||||
/**
|
||||
* 扫描请求
|
||||
*/
|
||||
public static final String DID_REQ_STATUS_QR = "2";
|
||||
/**
|
||||
* 返回处理
|
||||
*/
|
||||
public static final String DID_REQ_STATUS_CALLBACK = "3";
|
||||
|
||||
/**
|
||||
* 手机绑定
|
||||
*/
|
||||
public static final String DID_REQ_PHONE_BIND = "4";
|
||||
|
||||
/**
|
||||
* did 认证失败
|
||||
*/
|
||||
public static final String DID_REQ_STATUS_BUSI_FAILURE = "5";
|
||||
public static final String DID_REQ_STATUS_BUSI_FAILURE_MSG_PREFIX = "TXW:DID:BUSI:FAILURE:MSG:";
|
||||
/**
|
||||
* 认证成功
|
||||
*/
|
||||
public static final String DID_REQ_STATUS_BUSI_SUCCESS = "6";
|
||||
|
||||
public static final int ERROR_CODE_PARAM = 301001;
|
||||
|
||||
public static final long timeout = 1000 * 60 * 30;
|
||||
|
||||
@Resource
|
||||
private YhxxService yhxxService;
|
||||
|
||||
@Resource
|
||||
private OAuth2TokenService oauth2TokenService;
|
||||
|
||||
/**
|
||||
* 获取登录二维码内容
|
||||
*
|
||||
* @name 获取登录二维码内容
|
||||
* @time 2025-12-12
|
||||
* @author 崔学志
|
||||
* @history 修订历史(历次修订内容、修订人、修订时间等)
|
||||
*/
|
||||
@Operation(summary = "获取登录二维码内容")
|
||||
@PostMapping("/pub/login/qrcode")
|
||||
public CommonResult<QrCodeInfo> getLoginUrlQRCode() {
|
||||
return getQrCode(XTCS_CODE_TXW_DID_LOGIN_VP_URL);
|
||||
}
|
||||
|
||||
private CommonResult<QrCodeInfo> getQrCode(String xtcsCode) {
|
||||
CommonResult<QrCodeInfo> result = CommonResult.success(null);
|
||||
String url = XtcsUtils.getXtcs(xtcsCode);
|
||||
if (GyUtils.isNull(url)) {
|
||||
String msg = String.format("系统参数%s为空!", xtcsCode);
|
||||
log.info(msg);
|
||||
result.setMsg(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
return result;
|
||||
}
|
||||
String reqId = GyUtils.getUuid() + GyUtils.getUuid();
|
||||
String tmp = String.format("%s?reqId=%s", url, reqId);
|
||||
QrCodeInfo info = QrCodeInfo.builder().reqId(reqId).url(tmp).build();
|
||||
String key = String.format("%s%s", REQ_ID_PREFIX, reqId);
|
||||
CacheUtils.cacheData(key, DID_REQ_STATUS_PAGE, timeout);
|
||||
result.setData(info);
|
||||
//缓存里设置登录账户
|
||||
key = String.format("%s%s", REQ_USER_DID_DLZH_PREFIX, reqId);
|
||||
String yhuuid = SessionUtils.getYhUuid();
|
||||
CacheUtils.cacheData(key, yhuuid);
|
||||
log.info("key:{},yhuuid:{}",key,yhuuid);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取认证二维码内容
|
||||
*
|
||||
* @name 获取认证二维码内容
|
||||
* @time 2025-12-12
|
||||
* @author 崔学志
|
||||
* @history 修订历史(历次修订内容、修订人、修订时间等)
|
||||
*/
|
||||
@Operation(summary = "获取认证二维码内容")
|
||||
@Parameter(name = "request", description = "请求报文")
|
||||
@PostMapping("/busilice/qrcode")
|
||||
public CommonResult<QrCodeInfo> getBusinessLicenseUrlQRCode() {
|
||||
return getQrCode(XTCS_CODE_TXW_DID_BUSI_LICE_VP_URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录凭证信息
|
||||
*
|
||||
* @name 获取登录凭证信息
|
||||
* @time 2025-12-12
|
||||
* @author 崔学志
|
||||
* @history 修订历史(历次修订内容、修订人、修订时间等)
|
||||
*/
|
||||
@Operation(summary = "获取登录凭证信息")
|
||||
@Parameter(name = "request", description = "请求报文")
|
||||
@GetMapping(value = "/pub/getvp/login", produces = "application/json")
|
||||
public String getLoginVP(
|
||||
@RequestParam(required = false, name = "reqId") String reqId) {
|
||||
Response<VerifiablePresentation<DidLoginExtend>> result =Response.SuccessResponse();
|
||||
// Map<String,Object> r =new HashMap<>();
|
||||
if (GyUtils.isNull(reqId)) {
|
||||
String msg = "reqId is null . ";
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(ERROR_CODE_PARAM);
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
// return r;
|
||||
}
|
||||
String key = String.format("%s%s", REQ_ID_PREFIX, reqId);
|
||||
String status = CacheUtils.getCacheData(key);
|
||||
log.info("request {}, status :{}",reqId,status);
|
||||
if (GyUtils.isNull(status)) {
|
||||
String msg = String.format("该请求%s已过期!", reqId);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
// return r;
|
||||
}
|
||||
if (!GyUtils.isEquals(status, DID_REQ_STATUS_PAGE)) {
|
||||
String msg = String.format("该请求%s状态不正确,请在页面上重新操作!", reqId);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
CacheUtils.cacheData(key, DID_REQ_STATUS_QR);
|
||||
String consoleUrl = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_CONSOLE_LOGIN_URL);
|
||||
// 新建客户端
|
||||
IDidClient didClient = new DidClient(consoleUrl, DidClient.version15);
|
||||
String username = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_CONSOLE_USERNAME);
|
||||
String pwd = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_CONSOLE_PASSWORD);
|
||||
// 登录
|
||||
Response<AccessToken> login = didClient.login(username, pwd);
|
||||
|
||||
log.info("did控制台登录响应:{}", login);
|
||||
String url = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_LOGIN_CALLBACK_URL);
|
||||
if (GyUtils.isNull(url)) {
|
||||
String msg = String.format("系统参数%s为空!", XTCS_CODE_TXW_DID_LOGIN_CALLBACK_URL);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
// return r;
|
||||
}
|
||||
String callbackUrl = String.format("%s?reqId=%s", url,reqId);
|
||||
String authorizedName = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_AUTH_NAME);
|
||||
if (GyUtils.isNull(authorizedName)) {
|
||||
String msg = String.format("系统参数%s为空!", XTCS_CODE_TXW_DID_AUTH_NAME);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
// return r;
|
||||
}
|
||||
String authorizedNameEn = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_AUTH_EN_NAME);
|
||||
if (GyUtils.isNull(authorizedNameEn)) {
|
||||
String msg = String.format("系统参数%s为空!", XTCS_CODE_TXW_DID_AUTH_EN_NAME);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
// return r;
|
||||
}
|
||||
LoginExtend extend1 = LoginExtend.builder()
|
||||
.requestId(reqId)
|
||||
.method("POST")
|
||||
.callbackUrl(callbackUrl)
|
||||
.authorizedName(authorizedName)
|
||||
.authorizedNameEn(authorizedNameEn)
|
||||
.build();
|
||||
DidLoginExtend extend = new DidLoginExtend();
|
||||
BeanUtils.copyBean(extend1, extend);
|
||||
List<DidExtendVcsInfo> vcs = new ArrayList<>();
|
||||
String did = getXtcs(XTCS_CODE_TXW_DID_CONSOLE_DIDCODE);
|
||||
// String issuer = "did:cndid:cndid";
|
||||
String tmpid = getXtcs(XTCS_CODE_TXW_DID_LOGIN_TEMPLATE_ID);
|
||||
// tmpid = "100752";
|
||||
String version = getXtcs(XTCS_CODE_TXW_DID_LOGIN_TEMPLATE_VERSION);
|
||||
// version = "v2";
|
||||
// DidExtendVcsInfo vcsInfo = DidExtendVcsInfo.builder()
|
||||
// .vctId(tmpid)
|
||||
// .vctVersion(version)
|
||||
// .issuer(did)
|
||||
// .build();
|
||||
// vcs.add(vcsInfo);
|
||||
DidExtendVcsInfo vcsInfo = DidExtendVcsInfo.builder()
|
||||
.vctId("100001")
|
||||
.vctVersion("v9")
|
||||
.issuer("did:cndid:cndid")
|
||||
.build();
|
||||
vcs.add(vcsInfo);
|
||||
// vcsInfo = DidExtendVcsInfo.builder()
|
||||
// .vctId("100000")
|
||||
// .vctVersion("v7")
|
||||
// .issuer("did:cndid:cndid")
|
||||
// .build();
|
||||
vcs.add(vcsInfo);
|
||||
extend.setVcs(vcs);
|
||||
List<Proof> proofList = new ArrayList<Proof>();
|
||||
// VerifiablePresentation<DidLoginExtend> loginvp = new VerifiablePresentation<DidLoginExtend>();
|
||||
VerifiablePresentationBuilder<DidLoginExtend> verifiablePresentationBuilder = VerifiablePresentation.builder();
|
||||
verifiablePresentationBuilder.presentationUsage("DID_LOGIN_REQUEST");
|
||||
verifiablePresentationBuilder.proof(proofList);
|
||||
verifiablePresentationBuilder.extend(extend);
|
||||
VerifiablePresentation<DidLoginExtend> loginvp = verifiablePresentationBuilder.build();
|
||||
Response<VerifiablePresentation<DidLoginExtend>> res = didClient.vpSign(loginvp, DidLoginExtend.class);
|
||||
log.info("res:{}", res);
|
||||
String ret = JsonUtils.toJson(res.getData());
|
||||
log.info("ret:{}", ret);
|
||||
|
||||
Response<Boolean> veri = didClient.vpVerify(ret);
|
||||
log.info("vpVerify:{}", veri);
|
||||
// veri = didClient.vpVerify(ret);
|
||||
// r.put("code",200000);
|
||||
// r.put("msg","ok");
|
||||
// r.put("data", res.getData());
|
||||
// log.info("return:{}", JsonUtils.toJson(r));
|
||||
// return JsonUtils.toJson(r);
|
||||
return JsonUtils.toJson(res);
|
||||
}
|
||||
|
||||
private String getXtcs(String xtcsCode) {
|
||||
return getXtcs(xtcsCode,null);
|
||||
}
|
||||
|
||||
private String getXtcs(String xtcsCode, String prefix) {
|
||||
if (GyUtils.isNull(xtcsCode)) {
|
||||
return null;
|
||||
}
|
||||
String code =xtcsCode;
|
||||
if (GyUtils.isNotNull(prefix)) {
|
||||
code = xtcsCode.replaceFirst("TXW", prefix);
|
||||
}
|
||||
return XtcsUtils.getXtcs(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录凭证信息返回调用
|
||||
*
|
||||
* @name 获取登录凭证信息返回调用
|
||||
* @time 2025-12-12
|
||||
* @author 崔学志
|
||||
* @history 修订历史(历次修订内容、修订人、修订时间等)
|
||||
*/
|
||||
@Operation(summary = "获取登录凭证信息返回调用")
|
||||
@Parameter(name = "request", description = "请求报文")
|
||||
@PostMapping(value = "/pub/callback/login", produces = "application/json")
|
||||
public String getLoginVPCallback(@RequestParam(required = false, name = "reqId") String reqId,
|
||||
@RequestBody Map<String, Object> vpRequestBody) {
|
||||
Response<String> result =Response.SuccessResponse();
|
||||
result.setCode(200000);
|
||||
if (GyUtils.isNull(vpRequestBody)) {
|
||||
String msg = "vpRequestBody is null . ";
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(ERROR_CODE_PARAM);
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
VerifiablePresentation request = BeanUtils.toBean(vpRequestBody, VerifiablePresentation.class);
|
||||
log.info("request 参数:{}",request);
|
||||
String checkMsg = checkvp(request);
|
||||
if (GyUtils.isNotNull(checkMsg)) {
|
||||
log.info(checkMsg);
|
||||
result.setMessage(checkMsg);
|
||||
result.setCode(ERROR_CODE_PARAM);
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
result.setCode(200000);
|
||||
result.setData("true");
|
||||
if (GyUtils.isNull(reqId)) {
|
||||
String msg = "reqId is null . ";
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(ERROR_CODE_PARAM);
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
if (GyUtils.isNull(request)) {
|
||||
String msg = "request is null . ";
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(ERROR_CODE_PARAM);
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
String key = String.format("%s%s", REQ_ID_PREFIX, reqId);
|
||||
String status = CacheUtils.getCacheData(key);
|
||||
log.info("request {}, status :{}",reqId,status);
|
||||
if (GyUtils.isNull(status)) {
|
||||
String msg = String.format("该请求%s已过期!", reqId);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
if (!GyUtils.isEquals(status, DID_REQ_STATUS_QR)) {
|
||||
String msg = String.format("该请求%s状态不正确,请在页面上重新操作!", reqId);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
CacheUtils.cacheData(key, DID_REQ_STATUS_CALLBACK);
|
||||
List<VerifiableCredential> vcList = request.getVerifiableCredential();
|
||||
if (GyUtils.isNotNull(vcList)) {
|
||||
VerifiableCredential vc = vcList.get(0);
|
||||
String holderDid = vc.getHolder();
|
||||
DidCallbackExtendInfo extInfo = BeanUtils.toBean(request.getExtend(), DidCallbackExtendInfo.class);
|
||||
DidCredentialSubject cs = BeanUtils.toBean(vc.getCredentialSubject(), DidCredentialSubject.class);
|
||||
YhxxbDTO yhxx = null;
|
||||
String dlzh = cs.getPhone(); // 获取手机号
|
||||
if (GyUtils.isNotNull(dlzh)) {
|
||||
yhxx = yhxxService.getYhxxByDlzh(dlzh);
|
||||
}
|
||||
else if (GyUtils.isNotNull(extInfo) && GyUtils.isNotNull(extInfo.getAuthoriserIdCard())) {
|
||||
yhxx = yhxxService.getYhxxBySfzjhm((extInfo.getAuthoriserIdCard()));
|
||||
}
|
||||
else {
|
||||
yhxx = yhxxService.getYhxxByDid(holderDid);
|
||||
}
|
||||
//手机号码为空 ,进行页面绑定
|
||||
if (GyUtils.isNull(yhxx) && GyUtils.isNull(dlzh)) {
|
||||
//缓存did 。一次请求对应一个did
|
||||
String tmp = String.format("%s%s", REQ_USER_DID_PREFIX,reqId);
|
||||
CacheUtils.cacheData(tmp, holderDid,timeout);
|
||||
//缓存did数据,为创建账号做准备
|
||||
cs.setExtInfo(extInfo);
|
||||
tmp = String.format("%s%s", REQ_USER_DID_DATA_PREFIX,reqId);
|
||||
CacheUtils.cacheData(tmp, JsonUtils.toJson(cs),timeout);
|
||||
//进行手机绑定
|
||||
key = String.format("%s%s", REQ_ID_PREFIX, reqId);
|
||||
CacheUtils.cacheData(key, DID_REQ_PHONE_BIND,timeout);
|
||||
}
|
||||
//手机号不为空 ,直接加入账户数据
|
||||
else if (GyUtils.isNull(yhxx) && GyUtils.isNotNull(dlzh)) {
|
||||
yhxx = yhxxService.getYhxxBySjhm(dlzh);
|
||||
if (GyUtils.isNull(yhxx)) {
|
||||
yhxx = new YhxxbDTO();
|
||||
yhxx.setYhUuid(IdUtil.fastSimpleUUID());
|
||||
yhxx.setDid(holderDid);
|
||||
yhxx.setSjhm1(dlzh);
|
||||
yhxx.setDlzh(dlzh);
|
||||
if (GyUtils.isNotNull(cs.getLegalName())) {
|
||||
yhxx.setZsxm1(cs.getLegalName());
|
||||
}
|
||||
else if (GyUtils.isNotNull(cs.getEntname())) {
|
||||
yhxx.setZsxm1(cs.getEntname());
|
||||
}
|
||||
else {
|
||||
yhxx.setZsxm1("--");
|
||||
}
|
||||
if (GyUtils.isNotNull(extInfo)) {
|
||||
yhxx.setSfzjhm(extInfo.getAuthoriserIdCard());
|
||||
}
|
||||
yhxx = yhxxService.saveYhxxByDid(yhxx);
|
||||
}
|
||||
else {
|
||||
yhxx.setDid(holderDid);
|
||||
yhxxService.updateDid(yhxx);
|
||||
}
|
||||
// 企业认证成功
|
||||
YhxxbDTO qyxx = new YhxxbDTO();
|
||||
qyxx.setQymc(cs.getEntname());
|
||||
qyxx.setNsrsbh(cs.getUniscid());
|
||||
qyxx.setYhUuid(yhxx.getYhUuid());
|
||||
log.info("qyxx:{}",qyxx);
|
||||
qyxx = yhxxService.intQyxxByDid(qyxx);
|
||||
String tmp = String.format("%s%s", REQ_USER_DATA_PREFIX,reqId);
|
||||
CacheUtils.cacheData(tmp, JsonUtils.toJson(yhxx),timeout);
|
||||
}
|
||||
else {
|
||||
String tmp = String.format("%s%s", REQ_USER_DATA_PREFIX,reqId);
|
||||
CacheUtils.cacheData(tmp, JsonUtils.toJson(yhxx),timeout);
|
||||
}
|
||||
}
|
||||
else {
|
||||
String msg = String.format("返回参数VerifiableCredential为空!");
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
|
||||
private String checkvp(VerifiablePresentation request) {
|
||||
if (GyUtils.isNull(request)) {
|
||||
return null;
|
||||
}
|
||||
String consoleUrl = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_CONSOLE_LOGIN_URL);
|
||||
// 新建客户端
|
||||
IDidClient didClient = new DidClient(consoleUrl, DidClient.version15);
|
||||
String username = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_CONSOLE_USERNAME);
|
||||
String pwd = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_CONSOLE_PASSWORD);
|
||||
// 登录
|
||||
Response<AccessToken> login = didClient.login(username, pwd);
|
||||
Response<Boolean> veri = didClient.vpVerify(request);
|
||||
log.info("checkvp veri:{}",veri);
|
||||
if (GyUtils.isNotNull(veri) && GyUtils.isNotNull(veri.getData())
|
||||
&& veri.getData()) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
// return veri.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取企业实名凭证信息
|
||||
*
|
||||
* @name 获取企业实名凭证信息
|
||||
* @time 2025-12-12
|
||||
* @author 崔学志
|
||||
* @history 修订历史(历次修订内容、修订人、修订时间等)
|
||||
*/
|
||||
@Operation(summary = "获取企业实名凭证信息")
|
||||
@Parameter(name = "request", description = "请求报文")
|
||||
@GetMapping(value ="/pub/getvp/busi", produces = "application/json")
|
||||
public String getBusinessLicenseVP(
|
||||
@RequestParam(required = false, name = "reqId") String reqId) {
|
||||
Response<VerifiablePresentation<ApplyBusinessLicenseExtend>> result =Response.SuccessResponse();
|
||||
if (GyUtils.isNull(reqId)) {
|
||||
String msg = "reqId is null . ";
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(ERROR_CODE_PARAM);
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
String key = String.format("%s%s", REQ_ID_PREFIX, reqId);
|
||||
String status = CacheUtils.getCacheData(key);
|
||||
log.info("request {}, status :{}",reqId,status);
|
||||
if (GyUtils.isNull(status)) {
|
||||
String msg = String.format("该请求%s已过期!", reqId);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
if (!GyUtils.isEquals(status, DID_REQ_STATUS_PAGE)) {
|
||||
String msg = String.format("该请求%s状态不正确,请在页面上重新操作!", reqId);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
CacheUtils.cacheData(key, DID_REQ_STATUS_QR);
|
||||
String consoleUrl = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_CONSOLE_LOGIN_URL);
|
||||
// 新建客户端
|
||||
IDidClient didClient = new DidClient(consoleUrl, DidClient.version15);
|
||||
String username = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_CONSOLE_USERNAME);
|
||||
String pwd = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_CONSOLE_PASSWORD);
|
||||
// 登录
|
||||
Response<AccessToken> login = didClient.login(username, pwd);
|
||||
log.info("did控制台登录响应:{}", login);
|
||||
List<Proof> proofList = new ArrayList<Proof>();
|
||||
// Proof pr = Proof.builder()
|
||||
// .build();
|
||||
VerifiablePresentation<ApplyBusinessLicenseExtend> busivp = VerifiablePresentation.vpCreateApplyBusinessLicense(proofList);
|
||||
busivp.setPresentationUsage("DID_GET_IDENTITY_VC_REQUEST");
|
||||
String url = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_BUSI_LICE_CALLBACK_URL);
|
||||
if (GyUtils.isNull(url)) {
|
||||
String msg = String.format("系统参数%s为空!", XTCS_CODE_TXW_DID_LOGIN_CALLBACK_URL);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
String callbackUrl = String.format("%s?reqId=%s", url,reqId);
|
||||
String authorizedName = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_AUTH_NAME);
|
||||
if (GyUtils.isNull(authorizedName)) {
|
||||
String msg = String.format("系统参数%s为空!", XTCS_CODE_TXW_DID_AUTH_NAME);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
String authorizedNameEn = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_AUTH_EN_NAME);
|
||||
if (GyUtils.isNull(authorizedNameEn)) {
|
||||
String msg = String.format("系统参数%s为空!", XTCS_CODE_TXW_DID_AUTH_EN_NAME);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
List<String> vctId = Arrays.asList("100001");
|
||||
String condid = XtcsUtils.getXtcs(XTCS_CODE_TXW_DID_CONSOLE_DIDCODE);
|
||||
condid = "did:cndid:cndid";
|
||||
List<String> issuer = Arrays.asList(condid);
|
||||
ApplyBusinessLicenseExtend extend = ApplyBusinessLicenseExtend.builder()
|
||||
.requestId(reqId)
|
||||
.method("POST")
|
||||
.callbackUrl(callbackUrl)
|
||||
.authorizedName(authorizedName)
|
||||
.authorizedNameEn(authorizedNameEn)
|
||||
.vctId(vctId)
|
||||
.issuer(issuer)
|
||||
.build();
|
||||
busivp.setExtend(extend);
|
||||
Response<VerifiablePresentation<ApplyBusinessLicenseExtend>> res = didClient.vpCreateApplyBusinessLicense(busivp);
|
||||
log.info("res:{}", res);
|
||||
// return res;
|
||||
Response<Boolean> ver = didClient.vpVerify(res.getData());
|
||||
log.info("ver:{}", ver);
|
||||
return JsonUtils.toJson(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取企业实名凭证信息返回调用
|
||||
*
|
||||
* @name 获取企业实名凭证信息返回调用
|
||||
* @time 2025-12-12
|
||||
* @author 崔学志
|
||||
* @history 修订历史(历次修订内容、修订人、修订时间等)
|
||||
*/
|
||||
@Operation(summary = "获取企业实名凭证信息返回调用")
|
||||
@Parameter(name = "request", description = "请求报文")
|
||||
@PostMapping(value = "/pub/callback/busi", produces = "application/json")
|
||||
public String getBusinessLicenseVPCallback(
|
||||
@RequestParam(required = false, name = "reqId") String reqId,
|
||||
@RequestBody VerifiablePresentation request) {
|
||||
log.info("request 参数:{}",request);
|
||||
Response<String> result =Response.SuccessResponse();
|
||||
result.setCode(200000);
|
||||
result.setData("true");
|
||||
if (GyUtils.isNull(reqId)) {
|
||||
String msg = "reqId is null . ";
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(ERROR_CODE_PARAM);
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
if (GyUtils.isNull(request)) {
|
||||
String msg = "request is null . ";
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(ERROR_CODE_PARAM);
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
String checkMsg = checkvp(request);
|
||||
if (GyUtils.isNotNull(checkMsg)) {
|
||||
log.info(checkMsg);
|
||||
result.setMessage(checkMsg);
|
||||
result.setCode(ERROR_CODE_PARAM);
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
String key = String.format("%s%s", REQ_ID_PREFIX, reqId);
|
||||
String status = CacheUtils.getCacheData(key);
|
||||
log.info("request {}, status :{}",reqId,status);
|
||||
if (GyUtils.isNull(status)) {
|
||||
String msg = String.format("该请求%s已过期!", reqId);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
if (!GyUtils.isEquals(status, DID_REQ_STATUS_QR)) {
|
||||
String msg = String.format("该请求%s状态不正确,请在页面上重新操作!", reqId);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
CacheUtils.cacheData(key, DID_REQ_STATUS_CALLBACK);
|
||||
List<VerifiableCredential> vcList = request.getVerifiableCredential();
|
||||
if (GyUtils.isNotNull(vcList)) {
|
||||
VerifiableCredential vc = vcList.get(0);
|
||||
String holderDid = vc.getHolder();
|
||||
log.info("holderDid:{}",holderDid);
|
||||
DidCallbackExtendInfo extInfo = BeanUtils.toBean(request.getExtend(), DidCallbackExtendInfo.class);
|
||||
DidCredentialSubject cs = BeanUtils.toBean(vc.getCredentialSubject(), DidCredentialSubject.class);
|
||||
log.info("cs:{}",cs);
|
||||
YhxxbDTO yhxx = yhxxService.getYhxxByDid(holderDid);
|
||||
if (GyUtils.isNull(yhxx)) {
|
||||
String tmp = String.format("%s%s", REQ_USER_DID_DLZH_PREFIX, reqId);
|
||||
log.info("key:{}",tmp);
|
||||
String yhuuid = CacheUtils.getCacheData(tmp);
|
||||
log.info("yhuuid:{}",yhuuid);
|
||||
yhxx = yhxxService.getYhxx(yhuuid);
|
||||
if (GyUtils.isNotNull(yhxx)) {
|
||||
yhxx.setDid(holderDid);
|
||||
yhxxService.updateDid(yhxx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
String msg = String.format("已经进行过实名认证。不能进行重复认证!");
|
||||
CacheUtils.cacheData(key, DID_REQ_STATUS_BUSI_FAILURE);
|
||||
CacheUtils.cacheData(DID_REQ_STATUS_BUSI_FAILURE_MSG_PREFIX+reqId, msg);
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
|
||||
}
|
||||
log.info("yhxx:{}",yhxx);
|
||||
if (GyUtils.isNull(yhxx)) {
|
||||
CacheUtils.cacheData(key, DID_REQ_STATUS_BUSI_FAILURE);
|
||||
CacheUtils.cacheData(DID_REQ_STATUS_BUSI_FAILURE_MSG_PREFIX+reqId, "根据did未查询到数据!");
|
||||
}
|
||||
else {
|
||||
if (GyUtils.isNotNull(cs) ) {
|
||||
if (GyUtils.isEquals(cs.getEntname(), yhxx.getZsxm1())
|
||||
|| GyUtils.isEquals(cs.getLegalName(), yhxx.getZsxm1())) {
|
||||
CacheUtils.cacheData(key, DID_REQ_STATUS_BUSI_SUCCESS);
|
||||
YhxxbDTO qyxx = new YhxxbDTO();
|
||||
qyxx.setQymc(cs.getEntname());
|
||||
qyxx.setNsrsbh(cs.getUniscid());
|
||||
qyxx.setYhUuid(yhxx.getYhUuid());
|
||||
log.info("qyxx:{}",qyxx);
|
||||
qyxx = yhxxService.intQyxxByDid(qyxx);
|
||||
}
|
||||
else {
|
||||
CacheUtils.cacheData(key, DID_REQ_STATUS_BUSI_FAILURE);
|
||||
CacheUtils.cacheData(DID_REQ_STATUS_BUSI_FAILURE_MSG_PREFIX+reqId, "名称不一致!");
|
||||
}
|
||||
}
|
||||
else {
|
||||
CacheUtils.cacheData(key, DID_REQ_STATUS_BUSI_FAILURE);
|
||||
CacheUtils.cacheData(DID_REQ_STATUS_BUSI_FAILURE_MSG_PREFIX+reqId, "根据did未查询到数据!");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
CacheUtils.cacheData(key, DID_REQ_STATUS_BUSI_FAILURE);
|
||||
CacheUtils.cacheData(DID_REQ_STATUS_BUSI_FAILURE_MSG_PREFIX+reqId, "返回参数VerifiableCredential为空!");
|
||||
String msg = String.format("返回参数VerifiableCredential为空!");
|
||||
log.info(msg);
|
||||
result.setMessage(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
// return result;
|
||||
return JsonUtils.toJson(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录回调响应结果
|
||||
*
|
||||
* @name 获取登录回调响应结果
|
||||
* @time 2025-12-12
|
||||
* @author 崔学志
|
||||
* @history 修订历史(历次修订内容、修订人、修订时间等)
|
||||
*/
|
||||
@Operation(summary = "获取登录回调响应结果")
|
||||
@Parameter(name = "request", description = "请求报文")
|
||||
@GetMapping("/pub/backresult/login")
|
||||
public CommonResult<R> getLoginCallbackResult(@RequestParam(required = false, name = "reqId") String reqId) {
|
||||
CommonResult<R> result = CommonResult.success(null);
|
||||
if (GyUtils.isNull(reqId)) {
|
||||
String msg = "reqId is null . ";
|
||||
log.info(msg);
|
||||
result.setMsg(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
return result;
|
||||
}
|
||||
String key = String.format("%s%s", REQ_ID_PREFIX, reqId);
|
||||
String status = CacheUtils.getCacheData(key);
|
||||
// status = "3";
|
||||
R r = R.ok().put("status", status);
|
||||
key = String.format("%s%s", REQ_USER_DATA_PREFIX, reqId);
|
||||
String userJson = CacheUtils.getCacheData(key);
|
||||
if (GyUtils.isNotNull(userJson)) {
|
||||
YhxxbDTO yhxx = JsonUtils.toBean(userJson, YhxxbDTO.class);
|
||||
String userId = yhxx.getYhUuid();
|
||||
// 创建访问令牌
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, "default", null);
|
||||
// 构建返回结果
|
||||
final AuthLoginRespVO respVO = new AuthLoginRespVO();
|
||||
respVO.setAccessToken(accessTokenDO.getAccessToken());
|
||||
respVO.setRefreshToken(accessTokenDO.getRefreshToken());
|
||||
respVO.setExpiresTime(accessTokenDO.getGqsj());
|
||||
AuthLoginRespVO login = respVO;
|
||||
final Cookie cookie = new Cookie(SsoConstants.COOKIE_TOKEN_KEY,login.getAccessToken());
|
||||
cookie.setPath(SsoConstants.COOKIE_PATH);
|
||||
cookie.setHttpOnly(true);
|
||||
//cookie.setMaxAge(-1);
|
||||
final HttpServletResponse response = ServletUtils.getResponse();
|
||||
response.addCookie(cookie);
|
||||
// return success(login);
|
||||
r.put("authLoginRespVO", login);
|
||||
}
|
||||
result.setData(r);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取认证回调响应结果
|
||||
*
|
||||
* @name 获取认证回调响应结果
|
||||
* @time 2025-12-12
|
||||
* @author 崔学志
|
||||
* @history 修订历史(历次修订内容、修订人、修订时间等)
|
||||
*/
|
||||
@Operation(summary = "获取认证回调响应结果")
|
||||
@Parameter(name = "request", description = "请求报文")
|
||||
@GetMapping("/pub/backresult/busi")
|
||||
public CommonResult<R> getBusiLiceCallbackResult(@RequestParam(required = false, name = "reqId") String reqId) {
|
||||
CommonResult<R> result = CommonResult.success(null);
|
||||
if (GyUtils.isNull(reqId)) {
|
||||
String msg = "reqId is null . ";
|
||||
log.info(msg);
|
||||
result.setMsg(msg);
|
||||
result.setCode(GlobalErrorCodeConstants.ERROR.getCode());
|
||||
return result;
|
||||
}
|
||||
String key = String.format("%s%s", REQ_ID_PREFIX, reqId);
|
||||
String status = CacheUtils.getCacheData(key);
|
||||
String msg = CacheUtils.getCacheData(DID_REQ_STATUS_BUSI_FAILURE_MSG_PREFIX+reqId);
|
||||
// status = "6";
|
||||
R r = R.ok().put("status", status)
|
||||
.put("msg", msg);
|
||||
result.setData(r);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package com.css.txw.sso.controller.thirdparty;//package com.css.lsl.sso.controller.thirdparty;
|
||||
//
|
||||
//
|
||||
//import cn.hutool.crypto.SecureUtil;
|
||||
//import cn.hutool.http.HttpRequest;
|
||||
//import cn.hutool.http.HttpResponse;
|
||||
//import cn.hutool.http.HttpStatus;
|
||||
//import com.alibaba.fastjson.JSONObject;
|
||||
//import com.css.znsb.framework.common.pojo.CommonResult;
|
||||
//import com.css.ckts.sso.pojo.vo.thirdparty.GssbTokenVO;
|
||||
//import com.css.ckts.sso.util.AesUtil;
|
||||
//import io.swagger.v3.oas.annotations.Operation;
|
||||
//import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
//import java.net.URLEncoder;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.web.bind.annotation.PostMapping;
|
||||
//import org.springframework.web.bind.annotation.RequestMapping;
|
||||
//import org.springframework.web.bind.annotation.RestController;
|
||||
//
|
||||
//@Tag(name = "对接个税申报系统")
|
||||
//@RestController
|
||||
//@RequestMapping("/gssb")
|
||||
//@Slf4j
|
||||
//public class GssbController {
|
||||
//
|
||||
// //租户ID 平台分配
|
||||
// private static String tenantId = "zrgssy_admin";
|
||||
// //用户名 平台分配
|
||||
// private static String username = "12586555655";
|
||||
// //密码 平台分配
|
||||
// private static String password = "tKlkv*oM";
|
||||
//
|
||||
// // 固定的
|
||||
// private static String authorization = "Basic bWFnaWNjdWJlX2ludm9pY2U6bWFnaWNjdWJlX2ludm9pY2Vfc2VjcmV0";
|
||||
// // 密码AES加密秘钥
|
||||
// private static String aesKey = "O2BEeIv399qHQNhD6aGW8R8DEj4bqHXm";
|
||||
//
|
||||
// // 平台根url
|
||||
// private static String baseUrl = "https://zr.jcsk100.com/api/";
|
||||
//
|
||||
// // token url
|
||||
// private static String tokenUrl = "cube-auth/oauth/token";
|
||||
//
|
||||
//
|
||||
//
|
||||
// @Operation(summary = "获取token", description = "密码模式与个税申报系统对接")
|
||||
// @PostMapping("/getToken")
|
||||
// public CommonResult<GssbTokenVO> getToken(){
|
||||
// final GssbTokenVO gssbTokenVO = new GssbTokenVO();
|
||||
// HttpResponse response = reqSaasToken();
|
||||
// log.info("获取 Saas 授权信息 body:{}", response.body());
|
||||
// if (response.getStatus() == HttpStatus.HTTP_OK) {
|
||||
// String body = response.body();
|
||||
// log.info("Gssb Response->{}",body);
|
||||
// JSONObject responseJson = JSONObject.parseObject(body);
|
||||
// String accessToken = responseJson.getString("access_token");
|
||||
// String refreshToken = responseJson.getString("refresh_token");
|
||||
// gssbTokenVO.setAccessToken(accessToken);
|
||||
// gssbTokenVO.setRefreshToken(refreshToken);
|
||||
// }
|
||||
// gssbTokenVO.setTenantId(tenantId);
|
||||
// return CommonResult.success(gssbTokenVO);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public static HttpResponse reqSaasToken() {
|
||||
// String param = "?tenantId=" + tenantId + "&username=" + username + "&password=" + URLEncoder.encode(encodeAes(SecureUtil.md5(password))) + "&grant_type=password&scope=all&type=account";
|
||||
// String url = baseUrl + tokenUrl + param;
|
||||
//
|
||||
// return HttpRequest.post(url)
|
||||
// .header("Content-Type", "application/json")
|
||||
// .header("Authorization", authorization)
|
||||
// .header("Tenant-Id", tenantId)
|
||||
// .execute();
|
||||
// }
|
||||
//
|
||||
// public static String encodeAes(String txt) {
|
||||
// return AesUtil.encryptToBase64(txt, aesKey);
|
||||
// }
|
||||
//
|
||||
//}
|
||||
@ -0,0 +1,44 @@
|
||||
package com.css.txw.sso.controller.verify;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.css.txw.sso.service.verify.VerifyService;
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
import com.css.ggzc.framework.common.util.servlet.ServletUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@Tag(name = "验证码")
|
||||
@RestController
|
||||
@RequestMapping("/verify")
|
||||
public class VerifyController {
|
||||
|
||||
@Resource
|
||||
private VerifyService verifyService;
|
||||
|
||||
|
||||
@Operation(summary = "获取验证码")
|
||||
@PermitAll
|
||||
@PostMapping("/get")
|
||||
public CommonResult<String> check(HttpServletRequest request){
|
||||
final String remoteId = getRemoteId(request);
|
||||
return verifyService.getVerifyToken(remoteId);
|
||||
}
|
||||
|
||||
public static String getRemoteId(HttpServletRequest request) {
|
||||
String ip = ServletUtils.getClientIP(request);
|
||||
String ua = request.getHeader("user-agent");
|
||||
if (StrUtil.isNotBlank(ip)) {
|
||||
return ip + ua;
|
||||
}
|
||||
return request.getRemoteAddr() + ua;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.css.txw.sso.convert;
|
||||
|
||||
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2AccessTokenDO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginRespVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface AuthConvert {
|
||||
|
||||
AuthConvert INSTANCE = Mappers.getMapper(AuthConvert.class);
|
||||
|
||||
AuthLoginRespVO convert(OAuth2AccessTokenDO bean);
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.css.txw.sso.convert;
|
||||
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import com.css.ggzc.framework.common.util.object.BeanUtils;
|
||||
import com.css.txw.sso.enums.UserTypeEnum;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2AccessTokenDO;
|
||||
import com.css.txw.sso.pojo.dto.session.AccessTokenInfo;
|
||||
import com.css.txw.sso.pojo.vo.oauth2.OAuth2OpenAccessTokenRespVO;
|
||||
import com.css.txw.sso.pojo.vo.oauth2.OAuth2OpenCheckTokenRespVO;
|
||||
import com.css.txw.sso.util.OAuth2Utils;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface OAuth2OpenConvert {
|
||||
|
||||
OAuth2OpenConvert INSTANCE = Mappers.getMapper(OAuth2OpenConvert.class);
|
||||
|
||||
default OAuth2OpenAccessTokenRespVO convert(OAuth2AccessTokenDO bean) {
|
||||
OAuth2OpenAccessTokenRespVO respVO = BeanUtils.toBean(bean, OAuth2OpenAccessTokenRespVO.class);
|
||||
//respVO.setTokenType(SecurityFrameworkUtils.AUTHORIZATION_BEARER.toLowerCase());
|
||||
respVO.setExpiresIn(OAuth2Utils.getExpiresIn(bean.getGqsj()));
|
||||
//respVO.setScope(OAuth2Utils.buildScopeStr(bean.getScopes()));
|
||||
return respVO;
|
||||
}
|
||||
|
||||
default OAuth2OpenCheckTokenRespVO convert2(AccessTokenInfo bean) {
|
||||
OAuth2OpenCheckTokenRespVO respVO = BeanUtils.toBean(bean, OAuth2OpenCheckTokenRespVO.class);
|
||||
respVO.setExp(LocalDateTimeUtil.toEpochMilli(bean.getGqsj()) / 1000L);
|
||||
respVO.setUserType(UserTypeEnum.ADMIN.getValue());
|
||||
return respVO;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.css.txw.sso.enums;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 通用状态枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum CommonStatusEnum {
|
||||
|
||||
ENABLE(0, "开启"),
|
||||
DISABLE(1, "关闭");
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CommonStatusEnum::getStatus).toArray();
|
||||
|
||||
/**
|
||||
* 状态值
|
||||
*/
|
||||
private final Integer status;
|
||||
/**
|
||||
* 状态名
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
public static boolean isEnable(Integer status) {
|
||||
return ObjUtil.equal(ENABLE.status, status);
|
||||
}
|
||||
|
||||
public static boolean isDisable(Integer status) {
|
||||
return ObjUtil.equal(DISABLE.status, status);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.css.txw.sso.enums;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 全局用户类型枚举
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum UserTypeEnum {
|
||||
|
||||
MEMBER(1, "会员"), // 面向 c 端,普通用户
|
||||
ADMIN(2, "管理员"); // 面向 b 端,管理后台
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(UserTypeEnum::getValue).toArray();
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer value;
|
||||
/**
|
||||
* 类型名
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
public static UserTypeEnum valueOf(Integer value) {
|
||||
return ArrayUtil.firstMatch(userType -> userType.getValue().equals(value), UserTypeEnum.values());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
# 定时任务
|
||||
@ -0,0 +1,70 @@
|
||||
package com.css.txw.sso.mapper.oauth2;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.css.ggzc.framework.common.util.gy.GyUtils;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2AccessTokenDO;
|
||||
import com.css.ggzc.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.css.ggzc.framework.mybatis.core.query.QueryWrapperX;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface OAuth2AccessTokenMapper extends BaseMapperX<OAuth2AccessTokenDO> {
|
||||
|
||||
default OAuth2AccessTokenDO selectByAccessToken(String accessToken) {
|
||||
return selectOne(OAuth2AccessTokenDO::getAccessToken, accessToken);
|
||||
}
|
||||
|
||||
default List<OAuth2AccessTokenDO> selectByYhuuid(String yhuuid) {
|
||||
return selectList(OAuth2AccessTokenDO::getYhUuid, yhuuid);
|
||||
}
|
||||
|
||||
default List<OAuth2AccessTokenDO> selectRefreshTokenByAccessTokens(List<String> accessTokens) {
|
||||
QueryWrapperX<OAuth2AccessTokenDO> wrapperX = new QueryWrapperX<>();
|
||||
wrapperX.lambda()
|
||||
// .select(OAuth2AccessTokenDO::getRefreshToken)
|
||||
.in(OAuth2AccessTokenDO::getAccessToken, accessTokens);
|
||||
return selectList(wrapperX);
|
||||
}
|
||||
|
||||
|
||||
default List<OAuth2AccessTokenDO> selectListByRefreshToken(String refreshToken) {
|
||||
return selectList(OAuth2AccessTokenDO::getRefreshToken, refreshToken);
|
||||
}
|
||||
|
||||
default Integer updateCompany(String accessToken,String jguuid){
|
||||
UpdateWrapper<OAuth2AccessTokenDO> updateWrapper = new UpdateWrapper<>();
|
||||
if (!GyUtils.isNull(jguuid)){
|
||||
updateWrapper.set("qyuuid",jguuid);
|
||||
}
|
||||
updateWrapper.set("xgrq", LocalDateTime.now());
|
||||
updateWrapper.set("xgrsfid","SSO");
|
||||
updateWrapper.eq("access_token",accessToken);
|
||||
return update(updateWrapper);
|
||||
}
|
||||
|
||||
default Integer updateGllp(String uuid,String gllp){
|
||||
LambdaUpdateWrapper<OAuth2AccessTokenDO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.set(OAuth2AccessTokenDO::getGllp,gllp)
|
||||
.eq(OAuth2AccessTokenDO::getUuid,uuid);
|
||||
return update(updateWrapper);
|
||||
}
|
||||
|
||||
default Integer deleteByTokens(List<String> tokens){
|
||||
QueryWrapperX<OAuth2AccessTokenDO> wrapperX = new QueryWrapperX<>();
|
||||
wrapperX.lambda().in(OAuth2AccessTokenDO::getAccessToken, tokens);
|
||||
return delete(wrapperX);
|
||||
}
|
||||
|
||||
default Integer updateGllpByTokens(List<String> tokens,String gllp){
|
||||
LambdaUpdateWrapper<OAuth2AccessTokenDO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.set(OAuth2AccessTokenDO::getGllp,gllp)
|
||||
.in(OAuth2AccessTokenDO::getUuid,tokens);
|
||||
return update(updateWrapper);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.css.txw.sso.mapper.oauth2;
|
||||
|
||||
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2ClientDO;
|
||||
import com.css.ggzc.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
|
||||
/**
|
||||
* OAuth2 客户端 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface OAuth2ClientMapper extends BaseMapperX<OAuth2ClientDO> {
|
||||
|
||||
default OAuth2ClientDO selectByClientId(String clientId) {
|
||||
return selectOne(OAuth2ClientDO::getClientid, clientId);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.css.txw.sso.mapper.oauth2;
|
||||
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2CodeDO;
|
||||
import com.css.ggzc.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface OAuth2CodeMapper extends BaseMapperX<OAuth2CodeDO> {
|
||||
|
||||
default OAuth2CodeDO selectByCode(String code) {
|
||||
return selectOne(OAuth2CodeDO::getSqm, code);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.css.txw.sso.mapper.oauth2;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2RefreshTokenDO;
|
||||
import com.css.ggzc.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.css.ggzc.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import com.css.ggzc.framework.mybatis.core.query.QueryWrapperX;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface OAuth2RefreshTokenMapper extends BaseMapperX<OAuth2RefreshTokenDO> {
|
||||
|
||||
default int deleteByRefreshToken(String refreshToken) {
|
||||
return delete(new LambdaQueryWrapperX<OAuth2RefreshTokenDO>()
|
||||
.eq(OAuth2RefreshTokenDO::getRefreshToken, refreshToken));
|
||||
}
|
||||
|
||||
default OAuth2RefreshTokenDO selectByRefreshToken(String refreshToken) {
|
||||
return selectOne(OAuth2RefreshTokenDO::getRefreshToken, refreshToken);
|
||||
}
|
||||
|
||||
default Integer updateJguuid(String refreshToken,String currentJguuid){
|
||||
UpdateWrapper<OAuth2RefreshTokenDO> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.set("jguuid_1",currentJguuid);
|
||||
updateWrapper.set("xgrq", LocalDateTime.now());
|
||||
updateWrapper.set("xgrsfid","SSO");
|
||||
updateWrapper.eq("refresh_token",refreshToken);
|
||||
return update(updateWrapper);
|
||||
}
|
||||
|
||||
default Integer deleteByTokens(List<String> tokens){
|
||||
QueryWrapperX<OAuth2RefreshTokenDO> wrapperX = new QueryWrapperX<>();
|
||||
wrapperX.lambda().in(OAuth2RefreshTokenDO::getRefreshToken, tokens);
|
||||
return delete(wrapperX);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
# mapper 建议按业务分包
|
||||
@ -0,0 +1,71 @@
|
||||
package com.css.txw.sso.pojo.domain.oauth2;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.css.ggzc.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* OAuth2 访问令牌 DO
|
||||
*/
|
||||
@TableName(value = "txw_sso_access_token", autoResultMap = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2AccessTokenDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* UUID||uuid
|
||||
*/
|
||||
@TableId(value = "uuid")
|
||||
private String uuid;
|
||||
|
||||
/**
|
||||
* 用户UUID
|
||||
*/
|
||||
@TableField(value = "yh_uuid")
|
||||
private String yhUuid;
|
||||
|
||||
@TableField(value = "qyuuid")
|
||||
private String qyuuid;
|
||||
|
||||
/**
|
||||
* access_token||access_token
|
||||
*/
|
||||
@TableField(value = "access_token")
|
||||
private String accessToken;
|
||||
|
||||
/**
|
||||
* refresh_token||refresh_token
|
||||
*/
|
||||
@TableField(value = "refresh_token")
|
||||
private String refreshToken;
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
@TableField(value = "clientid")
|
||||
private String clientid;
|
||||
|
||||
/**
|
||||
* 授权内容||授权内容
|
||||
*/
|
||||
@TableField(value = "sqnr")
|
||||
private String sqnr;
|
||||
|
||||
/**
|
||||
* 挂起时间
|
||||
*/
|
||||
@TableField(value = "gqsj")
|
||||
private LocalDateTime gqsj;
|
||||
|
||||
|
||||
@TableField(value = "gllp")
|
||||
private String gllp;
|
||||
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.css.txw.sso.pojo.domain.oauth2;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.css.txw.sso.enums.UserTypeEnum;
|
||||
import com.css.ggzc.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* OAuth2 批准 DO
|
||||
*
|
||||
* 用户在 sso.vue 界面时,记录接受的 scope 列表
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "system_oauth2_approve", autoResultMap = true)
|
||||
@KeySequence("system_oauth2_approve_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class OAuth2ApproveDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,数据库自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*
|
||||
* 枚举 {@link UserTypeEnum}
|
||||
*/
|
||||
private Integer userType;
|
||||
/**
|
||||
* 客户端编号
|
||||
*
|
||||
* 关联 {@link OAuth2ClientDO#getId()}
|
||||
*/
|
||||
private String clientId;
|
||||
/**
|
||||
* 授权范围
|
||||
*/
|
||||
private String scope;
|
||||
/**
|
||||
* 是否接受
|
||||
*
|
||||
* true - 接受
|
||||
* false - 拒绝
|
||||
*/
|
||||
private Boolean approved;
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private LocalDateTime expiresTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
package com.css.txw.sso.pojo.domain.oauth2;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.css.ggzc.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* OAuth2 客户端 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "txw_sso_client", autoResultMap = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2ClientDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* UUID||uuid
|
||||
*/
|
||||
@TableId(value = "uuid")
|
||||
private String uuid;
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
@TableField(value = "clientid")
|
||||
private String clientid;
|
||||
|
||||
/**
|
||||
* 授权密钥||授权密钥
|
||||
*/
|
||||
@TableField(value = "sqmy")
|
||||
private String sqmy;
|
||||
|
||||
/**
|
||||
* 有效标志
|
||||
*/
|
||||
@TableField(value = "yxbz")
|
||||
private String yxbz;
|
||||
|
||||
/**
|
||||
* 访问令牌有效期||访问令牌有效期
|
||||
*/
|
||||
@TableField(value = "fwlpyxq")
|
||||
private String fwlpyxq;
|
||||
|
||||
/**
|
||||
* 刷新令牌有效期||刷新令牌有效期
|
||||
*/
|
||||
@TableField(value = "sxlpyxq")
|
||||
private String sxlpyxq;
|
||||
|
||||
/**
|
||||
* 重定向地址||重定向地址
|
||||
*/
|
||||
@TableField(value = "cdxdz")
|
||||
private String cdxdz;
|
||||
|
||||
/**
|
||||
* 授权内容||授权内容
|
||||
*/
|
||||
@TableField(value = "sqnr")
|
||||
private String sqnr;
|
||||
|
||||
@TableField(value = "sm_1")
|
||||
private String sm1;
|
||||
|
||||
@TableField(value = "dcdz")
|
||||
private String dcdz;
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package com.css.txw.sso.pojo.domain.oauth2;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.css.ggzc.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* OAuth2 授权码 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "txw_sso_code", autoResultMap = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2CodeDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* UUID||uuid
|
||||
*/
|
||||
@TableId(value = "uuid")
|
||||
private String uuid;
|
||||
|
||||
/**
|
||||
* 用户UUID
|
||||
*/
|
||||
@TableField(value = "yh_uuid")
|
||||
private String yhUuid;
|
||||
|
||||
/**
|
||||
* 授权码||授权码
|
||||
*/
|
||||
@TableField(value = "sqm")
|
||||
private String sqm;
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
@TableField(value = "clientid")
|
||||
private String clientid;
|
||||
|
||||
/**
|
||||
* 授权内容||授权内容
|
||||
*/
|
||||
@TableField(value = "sqnr")
|
||||
private String sqnr;
|
||||
|
||||
/**
|
||||
* 挂起时间
|
||||
*/
|
||||
@TableField(value = "gqsj")
|
||||
private LocalDateTime gqsj;
|
||||
|
||||
/**
|
||||
* 重定向地址||重定向地址
|
||||
*/
|
||||
@TableField(value = "cdxdz")
|
||||
private String cdxdz;
|
||||
|
||||
/**
|
||||
* 有效标志
|
||||
*/
|
||||
@TableField(value = "rzzt_1")
|
||||
private String rzzt;
|
||||
|
||||
@TableField(value = "access_token")
|
||||
private String accessToken;
|
||||
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.css.txw.sso.pojo.domain.oauth2;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.css.ggzc.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* OAuth2 刷新令牌
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "txw_sso_refresh_token", autoResultMap = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2RefreshTokenDO extends BaseDO {
|
||||
/**
|
||||
* UUID||uuid
|
||||
*/
|
||||
@TableId(value = "uuid")
|
||||
private String uuid;
|
||||
|
||||
/**
|
||||
* 用户UUID
|
||||
*/
|
||||
@TableField(value = "yh_uuid")
|
||||
private String yhUuid;
|
||||
|
||||
@TableField(value = "qyuuid")
|
||||
private String qyuuid;
|
||||
|
||||
/**
|
||||
* refresh_token||refresh_token
|
||||
*/
|
||||
@TableField(value = "refresh_token")
|
||||
private String refreshToken;
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
@TableField(value = "clientid")
|
||||
private String clientid;
|
||||
|
||||
/**
|
||||
* 授权内容||授权内容
|
||||
*/
|
||||
@TableField(value = "sqnr")
|
||||
private String sqnr;
|
||||
|
||||
/**
|
||||
* 挂起时间
|
||||
*/
|
||||
@TableField(value = "gqsj")
|
||||
private LocalDateTime gqsj;
|
||||
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
# dto包
|
||||
@ -0,0 +1,23 @@
|
||||
package com.css.txw.sso.pojo.dto.session;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class AccessTokenInfo {
|
||||
|
||||
|
||||
private String uuid;
|
||||
private String yhUuid;
|
||||
private String qyuuid;
|
||||
private String accessToken;
|
||||
|
||||
private String refreshToken;
|
||||
private String clientid;
|
||||
private String sqnr;
|
||||
private LocalDateTime gqsj;
|
||||
@Schema(description = "关联令牌")
|
||||
private String gllp;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.css.txw.sso.pojo.dto.session;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SessionInfo {
|
||||
|
||||
private AccessTokenInfo tokenInfo;
|
||||
|
||||
private YhInfo yhxx;
|
||||
private String qyuuid;
|
||||
private String qymc;
|
||||
private String nsrsbh;
|
||||
private String currentYhuuid;
|
||||
private String currentYhlx;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.css.txw.sso.pojo.dto.session;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class YhInfo {
|
||||
|
||||
private String yhuuid;
|
||||
private String zsxm;
|
||||
private String sjhm;
|
||||
private String sfzjlx;
|
||||
private String sfzjhm;
|
||||
private String yhdid;
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
package com.css.txw.sso.pojo.dto.yhxx;
|
||||
|
||||
public class YhxxDTO {
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
package com.css.txw.sso.pojo.vo;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
@Schema(description = "管理后台 - 账号密码登录 Request VO,如果登录并绑定社交用户,需要传递 social 开头的参数")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthLoginReqVO {
|
||||
|
||||
@Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma")
|
||||
@NotEmpty(message = "登录账号不能为空")
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
||||
@JsonProperty("Username")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao")
|
||||
@NotEmpty(message = "密码不能为空")
|
||||
@JsonProperty("Password")
|
||||
private String password;
|
||||
|
||||
// ========== 图片验证码相关 ==========
|
||||
|
||||
@Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,
|
||||
example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
|
||||
@NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
|
||||
@JsonProperty("CaptchaVerification")
|
||||
private String captchaVerification;
|
||||
|
||||
// ========== 绑定社交登录时,需要传递如下参数 ==========
|
||||
|
||||
@Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
//@InEnum(SocialTypeEnum.class)
|
||||
@JsonProperty("SocialType")
|
||||
private Integer socialType;
|
||||
|
||||
@Schema(description = "授权码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@JsonProperty("SocialCode")
|
||||
private String socialCode;
|
||||
|
||||
@Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
|
||||
@JsonProperty("SocialState")
|
||||
private String socialState;
|
||||
|
||||
/**
|
||||
* 开启验证码的 Group
|
||||
*/
|
||||
public interface CodeEnableGroup {}
|
||||
|
||||
@AssertTrue(message = "授权码不能为空")
|
||||
public boolean isSocialCodeValid() {
|
||||
return socialType == null || StrUtil.isNotEmpty(socialCode);
|
||||
}
|
||||
|
||||
@AssertTrue(message = "授权 state 不能为空")
|
||||
public boolean isSocialState() {
|
||||
return socialType == null || StrUtil.isNotEmpty(socialState);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.css.txw.sso.pojo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 登录 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthLoginRespVO {
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "happy")
|
||||
private String accessToken;
|
||||
|
||||
@Schema(description = "刷新令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice")
|
||||
private String refreshToken;
|
||||
|
||||
@Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime expiresTime;
|
||||
|
||||
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String yhlx;
|
||||
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.css.txw.sso.pojo.vo;
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@Data
|
||||
public class DidBindPhoneReqVO {
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
@Schema(description = "验证码")
|
||||
@NotEmpty(message = "验证码不能为空")
|
||||
private String sms;
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
@Schema(description = "手机号码")
|
||||
@NotEmpty(message = "手机号码不能为空")
|
||||
private String sjhm;
|
||||
private String reqId;
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.css.txw.sso.pojo.vo;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 登录用户信息
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class LoginUser {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private String useId;
|
||||
|
||||
/**
|
||||
* 授权范围
|
||||
*/
|
||||
private List<String> scopes;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.css.txw.sso.pojo.vo;
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@Data
|
||||
public class SMSLoginReqVO {
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
@Schema(description = "验证码")
|
||||
@NotEmpty(message = "验证码不能为空")
|
||||
private String sms;
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
@Schema(description = "手机号码")
|
||||
@NotEmpty(message = "手机号码不能为空")
|
||||
private String sjhm;
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.css.txw.sso.pojo.vo;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@Data
|
||||
public class SendMsgReqVO {
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
@Schema(description = "手机号码")
|
||||
@NotEmpty(message = "手机号码不能为空")
|
||||
private String sjhm1;
|
||||
|
||||
@Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "验证码不能为空", groups = AuthLoginReqVO.CodeEnableGroup.class)
|
||||
private String captchaVerification;
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.css.txw.sso.pojo.vo.oauth2;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class LogoutVO {
|
||||
|
||||
@Schema(description = "第三方访问令牌")
|
||||
private String token;
|
||||
@Schema(description = "登出地址")
|
||||
private String dcdz;
|
||||
@Schema(description = "客户端")
|
||||
private String client;
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.css.txw.sso.pojo.vo.oauth2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Schema(description = "管理后台 - 【开放接口】访问令牌 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2OpenAccessTokenRespVO {
|
||||
|
||||
@Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou")
|
||||
@JsonProperty("access_token")
|
||||
private String accessToken;
|
||||
|
||||
@Schema(description = "刷新令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice")
|
||||
@JsonProperty("refresh_token")
|
||||
private String refreshToken;
|
||||
|
||||
@Schema(description = "过期时间,单位:秒", requiredMode = Schema.RequiredMode.REQUIRED, example = "42430")
|
||||
@JsonProperty("expires_in")
|
||||
private Long expiresIn;
|
||||
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.css.txw.sso.pojo.vo.oauth2;
|
||||
|
||||
import com.css.ggzc.framework.common.core.KeyValue;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 授权页的信息 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2OpenAuthorizeInfoRespVO {
|
||||
|
||||
/**
|
||||
* 客户端
|
||||
*/
|
||||
private Client client;
|
||||
|
||||
@Schema(description = "scope 的选中信息,使用 List 保证有序性,Key 是 scope,Value 为是否选中", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<KeyValue<String, Boolean>> scopes;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Client {
|
||||
|
||||
@Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "应用图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
|
||||
private String logo;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.css.txw.sso.pojo.vo.oauth2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 【开放接口】校验令牌 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2OpenCheckTokenRespVO {
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
|
||||
@JsonProperty("user_id")
|
||||
private Long userId;
|
||||
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@JsonProperty("user_type")
|
||||
private Integer userType;
|
||||
@Schema(description = "租户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@JsonProperty("tenant_id")
|
||||
private Long tenantId;
|
||||
|
||||
@Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "car")
|
||||
@JsonProperty("client_id")
|
||||
private String clientId;
|
||||
@Schema(description = "授权范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "user_info")
|
||||
private List<String> scopes;
|
||||
|
||||
@Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou")
|
||||
@JsonProperty("access_token")
|
||||
private String accessToken;
|
||||
|
||||
@Schema(description = "过期时间,时间戳 / 1000,即单位:秒", requiredMode = Schema.RequiredMode.REQUIRED, example = "1593092157")
|
||||
private Long exp;
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package com.css.txw.sso.pojo.vo.oauth2;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - 【开放接口】用户信息对象")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2UserInfoRespVO {
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*/
|
||||
@Schema(description = "用户UUID")
|
||||
private String yhuuid;
|
||||
@Schema(description = "登录账号")
|
||||
private String dlzh;
|
||||
@Schema(description = "真实姓名")
|
||||
private String zsxm;
|
||||
@Schema(description = "手机号码")
|
||||
private String sjhm;
|
||||
private String yhdid;
|
||||
/**
|
||||
* 机构信息
|
||||
*/
|
||||
@Schema(description = "机构UUID")
|
||||
private String qyuuid;
|
||||
@Schema(description = "机构名称")
|
||||
private String qymc;
|
||||
@Schema(description = "社会信用代码")
|
||||
private String shxydm;
|
||||
@Schema(description = "用户类型")
|
||||
private String yhlx;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.css.txw.sso.pojo.vo.oauth2;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class SwjgTreeVO {
|
||||
|
||||
@Schema(description = "code")
|
||||
private String code;
|
||||
@Schema(description = "pcode")
|
||||
private String pcode;
|
||||
@Schema(description = "caption")
|
||||
private String caption;
|
||||
|
||||
private String nsrsbh;
|
||||
|
||||
private String shxydm;
|
||||
|
||||
private String ssjswjgDm;
|
||||
|
||||
private String djxh;
|
||||
|
||||
private String bz;
|
||||
|
||||
private String yxbz;
|
||||
|
||||
private String xzqhszDm;
|
||||
|
||||
private String qydmz;
|
||||
|
||||
private String tbwczt;
|
||||
|
||||
private Date tbwcsj;
|
||||
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
# vo包
|
||||
17
txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/pojo/vo/thirdparty/GssbTokenVO.java
vendored
Normal file
17
txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/pojo/vo/thirdparty/GssbTokenVO.java
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
package com.css.txw.sso.pojo.vo.thirdparty;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "个税申报Token信息")
|
||||
@Data
|
||||
public class GssbTokenVO {
|
||||
|
||||
@Schema(description = "访问令牌")
|
||||
private String accessToken;
|
||||
@Schema(description = "刷新令牌")
|
||||
private String refreshToken;
|
||||
@Schema(description = "租户ID")
|
||||
private String tenantId;
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.css.txw.sso.pojo.vo.thirdparty.did;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DidCallbackExtendInfo {
|
||||
private String requestId;
|
||||
private String authoriserIdCard;
|
||||
private String authoriserIdCardDid;
|
||||
private String authoriserPersonNameDid;
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.css.txw.sso.pojo.vo.thirdparty.did;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DidCredentialSubject {
|
||||
//姓名
|
||||
protected String legalName;
|
||||
//用户id
|
||||
protected String uniscid;
|
||||
//地址
|
||||
protected String dom;
|
||||
protected String licencesn;
|
||||
//进出口企业在平台的名称
|
||||
protected String entname;
|
||||
//测试签发机构
|
||||
protected String issuerName;
|
||||
protected String opscope;
|
||||
protected String opto;
|
||||
//企业实名认证证书
|
||||
protected String certificateName;
|
||||
protected String operator;
|
||||
protected String opfrom;
|
||||
protected String phone;
|
||||
protected DidCallbackExtendInfo extInfo ;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.css.txw.sso.pojo.vo.thirdparty.did;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DidExtendVcsInfo {
|
||||
private String issuer;
|
||||
private String vctId;
|
||||
private String vctVersion ;
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.css.txw.sso.pojo.vo.thirdparty.did;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.chainweaver.did.sdk.model.req.LoginExtend;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DidLoginExtend extends LoginExtend{
|
||||
private Boolean personalSignature;
|
||||
// private String authorizedName;
|
||||
// private String authorizedNameEn;
|
||||
// private String callbackUrl;
|
||||
// private String logo;
|
||||
// private String method;
|
||||
// private String requestId;
|
||||
// private String siteName;
|
||||
private List<DidExtendVcsInfo> vcs;
|
||||
}
|
||||
15
txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/pojo/vo/thirdparty/did/QrCodeInfo.java
vendored
Normal file
15
txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/pojo/vo/thirdparty/did/QrCodeInfo.java
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
package com.css.txw.sso.pojo.vo.thirdparty.did;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class QrCodeInfo {
|
||||
private String url;
|
||||
private String reqId;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.css.txw.sso.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
*
|
||||
* @project qyd-txw
|
||||
* @package com.css.txw.sso.properties
|
||||
* @file SsoProperties.java 创建时间:2025/11/25 20:19
|
||||
* @title 标题(要求能简洁地表达出类的功能和职责)
|
||||
* @description 描述(简要描述类的职责、实现方式、使用注意事项等)
|
||||
* @copyright Copyright (c) 2025 中国软件与技术服务股份有限公司
|
||||
* @company 中国软件与技术服务股份有限公司
|
||||
* @module 模块: 智能申报
|
||||
* @author 商健
|
||||
* @reviewer 审核人
|
||||
* @version 1.0.0
|
||||
* @history 修订历史(历次修订内容、修订人、修订时间等)
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "css.sso")
|
||||
@Data
|
||||
public class SsoProperties {
|
||||
private boolean loginCaptcha = true;
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
# 配置类
|
||||
@ -0,0 +1,10 @@
|
||||
package com.css.txw.sso.service.auth;
|
||||
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginReqVO;
|
||||
|
||||
public interface AdminAuthService {
|
||||
|
||||
String login(AuthLoginReqVO reqVO);
|
||||
|
||||
void logout(String accessToken);
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.css.txw.sso.service.auth;
|
||||
|
||||
import com.css.txw.mhzc.pojo.YhxxbDTO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginRespVO;
|
||||
import com.css.txw.sso.pojo.vo.DidBindPhoneReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SMSLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SendMsgReqVO;
|
||||
import com.css.txw.sso.pojo.vo.oauth2.LogoutVO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
public interface AuthService {
|
||||
|
||||
/**
|
||||
* 验证账号 + 密码。如果通过,则返回用户
|
||||
*
|
||||
* @param username 账号
|
||||
* @param password 密码
|
||||
* @return 用户
|
||||
*/
|
||||
YhxxbDTO authenticate(String username, String password);
|
||||
|
||||
/**
|
||||
* 账号登录
|
||||
*
|
||||
* @param reqVO 登录信息
|
||||
* @return 登录结果
|
||||
*/
|
||||
AuthLoginRespVO login(@Valid AuthLoginReqVO reqVO);
|
||||
|
||||
|
||||
/**
|
||||
* 基于 token 退出登录
|
||||
*
|
||||
* @param token token
|
||||
* @param logType 登出类型
|
||||
*/
|
||||
List<LogoutVO> logout(String token, Integer logType);
|
||||
|
||||
/**
|
||||
* 刷新访问令牌
|
||||
*
|
||||
* @param refreshToken 刷新令牌
|
||||
* @return 登录结果
|
||||
*/
|
||||
AuthLoginRespVO refreshToken(String refreshToken);
|
||||
|
||||
Integer sendMsg(SendMsgReqVO reqVO) throws Exception;
|
||||
|
||||
AuthLoginRespVO loginBySMS(SMSLoginReqVO reqVO);
|
||||
|
||||
AuthLoginRespVO didBindPhone(@Valid DidBindPhoneReqVO reqVO);
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package com.css.txw.sso.service.auth.impl;
|
||||
|
||||
|
||||
import cn.hutool.crypto.digest.MD5;
|
||||
import com.css.txw.mhzc.pojo.HtYhxxbDTO;
|
||||
import com.css.txw.sso.constants.SsoApiConstants;
|
||||
import com.css.txw.sso.constants.SsoConstants;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2AccessTokenDO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginReqVO;
|
||||
import com.css.txw.sso.service.auth.AdminAuthService;
|
||||
import com.css.txw.sso.service.oauth2.OAuth2TokenService;
|
||||
import com.css.txw.sso.service.verify.VerifyService;
|
||||
import com.css.txw.sso.service.yhxx.AccountLockService;
|
||||
import com.css.txw.sso.service.yhxx.YhxxService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.*;
|
||||
import static com.css.ggzc.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
|
||||
@Resource
|
||||
private AccountLockService accountLockService;
|
||||
|
||||
@Resource
|
||||
private VerifyService verifyService;
|
||||
|
||||
@Resource
|
||||
private OAuth2TokenService oauth2TokenService;
|
||||
|
||||
@Resource
|
||||
private YhxxService yhxxService;
|
||||
|
||||
@Override
|
||||
public String login(AuthLoginReqVO reqVO) {
|
||||
final Boolean checked = verifyService.checkVerifyToken(reqVO.getCaptchaVerification());
|
||||
if (!checked){
|
||||
throw exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR);
|
||||
}
|
||||
final HtYhxxbDTO authenticate = authenticate(reqVO.getUsername(), reqVO.getPassword());
|
||||
return createTokenAfterLoginSuccess(authenticate.getYhUuid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout(String accessToken) {
|
||||
// 删除访问令牌
|
||||
oauth2TokenService.removeAccessToken(SsoConstants.CLIENT_DEFAULT,accessToken);
|
||||
}
|
||||
|
||||
private String createTokenAfterLoginSuccess(String userId) {
|
||||
// 创建访问令牌
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAdminAccessToken(userId,"default");
|
||||
return accessTokenDO.getAccessToken();
|
||||
}
|
||||
|
||||
public HtYhxxbDTO authenticate(String username, String password) {
|
||||
HtYhxxbDTO adminInfoByDlzh = yhxxService.getAdminInfoByDlzh(username);
|
||||
|
||||
if (adminInfoByDlzh == null) {
|
||||
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
}
|
||||
|
||||
if (accountLockService.checkLockStatus(adminInfoByDlzh.getYhUuid())){
|
||||
throw exception(AUTH_LOGIN_PASSWORD_ERROR_LOCK);
|
||||
}
|
||||
|
||||
if (!isPasswordMatch(password, adminInfoByDlzh.getDlmm())) {
|
||||
accountLockService.handlePasswordError(adminInfoByDlzh.getYhUuid());
|
||||
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
}
|
||||
if (!"Y".equals(adminInfoByDlzh.getYxbz())){
|
||||
throw exception(AUTH_LOGIN_USER_DISABLED);
|
||||
}
|
||||
|
||||
accountLockService.clearCache(adminInfoByDlzh.getYhUuid());
|
||||
|
||||
return adminInfoByDlzh;
|
||||
}
|
||||
|
||||
private boolean isPasswordMatch(String rawPassword, String encodedPassword) {
|
||||
final String rawPasswordHex = MD5.create().digestHex(rawPassword);
|
||||
return rawPasswordHex.equals(encodedPassword);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,323 @@
|
||||
package com.css.txw.sso.service.auth.impl;
|
||||
|
||||
|
||||
import static com.aliyun.teautil.Common.toJSONString;
|
||||
import static com.css.ggzc.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_LOGIN_CAPTCHA_CODE_ERROR;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_LOGIN_PASSWORD_ERROR_LOCK;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.OAUTH2_LOGIN_SJHM_NOT_EXISTS;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.OAUTH2_LOGIN_SMS_NOT_EXISTS;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.OAUTH2_SJHM_LOCK;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.OAUTH2_SJHM_NOT_EXISTS;
|
||||
import static com.css.txw.sso.constants.SsoConstants.SMS_CLIENT_SIGNNAME;
|
||||
import static com.css.txw.sso.constants.SsoConstants.SMS_TEMPLATE_CODE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.aliyun.dysmsapi20170525.Client;
|
||||
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
|
||||
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
|
||||
import com.css.ggzc.framework.cache.utils.CacheUtils;
|
||||
import com.css.ggzc.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import com.css.ggzc.framework.common.util.gy.GyUtils;
|
||||
import com.css.ggzc.framework.common.util.json.JsonUtils;
|
||||
import com.css.txw.common.pojo.dto.sms.SMSResDTO;
|
||||
import com.css.txw.common.service.ISMService;
|
||||
import com.css.txw.mhzc.pojo.YhxxbDTO;
|
||||
import com.css.txw.sso.configuration.SMSClient;
|
||||
import com.css.txw.sso.controller.thirdparty.DidController;
|
||||
import com.css.txw.sso.convert.AuthConvert;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2AccessTokenDO;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2ClientDO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginRespVO;
|
||||
import com.css.txw.sso.pojo.vo.DidBindPhoneReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SMSLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SendMsgReqVO;
|
||||
import com.css.txw.sso.pojo.vo.oauth2.LogoutVO;
|
||||
import com.css.txw.sso.pojo.vo.thirdparty.did.DidCallbackExtendInfo;
|
||||
import com.css.txw.sso.pojo.vo.thirdparty.did.DidCredentialSubject;
|
||||
import com.css.txw.sso.service.auth.AuthService;
|
||||
import com.css.txw.sso.service.oauth2.OAuth2ClientService;
|
||||
import com.css.txw.sso.service.oauth2.OAuth2TokenService;
|
||||
import com.css.txw.sso.service.verify.VerifyService;
|
||||
import com.css.txw.sso.service.yhxx.AccountLockService;
|
||||
import com.css.txw.sso.service.yhxx.YhxxService;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.crypto.digest.MD5;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AuthServiceImpl implements AuthService {
|
||||
|
||||
@Resource
|
||||
private OAuth2TokenService oauth2TokenService;
|
||||
|
||||
@Resource
|
||||
private VerifyService verifyService;
|
||||
|
||||
@Resource
|
||||
private AccountLockService accountLockService;
|
||||
|
||||
@Resource
|
||||
private OAuth2ClientService clientService;
|
||||
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
@Resource
|
||||
private YhxxService yhxxService;
|
||||
|
||||
@Resource
|
||||
private ISMService smService;
|
||||
|
||||
@Override
|
||||
public YhxxbDTO authenticate(String username, String password) {
|
||||
|
||||
|
||||
YhxxbDTO yhxxbDO = yhxxService.getYhxxByDlzh(username);
|
||||
|
||||
if (yhxxbDO == null) {
|
||||
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
}
|
||||
|
||||
if (accountLockService.checkLockStatus(yhxxbDO.getYhUuid())) {
|
||||
throw exception(AUTH_LOGIN_PASSWORD_ERROR_LOCK);
|
||||
}
|
||||
|
||||
if (!isPasswordMatch(password, yhxxbDO.getDlmm())) {
|
||||
accountLockService.handlePasswordError(yhxxbDO.getYhUuid());
|
||||
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
}
|
||||
|
||||
accountLockService.clearCache(yhxxbDO.getYhUuid());
|
||||
|
||||
return yhxxbDO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthLoginRespVO login(AuthLoginReqVO reqVO) {
|
||||
final Boolean checked = verifyService.checkVerifyToken(reqVO.getCaptchaVerification());
|
||||
if (!checked) {
|
||||
throw exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR);
|
||||
}
|
||||
// 使用账号密码,进行登录
|
||||
YhxxbDTO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
|
||||
return createTokenAfterLoginSuccess(user.getYhUuid());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<LogoutVO> logout(String token, Integer logType) {
|
||||
List<LogoutVO> result = new ArrayList<>();
|
||||
|
||||
final List<OAuth2AccessTokenDO> oAuth2AccessTokenDOS = oauth2TokenService.removeAccessToken(token);
|
||||
if (!GyUtils.isNull(oAuth2AccessTokenDOS)) {
|
||||
oAuth2AccessTokenDOS.forEach(oAuth2AccessTokenDO -> {
|
||||
final String clientid = oAuth2AccessTokenDO.getClientid();
|
||||
if (GyUtils.isNull(clientid)) {
|
||||
log.info("logout方法clientid为空,入参token:{},loginType:{}", token, logType);
|
||||
} else {
|
||||
final OAuth2ClientDO oAuth2ClientFromCache = clientService.getOAuth2ClientFromCache(clientid);
|
||||
final String dcdz = oAuth2ClientFromCache.getDcdz();
|
||||
final LogoutVO logoutVO = new LogoutVO();
|
||||
logoutVO.setToken(token);
|
||||
logoutVO.setDcdz(dcdz);
|
||||
logoutVO.setClient(clientid);
|
||||
result.add(logoutVO);
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthLoginRespVO refreshToken(String refreshToken) {
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, "default");
|
||||
return AuthConvert.INSTANCE.convert(accessTokenDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer sendMsg(SendMsgReqVO reqVO) throws Exception{
|
||||
final Boolean checked = verifyService.checkVerifyToken(reqVO.getCaptchaVerification());
|
||||
if (!checked) {
|
||||
throw exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR);
|
||||
}
|
||||
String sjhm = reqVO.getSjhm1();
|
||||
Boolean aBoolean = stringRedisTemplate.hasKey(formatKeyPhone(sjhm));
|
||||
if (!GyUtils.isNull(aBoolean)&&aBoolean) {
|
||||
throw exception(OAUTH2_SJHM_LOCK);
|
||||
}
|
||||
stringRedisTemplate.opsForValue().set(formatKey(sjhm), sjhm, 1, TimeUnit.MINUTES);
|
||||
// YhxxbDTO yhxx = yhxxService.getYhxxBySjhm(sjhm);
|
||||
// if (GyUtils.isNull(yhxx)) {
|
||||
// throw exception(OAUTH2_SJHM_NOT_EXISTS);
|
||||
// }
|
||||
Boolean aBoolean1 = stringRedisTemplate.hasKey(formatKeyPhone(sjhm));
|
||||
if (GyUtils.isNull(aBoolean1)||!aBoolean1) {
|
||||
throw exception(OAUTH2_LOGIN_SMS_NOT_EXISTS);
|
||||
}
|
||||
String s = CacheUtils.dm2mc("cs_ggzc_xtcs", "SSO_SMS");
|
||||
String sms;
|
||||
if (!GyUtils.isNull(s)){
|
||||
sms = s;
|
||||
}else {
|
||||
sms = RandomStringUtils.randomNumeric(6);
|
||||
Map<String,String> param = new HashMap<>();
|
||||
param.put("code",sms);
|
||||
//发送短信
|
||||
SMSResDTO smsResDTO = smService.sendCaptcha(sjhm, sms);
|
||||
//String resJson = send(sjhm, param);
|
||||
stringRedisTemplate.opsForValue().set(formatKey(sjhm+sms), sjhm, 3, TimeUnit.MINUTES);
|
||||
//Map<String, Object> map = JsonUtils.toMap(resJson);
|
||||
Integer res = StringUtils.isBlank(smsResDTO.getCode()) ? 0 : Integer.parseInt(smsResDTO.getCode());
|
||||
return res;
|
||||
}
|
||||
stringRedisTemplate.opsForValue().set(formatKey(sjhm+sms), sjhm, 3, TimeUnit.MINUTES);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthLoginRespVO loginBySMS(SMSLoginReqVO reqVO) {
|
||||
String sms = reqVO.getSms();
|
||||
String sjhm = reqVO.getSjhm();
|
||||
Boolean aBoolean = stringRedisTemplate.hasKey(formatKey(sjhm+sms));
|
||||
if (GyUtils.isNull(aBoolean)||!aBoolean) {
|
||||
throw exception(OAUTH2_LOGIN_SJHM_NOT_EXISTS);
|
||||
}
|
||||
YhxxbDTO yhxx = yhxxService.getYhxxBySjhm(sjhm);
|
||||
if (GyUtils.isNull(yhxx)) {
|
||||
throw exception(OAUTH2_SJHM_NOT_EXISTS);
|
||||
}
|
||||
return createTokenAfterLoginSuccess(yhxx.getYhUuid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthLoginRespVO didBindPhone(@Valid DidBindPhoneReqVO reqVO) {
|
||||
String sms = reqVO.getSms();
|
||||
String sjhm = reqVO.getSjhm();
|
||||
Boolean aBoolean = stringRedisTemplate.hasKey(formatKey(sjhm+sms));
|
||||
if (GyUtils.isNull(aBoolean)||!aBoolean) {
|
||||
throw exception(OAUTH2_LOGIN_SJHM_NOT_EXISTS);
|
||||
}
|
||||
String reqId =reqVO.getReqId() ;
|
||||
// did用户注册
|
||||
//缓存did 。一次请求对应一个did
|
||||
String tmp = String.format("%s%s", DidController.REQ_USER_DID_PREFIX,reqId);
|
||||
String holderDid =CacheUtils.getCacheData(tmp);
|
||||
if (GyUtils.isNull(holderDid)) {
|
||||
throw exception(GlobalErrorCodeConstants.ERROR.getCode(),"缓存did为空!");
|
||||
}
|
||||
//缓存did数据,为创建账号做准备
|
||||
// DidCredentialSubject cs = JsonUtils.toBean(csjson, DidCredentialSubject.class);
|
||||
tmp = String.format("%s%s", DidController.REQ_USER_DID_DATA_PREFIX,reqId);
|
||||
// CacheUtils.cacheData(tmp, JsonUtils.toJson(cs),timeout);
|
||||
String csJson =CacheUtils.getCacheData(tmp);
|
||||
if (GyUtils.isNull(csJson)) {
|
||||
throw exception(GlobalErrorCodeConstants.ERROR.getCode(),"缓存did数据为空!");
|
||||
}
|
||||
YhxxbDTO existYhxx = yhxxService.getYhxxBySjhm(sjhm);
|
||||
YhxxbDTO yhxx = null;
|
||||
DidCredentialSubject cs =JsonUtils.toBean(csJson,DidCredentialSubject.class );
|
||||
if (GyUtils.isNull(existYhxx)) {
|
||||
yhxx = new YhxxbDTO();
|
||||
yhxx.setYhUuid(IdUtil.fastSimpleUUID());
|
||||
yhxx.setDid(holderDid);
|
||||
yhxx.setSjhm1(sjhm);
|
||||
yhxx.setDlzh(sjhm);
|
||||
if (GyUtils.isNotNull(cs.getLegalName())) {
|
||||
yhxx.setZsxm1(cs.getLegalName());
|
||||
}
|
||||
else if (GyUtils.isNotNull(cs.getEntname())) {
|
||||
yhxx.setZsxm1(cs.getEntname());
|
||||
}
|
||||
else {
|
||||
yhxx.setZsxm1("--");
|
||||
}
|
||||
DidCallbackExtendInfo ext = cs.getExtInfo();
|
||||
if (GyUtils.isNotNull(ext)) {
|
||||
yhxx.setSfzjhm(ext.getAuthoriserIdCard());
|
||||
}
|
||||
yhxx = yhxxService.saveYhxxByDid(yhxx);
|
||||
}
|
||||
else {
|
||||
// yhxx = existYhxx;
|
||||
// yhxx.setDid(holderDid);
|
||||
// yhxxService.updateDid(yhxx);
|
||||
throw exception(GlobalErrorCodeConstants.ERROR.getCode(),"已经存在该手机号的账号信息!");
|
||||
}
|
||||
// 企业认证成功
|
||||
YhxxbDTO qyxx = new YhxxbDTO();
|
||||
qyxx.setQymc(cs.getEntname());
|
||||
qyxx.setNsrsbh(cs.getUniscid());
|
||||
qyxx.setYhUuid(yhxx.getYhUuid());
|
||||
log.info("qyxx:{}",qyxx);
|
||||
qyxx = yhxxService.intQyxxByDid(qyxx);
|
||||
// YhxxbDTO yhxx = yhxxService.getYhxxBySjhm(sjhm);
|
||||
// if (GyUtils.isNull(yhxx)) {
|
||||
// throw exception(OAUTH2_SJHM_NOT_EXISTS);
|
||||
// }
|
||||
return createTokenAfterLoginSuccess(yhxx.getYhUuid());
|
||||
|
||||
}
|
||||
|
||||
private AuthLoginRespVO createTokenAfterLoginSuccess(String userId) {
|
||||
// 创建访问令牌
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, "default", null);
|
||||
// 构建返回结果
|
||||
final AuthLoginRespVO respVO = new AuthLoginRespVO();
|
||||
respVO.setAccessToken(accessTokenDO.getAccessToken());
|
||||
respVO.setRefreshToken(accessTokenDO.getRefreshToken());
|
||||
respVO.setExpiresTime(accessTokenDO.getGqsj());
|
||||
return respVO;
|
||||
}
|
||||
|
||||
private boolean isPasswordMatch(String rawPassword, String encodedPassword) {
|
||||
final String rawPasswordHex = MD5.create().digestHex(rawPassword);
|
||||
return rawPasswordHex.equals(encodedPassword);
|
||||
}
|
||||
|
||||
public String send(String sjhm,Map<String,String> param) throws Exception {
|
||||
// 初始化请求客户端
|
||||
Client client = SMSClient.createClient();
|
||||
|
||||
// 构造请求对象,请填入请求参数值
|
||||
SendSmsRequest sendSmsRequest = new SendSmsRequest()
|
||||
.setPhoneNumbers(sjhm)
|
||||
.setSignName(SMS_CLIENT_SIGNNAME)
|
||||
.setTemplateCode(SMS_TEMPLATE_CODE)
|
||||
.setTemplateParam(JsonUtils.toJson(param));
|
||||
|
||||
// 获取响应对象
|
||||
SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest);
|
||||
|
||||
// 响应包含服务端响应的 body 和 headers
|
||||
return toJSONString(sendSmsResponse);
|
||||
}
|
||||
|
||||
private static String formatKey(String sms) {
|
||||
String VERIFY_TOKEN = "sms_token:%s";
|
||||
return String.format(VERIFY_TOKEN, sms);
|
||||
}
|
||||
|
||||
private static String formatKeyPhone(String phone) {
|
||||
String PHONE_LOCK = "sms_token:%s";
|
||||
return String.format(PHONE_LOCK, phone);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.css.txw.sso.service.oauth2;
|
||||
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2ClientDO;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* OAuth2.0 Client Service 接口
|
||||
*
|
||||
* 从功能上,和 JdbcClientDetailsService 的功能,提供客户端的操作
|
||||
*/
|
||||
public interface OAuth2ClientService {
|
||||
|
||||
|
||||
/**
|
||||
* 获得 OAuth2 客户端,从缓存中
|
||||
*
|
||||
* @param clientId 客户端编号
|
||||
* @return OAuth2 客户端
|
||||
*/
|
||||
OAuth2ClientDO getOAuth2ClientFromCache(String clientId);
|
||||
|
||||
|
||||
/**
|
||||
* 从缓存中,校验客户端是否合法
|
||||
*
|
||||
* @return 客户端
|
||||
*/
|
||||
default OAuth2ClientDO validOAuthClientFromCache(String clientId) {
|
||||
return validOAuthClientFromCache(clientId, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从缓存中,校验客户端是否合法
|
||||
*
|
||||
* 非空时,进行校验
|
||||
*
|
||||
* @param clientId 客户端编号
|
||||
* @param clientSecret 客户端密钥
|
||||
* @param authorizedGrantType 授权方式
|
||||
* @param scopes 授权范围
|
||||
* @param redirectUri 重定向地址
|
||||
* @return 客户端
|
||||
*/
|
||||
OAuth2ClientDO validOAuthClientFromCache(String clientId, String clientSecret, String authorizedGrantType,
|
||||
Collection<String> scopes, String redirectUri);
|
||||
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
package com.css.txw.sso.service.oauth2;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.alibaba.nacos.shaded.com.google.common.annotations.VisibleForTesting;
|
||||
import com.css.txw.sso.constants.ErrorCodeConstants;
|
||||
import com.css.txw.sso.constants.RedisKeyConstants;
|
||||
import com.css.txw.sso.mapper.oauth2.OAuth2ClientMapper;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2ClientDO;
|
||||
import com.css.ggzc.framework.common.exception.ServiceException;
|
||||
import com.css.ggzc.framework.common.util.string.StrUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import static com.css.ggzc.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
||||
/**
|
||||
* OAuth2.0 Client Service 实现类
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class OAuth2ClientServiceImpl implements OAuth2ClientService {
|
||||
|
||||
@Resource
|
||||
private OAuth2ClientMapper oauth2ClientMapper;
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
void validateClientIdExists(String uuid, String clientId) {
|
||||
OAuth2ClientDO client = oauth2ClientMapper.selectByClientId(clientId);
|
||||
if (client == null) {
|
||||
return;
|
||||
}
|
||||
// 如果 id 为空,说明不用比较是否为相同 id 的客户端
|
||||
if (uuid == null) {
|
||||
throw new ServiceException(ErrorCodeConstants.OAUTH2_CLIENT_EXISTS);
|
||||
}
|
||||
if (!client.getUuid().equals(uuid)) {
|
||||
throw exception(ErrorCodeConstants.OAUTH2_CLIENT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames = RedisKeyConstants.OAUTH_CLIENT, key = "#clientId",
|
||||
unless = "#result == null")
|
||||
public OAuth2ClientDO getOAuth2ClientFromCache(String clientId) {
|
||||
return oauth2ClientMapper.selectByClientId(clientId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2ClientDO validOAuthClientFromCache(String clientId, String clientSecret, String authorizedGrantType,
|
||||
Collection<String> scopes, String redirectUri) {
|
||||
// 校验客户端存在、且开启
|
||||
OAuth2ClientDO client = getSelf().getOAuth2ClientFromCache(clientId);
|
||||
if (client == null) {
|
||||
throw exception(ErrorCodeConstants.OAUTH2_CLIENT_NOT_EXISTS);
|
||||
}
|
||||
if (!"Y".equals(client.getYxbz())) {
|
||||
throw exception(ErrorCodeConstants.OAUTH2_CLIENT_DISABLE);
|
||||
}
|
||||
|
||||
// 校验客户端密钥
|
||||
if (StrUtil.isNotEmpty(clientSecret) && ObjectUtil.notEqual(client.getSqmy(), clientSecret)) {
|
||||
throw exception(ErrorCodeConstants.OAUTH2_CLIENT_CLIENT_SECRET_ERROR);
|
||||
}
|
||||
|
||||
// 校验回调地址
|
||||
if (StrUtil.isNotEmpty(redirectUri) && !StrUtils.startWithAny(redirectUri, Arrays.asList(client.getCdxdz().split(";")))) {
|
||||
throw exception(ErrorCodeConstants.OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH, redirectUri);
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得自身的代理对象,解决 AOP 生效问题
|
||||
*
|
||||
* @return 自己
|
||||
*/
|
||||
private OAuth2ClientServiceImpl getSelf() {
|
||||
return SpringUtil.getBean(getClass());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.css.txw.sso.service.oauth2;
|
||||
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2CodeDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OAuth2.0 授权码 Service 接口
|
||||
*
|
||||
* 从功能上,和 Spring Security OAuth 的 JdbcAuthorizationCodeServices 的功能,提供授权码的操作
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface OAuth2CodeService {
|
||||
|
||||
/**
|
||||
* 创建授权码
|
||||
*
|
||||
* 参考 JdbcAuthorizationCodeServices 的 createAuthorizationCode 方法
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param userType 用户类型
|
||||
* @param clientId 客户端编号
|
||||
* @param scopes 授权范围
|
||||
* @param redirectUri 重定向 URI
|
||||
* @param state 状态
|
||||
* @return 授权码的信息
|
||||
*/
|
||||
OAuth2CodeDO createAuthorizationCode(String userId, Integer userType, String clientId,
|
||||
List<String> scopes, String redirectUri, String state);
|
||||
|
||||
/**
|
||||
* 创建授权码
|
||||
* @param clientId 客户端编号
|
||||
* @param redirectUri 重定向 URI
|
||||
* @param state 状态
|
||||
* @return 授权码的信息
|
||||
*/
|
||||
OAuth2CodeDO createAuthorizationCode(String clientId,String redirectUri, String state,String currentToken);
|
||||
|
||||
/**
|
||||
* 使用授权码
|
||||
*
|
||||
* @param code 授权码
|
||||
*/
|
||||
OAuth2CodeDO consumeAuthorizationCode(String code);
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user