package com.iailab.module.shasteel.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> exchange = restTemplate.exchange( authenticateUrl, HttpMethod.POST, new org.springframework.http.HttpEntity<>(headers), new ParameterizedTypeReference>() { }); Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); log.info(exchange.toString()); Map 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> exchange = restTemplate.exchange( authenticateUrl, HttpMethod.POST, new org.springframework.http.HttpEntity<>(headers), new ParameterizedTypeReference>() { }); Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); Map 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); } }