diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml
new file mode 100644
index 0000000..0508403
--- /dev/null
+++ b/.idea/checkstyle-idea.xml
@@ -0,0 +1,14 @@
+
+
+
+ 10.5.0
+ JavaOnly
+ true
+
+
+
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..d35bcbc
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/eclipseCodeFormatter.xml b/.idea/eclipseCodeFormatter.xml
new file mode 100644
index 0000000..d868994
--- /dev/null
+++ b/.idea/eclipseCodeFormatter.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..93028ca
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..a2e2b69
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..d5cd614
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/kqapi/src/main/java/com/ningdatech/kqapi/sso/controller/SsoController.java b/kqapi/src/main/java/com/ningdatech/kqapi/sso/controller/SsoController.java
new file mode 100644
index 0000000..913aa00
--- /dev/null
+++ b/kqapi/src/main/java/com/ningdatech/kqapi/sso/controller/SsoController.java
@@ -0,0 +1,36 @@
+package com.ningdatech.kqapi.sso.controller;
+
+import com.ningdatech.kqapi.sso.manage.SsoManage;
+import com.ningdatech.kqapi.sso.model.dto.ReqSsoDTO;
+import com.ningdatech.kqapi.sso.model.vo.SsoTokenVO;
+import com.ningdatech.kqapi.sso.model.vo.SsoUserInfoVO;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+/**
+ * @author CMM
+ * @since 2024/04/07 11:15
+ */
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("/api/v1/sso/")
+@RequiredArgsConstructor
+public class SsoController {
+
+ private final SsoManage ssoManage;
+
+ @PostMapping ("/token")
+ public SsoTokenVO getToken(@Valid @RequestBody ReqSsoDTO reqSsoDTO) {
+ return ssoManage.getToken(reqSsoDTO);
+ }
+
+ @PostMapping ("/getUserInfo")
+ public SsoUserInfoVO getUserInfo(@Valid @RequestBody ReqSsoDTO reqSsoDTO) {
+ return ssoManage.getUserInfo(reqSsoDTO);
+ }
+}
diff --git a/kqapi/src/main/java/com/ningdatech/kqapi/sso/manage/SsoManage.java b/kqapi/src/main/java/com/ningdatech/kqapi/sso/manage/SsoManage.java
new file mode 100644
index 0000000..d2b3450
--- /dev/null
+++ b/kqapi/src/main/java/com/ningdatech/kqapi/sso/manage/SsoManage.java
@@ -0,0 +1,86 @@
+package com.ningdatech.kqapi.sso.manage;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+
+import com.ningdatech.kqapi.common.exception.BizException;
+import com.ningdatech.kqapi.sso.model.dto.ReqSsoDTO;
+import com.ningdatech.kqapi.sso.model.vo.SsoTokenVO;
+import com.ningdatech.kqapi.sso.model.vo.SsoUserInfoVO;
+import com.ningdatech.kqapi.sso.utils.HmacAuthUtil;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+
+/**
+ * @author CMM
+ * @since 2024/04/07 11:17
+ */
+@Component
+@Slf4j
+@RequiredArgsConstructor
+public class SsoManage {
+
+ @Value("${sso.token.internet-url}")
+ private String tokenUrl;
+
+ @Value("${sso.user-info.internet-url}")
+ private String userInfoUrl;
+
+ @Value("${sso.access-key}")
+ private String accessKey;
+
+ @Value("${sso.secret-key}")
+ private String secretKey;
+
+ @Value("${sso.app-id}")
+ private String appId;
+
+ private final RestTemplate restTemplate;
+
+ /**
+ * 基于单点登录票据换取请求 token
+ *
+ * @param reqSsoDTO \
+ * @return SsoTokenVO
+ */
+ public SsoTokenVO getToken(ReqSsoDTO reqSsoDTO) {
+ String ticketId = reqSsoDTO.getTicketId();
+ if (StringUtils.isBlank(ticketId)){
+ throw new BizException("登录票据不能为空!");
+ }
+ Map header = HmacAuthUtil.generateHeader(tokenUrl, "POST", accessKey, secretKey);
+ MultiValueMap multiValueMap = HmacAuthUtil.convertToMultiValueMap(header);
+ reqSsoDTO.setAppId(appId);
+ HttpEntity