From a365eb1d7213c5f28c6d2fc2b8f87099d71d17d4 Mon Sep 17 00:00:00 2001 From: 潘志宝 <979469083@qq.com> Date: 星期一, 03 三月 2025 16:09:21 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- /dev/null | 6 - sdk/src/main/resources/META-INF/spring.factories | 1 sdk/src/main/java/com/iailab/sdk/auth/enums/ErrorCodeConstants.java | 16 +++ sdk/src/main/resources/application.yaml | 17 -- sdk/pom.xml | 23 --- sdk/src/main/java/com/iailab/sdk/auth/client/IailabAuthClient.java | 122 +++++++++++++++--------- sdk/src/main/java/com/iailab/sdk/auth/config/SdkAutoConfiguration.java | 28 +++++ sdk/src/main/java/com/iailab/sdk/auth/client/vo/AuthLoginRespVO.java | 24 ++++ sdk/src/main/java/com/iailab/sdk/util/http/IailabHttpUtils.java | 32 +++++- sdk/src/test/java/com/iailab/sdk/IailabClientTest.java | 14 -- sdk/src/main/java/com/iailab/sdk/auth/config/AuthProperties.java | 15 +++ 11 files changed, 198 insertions(+), 100 deletions(-) diff --git a/sdk/pom.xml b/sdk/pom.xml index 7d6080e..316109e 100644 --- a/sdk/pom.xml +++ b/sdk/pom.xml @@ -45,27 +45,12 @@ <groupId>com.iailab</groupId> <artifactId>iailab-common-test</artifactId> </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-validation</artifactId> + </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>--> -<!-- <executions>--> -<!-- <execution>--> -<!-- <goals>--> -<!-- <goal>repackage</goal> <!– 将引入的 jar 打入其中 –>--> -<!-- </goals>--> -<!-- </execution>--> -<!-- </executions>--> -<!-- </plugin>--> -<!-- </plugins>--> -<!-- </build>--> <build> <plugins> <plugin> diff --git a/sdk/src/main/java/com/iailab/sdk/auth/client/IailabAuthClient.java b/sdk/src/main/java/com/iailab/sdk/auth/client/IailabAuthClient.java index 4ba282b..e8d4772 100644 --- a/sdk/src/main/java/com/iailab/sdk/auth/client/IailabAuthClient.java +++ b/sdk/src/main/java/com/iailab/sdk/auth/client/IailabAuthClient.java @@ -1,16 +1,23 @@ package com.iailab.sdk.auth.client; import com.fasterxml.jackson.databind.ObjectMapper; -import com.iailab.sdk.auth.client.dto.TokenDTO; import com.iailab.sdk.auth.client.vo.AuthLoginReqVO; +import com.iailab.sdk.auth.config.AuthProperties; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.util.Assert; +import org.springframework.util.Base64Utils; +import org.springframework.util.ObjectUtils; import org.springframework.web.client.RestTemplate; +import java.nio.charset.StandardCharsets; import java.util.*; + +import static com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; +import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.iailab.sdk.auth.enums.ErrorCodeConstants.*; /** * @author Houzhongjian @@ -21,48 +28,42 @@ @Service public class IailabAuthClient { - /** - * 平台地址 - */ - public static String BASE_URL = "http://172.16.8.100:48080/admin-api"; - - /** - * 租户编号 - */ - public static String TENANT_ID = "1"; - private static final RestTemplate restTemplate = new RestTemplate(); + + private static AuthProperties authProperties; + + public static void setAuthProperties(AuthProperties properties) { + authProperties = properties; + } + + private static final String GRAND_TYPE = "password"; + + private static final String SCOPE = "user.read user.write"; + + // 鉴权token + public static String accessToken; + // 刷新token + public static String refreshToken; + // 鉴权token过期时间 + public static Long expireTime; /** * 用户名密码方式获取平台token */ - public static synchronized TokenDTO login(AuthLoginReqVO loginReqVO) throws Exception { + public static synchronized void authenticate() throws Exception { System.out.println("登录获取平台token"); - ObjectMapper objectMapper = new ObjectMapper(); - String paramString = objectMapper.writeValueAsString(loginReqVO); // 1.1 构建请求头 HttpHeaders headers = new HttpHeaders(); addClientHeader(headers); headers.setContentType(MediaType.APPLICATION_JSON_UTF8); // 1.2 构建authenticate请求URL - String authenticateUrl = BASE_URL + "/system/auth/login"; - // 2. 执行请求 - ResponseEntity<Map<String, Object>> exchange = restTemplate.exchange( - authenticateUrl, - HttpMethod.POST, - new HttpEntity<>(paramString, headers), - new ParameterizedTypeReference<Map<String, Object>>() { - }); - return handleResponse(exchange); - } - - public static synchronized TokenDTO refreshToken(String refreshToken) { - System.out.println("刷新token"); - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - addClientHeader(headers); // 1.2 构建authenticate请求URL - String authenticateUrl = BASE_URL + "/system/auth/refresh-token?refreshToken=" + refreshToken; + String authenticateUrl = authProperties.getBaseUrl() + "/system/oauth2/token?" + // 密码模式的参数 + + "&grant_type=" + GRAND_TYPE + + "&username=" + authProperties.getUsername() + + "&password=" + authProperties.getPassword() + + "&scope=" + SCOPE; // 2. 执行请求 ResponseEntity<Map<String, Object>> exchange = restTemplate.exchange( authenticateUrl, @@ -70,24 +71,55 @@ new HttpEntity<>(headers), new ParameterizedTypeReference<Map<String, Object>>() { }); - return handleResponse(exchange); + Map<String, Object> authMap = exchange.getBody(); + if(AUTH_BAD_CREDENTIALS.getCode().equals(authMap.get("code"))) { + throw exception(AUTH_BAD_CREDENTIALS); + } else if(AUTH_LOGIN_BAD_CREDENTIALS.getCode().equals(authMap.get("code"))) { + throw exception(AUTH_LOGIN_BAD_CREDENTIALS); + } + Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); + accessToken = authMap.get("access_token").toString(); + refreshToken = authMap.get("refresh_token").toString(); + expireTime = Long.valueOf(authMap.get("expires_time").toString()); + } + + public static synchronized void refreshToken() throws Exception { + System.out.println("刷新token"); + // 1.1 构建请求头 + HttpHeaders headers = new HttpHeaders(); + addClientHeader(headers); + // 1.2 构建authenticate请求URL + String authenticateUrl = authProperties.getBaseUrl() + "/system/auth/client-refresh-token?refreshToken=" + refreshToken+ "&clientId=" + authProperties.getClientId(); + // 2. 执行请求 + ResponseEntity<Map<String, Object>> exchange = restTemplate.exchange( + authenticateUrl, + HttpMethod.POST, + new HttpEntity<>(headers), + new ParameterizedTypeReference<Map<String, Object>>() { + }); + Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); + Map<String, Object> authMap = exchange.getBody(); + //刷新token过期,重新获取token + if (!ObjectUtils.isEmpty(authMap.get("code"))) { + Integer code = Integer.valueOf(authMap.get("code").toString()); + if (code == 401) { + authenticate(); + } else { + throw exception(AUTH_REFRESH_TOKEN_ERROR); + } + } else { + accessToken = authMap.get("access_token").toString(); + expireTime = Long.valueOf(authMap.get("expires_time").toString()); + } } private static void addClientHeader(HttpHeaders headers) { + // client 拼接,需要 BASE64 编码 + String client = authProperties.getClientId() + ":" + authProperties.getClientSecret(); + client = Base64Utils.encodeToString(client.getBytes(StandardCharsets.UTF_8)); + headers.add("Authorization", "Basic " + client); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("tenant-id", TENANT_ID); + headers.set("tenant-id", authProperties.getTenantId()); } - // 统一处理响应 - private static <T> TokenDTO handleResponse(ResponseEntity<T> response) { - Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - System.out.println(response); - TokenDTO authTokenDTO = new TokenDTO(); - Map<String, Object> authMap = (Map<String, Object>)response.getBody(); - Map<String, Object> tokenData = (Map<String, Object>)authMap.get("data"); - authTokenDTO.setAccessToken(tokenData.get("accessToken").toString()); - authTokenDTO.setRefreshToken(tokenData.get("refreshToken").toString()); - authTokenDTO.setExpiresTime(Long.valueOf(tokenData.get("expiresTime").toString())); - return authTokenDTO; - } } \ No newline at end of file diff --git a/sdk/src/main/java/com/iailab/sdk/auth/client/vo/AuthLoginRespVO.java b/sdk/src/main/java/com/iailab/sdk/auth/client/vo/AuthLoginRespVO.java new file mode 100644 index 0000000..d72d61d --- /dev/null +++ b/sdk/src/main/java/com/iailab/sdk/auth/client/vo/AuthLoginRespVO.java @@ -0,0 +1,24 @@ +package com.iailab.sdk.auth.client.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AuthLoginRespVO { + + private Long userId; + + private String accessToken; + + private String refreshToken; + + private LocalDateTime expiresTime; + +} diff --git a/sdk/src/main/java/com/iailab/sdk/auth/config/AuthProperties.java b/sdk/src/main/java/com/iailab/sdk/auth/config/AuthProperties.java new file mode 100644 index 0000000..08a8d60 --- /dev/null +++ b/sdk/src/main/java/com/iailab/sdk/auth/config/AuthProperties.java @@ -0,0 +1,15 @@ +package com.iailab.sdk.auth.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "iailab.token") +@Data +public class AuthProperties { + private String baseUrl; + private String tenantId; + private String username; + private String password; + private String clientId; + private String clientSecret; +} \ No newline at end of file diff --git a/sdk/src/main/java/com/iailab/sdk/auth/config/SdkAutoConfiguration.java b/sdk/src/main/java/com/iailab/sdk/auth/config/SdkAutoConfiguration.java new file mode 100644 index 0000000..b9cf3fe --- /dev/null +++ b/sdk/src/main/java/com/iailab/sdk/auth/config/SdkAutoConfiguration.java @@ -0,0 +1,28 @@ +package com.iailab.sdk.auth.config; + +import com.iailab.sdk.auth.client.IailabAuthClient; +import com.iailab.sdk.util.http.IailabHttpUtils; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; + + +/** + * SDK配置文件 + */ +@Configuration +@EnableConfigurationProperties(AuthProperties.class) +public class SdkAutoConfiguration { + private final AuthProperties authProperties; + + public SdkAutoConfiguration(AuthProperties authProperties) { + this.authProperties = authProperties; + } + + @PostConstruct + public void init() { + IailabAuthClient.setAuthProperties(authProperties); + IailabHttpUtils.setAuthProperties(authProperties); + } +} diff --git a/sdk/src/main/java/com/iailab/sdk/auth/config/SdkConfiguration.java b/sdk/src/main/java/com/iailab/sdk/auth/config/SdkConfiguration.java deleted file mode 100644 index 6b7d958..0000000 --- a/sdk/src/main/java/com/iailab/sdk/auth/config/SdkConfiguration.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.iailab.sdk.auth.config; - -import org.springframework.context.annotation.Configuration; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -/** - * SDK配置文件 - */ -@Configuration -public class SdkConfiguration { - - private String baseUrl; - - public String getTenantId() { - return tenantId; - } - - private String tenantId; - - public static SdkConfiguration load() { - SdkConfiguration config = new SdkConfiguration(); - - try(InputStream is = SdkConfiguration.class.getResourceAsStream("/application.yaml")) { - Properties props = new Properties(); - props.load(is); - config.baseUrl = props.getProperty("base-url"); - config.tenantId = props.getProperty("tenant-id"); - } catch (IOException e) { - // 处理异常或使用默认值 - } - - if(config.baseUrl == null) { - throw new IllegalStateException("BaseUrl must be configured"); - } - if(config.tenantId == null) { - throw new IllegalStateException("TenantId must be configured"); - } - - return config; - } - - public String getBaseUrl() { - return baseUrl; - } -} diff --git a/sdk/src/main/java/com/iailab/sdk/auth/enums/ErrorCodeConstants.java b/sdk/src/main/java/com/iailab/sdk/auth/enums/ErrorCodeConstants.java new file mode 100644 index 0000000..46af76a --- /dev/null +++ b/sdk/src/main/java/com/iailab/sdk/auth/enums/ErrorCodeConstants.java @@ -0,0 +1,16 @@ +package com.iailab.sdk.auth.enums; + +import com.iailab.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(1_002_000_000, "登录失败,账号密码不正确"); + ErrorCode AUTH_BAD_CREDENTIALS = new ErrorCode(400, "client_id 或 client_secret 未正确传递"); + ErrorCode AUTH_REFRESH_TOKEN_ERROR = new ErrorCode(1_002_000_001, "刷新token失败"); +} diff --git a/sdk/src/main/java/com/iailab/sdk/util/http/IailabHttpUtils.java b/sdk/src/main/java/com/iailab/sdk/util/http/IailabHttpUtils.java index b5cf6c4..9c1eda9 100644 --- a/sdk/src/main/java/com/iailab/sdk/util/http/IailabHttpUtils.java +++ b/sdk/src/main/java/com/iailab/sdk/util/http/IailabHttpUtils.java @@ -1,6 +1,7 @@ package com.iailab.sdk.util.http; import com.iailab.sdk.auth.client.IailabAuthClient; +import com.iailab.sdk.auth.config.AuthProperties; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; @@ -8,6 +9,7 @@ import org.apache.http.entity.StringEntity; import org.apache.http.util.EntityUtils; import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; @@ -16,6 +18,12 @@ public class IailabHttpUtils { + private static AuthProperties authProperties; + + public static void setAuthProperties(AuthProperties properties) { + authProperties = properties; + } + /** * * @param url @@ -23,8 +31,9 @@ * @param charset * @return */ - public static String doGet(String url, Map<String, String> map, String charset, String accessToken) { + public static String doGet(String url, Map<String, String> map, String charset) throws Exception { System.out.println("start doGet url: " + url); + checkToken(); org.apache.http.client.HttpClient httpClient = null; HttpGet httpGet = null; String result = null; @@ -51,8 +60,9 @@ //设置参数 httpGet.addHeader("Accept", "application/json"); httpGet.addHeader("Content-Type", "application/json;charset=UTF-8"); - httpGet.addHeader("Authorization", "Bearer " + accessToken); - httpGet.addHeader("Tenant-Id", String.valueOf(IailabAuthClient.TENANT_ID)); + httpGet.addHeader("Authorization", "Bearer " + IailabAuthClient.accessToken); + httpGet.addHeader("Tenant-Id", String.valueOf(authProperties.getTenantId())); + HttpResponse response = httpClient.execute(httpGet); if (response != null) { HttpEntity resEntity = response.getEntity(); @@ -73,8 +83,9 @@ * @param charset * @return */ - public static String doPost(String url, String json, String charset, String accessToken) { + public static String doPost(String url, String json, String charset) throws Exception { System.out.println("start doPost url: " + url); + checkToken(); org.apache.http.client.HttpClient httpClient = null; HttpPost httpPost = null; String result = null; @@ -84,8 +95,8 @@ //设置参数 httpPost.addHeader("Accept", "application/json"); httpPost.addHeader("Content-Type", "application/json;charset=UTF-8"); - httpPost.addHeader("Authorization", "Bearer " + accessToken); - httpPost.addHeader("Tenant-Id", String.valueOf(IailabAuthClient.TENANT_ID)); + httpPost.addHeader("Authorization", "Bearer " + IailabAuthClient.accessToken); + httpPost.addHeader("Tenant-Id", String.valueOf(authProperties.getTenantId())); StringEntity stringEntity = new StringEntity(json); stringEntity.setContentEncoding("UTF-8"); stringEntity.setContentType("application/json"); @@ -103,4 +114,13 @@ return result; } + private static void checkToken() throws Exception { + //第一次请求或者token过期,需要重新获取token + if(ObjectUtils.isEmpty(IailabAuthClient.accessToken)) { + IailabAuthClient.authenticate(); + } else if (IailabAuthClient.expireTime < System.currentTimeMillis() / 1000) { + IailabAuthClient.refreshToken(); + } + } + } diff --git a/sdk/src/main/resources/META-INF/spring.factories b/sdk/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..4ac7d96 --- /dev/null +++ b/sdk/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.iailab.sdk.auth.config.SdkAutoConfiguration \ No newline at end of file diff --git a/sdk/src/main/resources/application-dev.yaml b/sdk/src/main/resources/application-dev.yaml deleted file mode 100644 index 0a38e15..0000000 --- a/sdk/src/main/resources/application-dev.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- #################### SDK相关配置 #################### - -iailab: - auth: - base-url: http://172.16.8.100:48080/admin-api - tenant-id: 1 \ No newline at end of file diff --git a/sdk/src/main/resources/application.yaml b/sdk/src/main/resources/application.yaml index 946abfd..6adf8aa 100644 --- a/sdk/src/main/resources/application.yaml +++ b/sdk/src/main/resources/application.yaml @@ -1,13 +1,4 @@ -spring: - application: - name: sdk - - profiles: - active: dev - -iailab: - auth: - base-url: http://172.16.8.100:48080/admin-api - tenant-id: 1 - - +#spring: +# application: +# name: sdk +# diff --git a/sdk/src/test/java/com/iailab/sdk/IailabClientTest.java b/sdk/src/test/java/com/iailab/sdk/IailabClientTest.java index 7f15846..6ca996c 100644 --- a/sdk/src/test/java/com/iailab/sdk/IailabClientTest.java +++ b/sdk/src/test/java/com/iailab/sdk/IailabClientTest.java @@ -18,21 +18,13 @@ @Test public void testLogin() throws Exception { - // 准备参数 - AuthLoginReqVO authLoginReqVO = new AuthLoginReqVO(); - authLoginReqVO.setUsername("sysadmin"); - authLoginReqVO.setPassword("iailab2019"); - TokenDTO login = IailabAuthClient.login(authLoginReqVO); - System.out.println(login.getAccessToken()); - System.out.println(login.getRefreshToken()); + IailabAuthClient.authenticate(); } @Test - public void testRefreshToken() { + public void testRefreshToken() throws Exception { // 准备参数 - String refreshToken = "1d62031562364ed29d6d414fea97e2dd"; - TokenDTO tokenDTO = IailabAuthClient.refreshToken(refreshToken); - System.out.println(tokenDTO); + IailabAuthClient.refreshToken(); } -- Gitblit v1.9.3