From ca5436abd755ad04735810d9e146c7dcd1158663 Mon Sep 17 00:00:00 2001
From: liriming <1343021927@qq.com>
Date: 星期二, 25 三月 2025 11:05:32 +0800
Subject: [PATCH] 认证

---
 ansteel-biz/src/main/java/com/iailab/module/ansteel/config/FeignTokenInterceptor.java |   43 ++++++++++
 ansteel-biz/src/main/java/com/iailab/module/ansteel/util/token/IailabClient.java      |  145 ++++++++++++++++++++++++++++++++++++
 2 files changed, 188 insertions(+), 0 deletions(-)

diff --git a/ansteel-biz/src/main/java/com/iailab/module/ansteel/config/FeignTokenInterceptor.java b/ansteel-biz/src/main/java/com/iailab/module/ansteel/config/FeignTokenInterceptor.java
new file mode 100644
index 0000000..2e45c51
--- /dev/null
+++ b/ansteel-biz/src/main/java/com/iailab/module/ansteel/config/FeignTokenInterceptor.java
@@ -0,0 +1,43 @@
+package com.iailab.module.ansteel.config;
+
+import com.iailab.module.ansteel.util.token.IailabClient;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+@Configuration
+public class FeignTokenInterceptor implements RequestInterceptor {
+
+    @Autowired
+    private IailabClient iailabClient;
+
+    @Override
+    public void apply(RequestTemplate requestTemplate) {
+        // 从当前请求上下文中获取Token
+        String token = getTokenFromCurrentRequest();
+
+        if (token == null) {
+            // 如果没有获取到Token,从system-server中获取token
+            token = iailabClient.getToken();
+            if (token!= null) {
+                requestTemplate.header(HttpHeaders.AUTHORIZATION, token);
+            }
+            Long tenantId = iailabClient.getTenantId();
+            if (tenantId != null) {
+                requestTemplate.header("tenant-id", String.valueOf(tenantId));
+            }
+        }
+    }
+
+    private String getTokenFromCurrentRequest() {
+        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        if (attributes!= null) {
+            return attributes.getRequest().getHeader(HttpHeaders.AUTHORIZATION);
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/ansteel-biz/src/main/java/com/iailab/module/ansteel/util/token/IailabClient.java b/ansteel-biz/src/main/java/com/iailab/module/ansteel/util/token/IailabClient.java
new file mode 100644
index 0000000..974c1cd
--- /dev/null
+++ b/ansteel-biz/src/main/java/com/iailab/module/ansteel/util/token/IailabClient.java
@@ -0,0 +1,145 @@
+package com.iailab.module.ansteel.util.token;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+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.Map;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月21日
+ */
+@Slf4j
+@Component
+public class IailabClient {
+
+    /**
+     * 平台地址
+     */
+    @Value("${iailab.token.base-url}")
+    private String BASE_URL;
+
+    /**
+     * 租户编号
+     */
+    @Value("${iailab.token.tenant-id}")
+    private String TENANT_ID;
+
+    /**
+     * 客户端信息
+     */
+    @Value("${iailab.token.client-id}")
+    private String CLIENT_ID;
+    @Value("${iailab.token.client-secret}")
+    private String CLIENT_SECRET;
+    @Value("${iailab.token.username}")
+    private String USERNAME;
+    @Value("${iailab.token.password}")
+    private String PASSWORD;
+    private static final String GRAND_TYPE = "password";
+    private static final String SCOPE = "user.read user.write";
+
+
+    private static final RestTemplate restTemplate = new RestTemplate();
+
+    // 鉴权token
+    private String accessToken;
+    // 刷新token
+    private String refreshToken;
+    // 鉴权token过期时间
+    private Long expireTime;
+
+    /**
+     * 用户名密码方式获取平台token
+     */
+    private synchronized void authenticate() {
+        log.info("获取平台token");
+        // 1.1 构建请求头
+        HttpHeaders headers = new HttpHeaders();
+        addClientHeader(headers);
+        // 1.2 构建authenticate请求URL
+        String authenticateUrl = BASE_URL + "/oauth2/token?"
+                // 密码模式的参数
+                + "grant_type=" + GRAND_TYPE
+                + "&username=" + USERNAME
+                + "&password=" + PASSWORD
+                + "&scope=" + SCOPE;
+        // 2. 执行请求
+        ResponseEntity<Map<String, Object>> exchange = restTemplate.exchange(
+                authenticateUrl,
+                HttpMethod.POST,
+                new org.springframework.http.HttpEntity<>(headers),
+                new ParameterizedTypeReference<Map<String, Object>>() {
+                });
+        Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");
+        log.info(exchange.toString());
+        Map<String, Object> authMap = exchange.getBody();
+        accessToken = authMap.get("access_token").toString();
+        refreshToken = authMap.get("refresh_token").toString();
+        expireTime = Long.valueOf(authMap.get("expires_time").toString());
+    }
+
+    private synchronized void refreshToken() {
+        log.info("刷新token");
+        // 1.1 构建请求头
+        HttpHeaders headers = new HttpHeaders();
+        addClientHeader(headers);
+        // 1.2 构建authenticate请求URL
+        String authenticateUrl = BASE_URL + "/system/auth/client-refresh-token?refreshToken=" + refreshToken
+                + "&clientId=" + CLIENT_ID;
+        // 2. 执行请求
+        ResponseEntity<Map<String, Object>> exchange = restTemplate.exchange(
+                authenticateUrl,
+                HttpMethod.POST,
+                new org.springframework.http.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 {
+            accessToken = authMap.get("access_token").toString();
+            expireTime = Long.valueOf(authMap.get("expires_time").toString());
+        }
+    }
+
+    private void addClientHeader(HttpHeaders headers) {
+        // client 拼接,需要 BASE64 编码
+        String client = CLIENT_ID + ":" + CLIENT_SECRET;
+        client = Base64Utils.encodeToString(client.getBytes(StandardCharsets.UTF_8));
+        headers.add("Authorization", "Basic " + client);
+        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+        headers.set("tenant-id", getTenantId().toString());
+    }
+
+    public String getToken() {
+        //第一次请求或者token过期,需要重新获取token
+        if(ObjectUtils.isEmpty(accessToken)) {
+            authenticate();
+        } else if (expireTime < System.currentTimeMillis() / 1000) {
+            refreshToken();
+        }
+        
+        return accessToken;
+    }
+    public Long getTenantId() {
+        return Long.valueOf(TENANT_ID);
+    }
+}
\ No newline at end of file

--
Gitblit v1.9.3