|
|
@ -0,0 +1,176 @@ |
|
|
|
/* |
|
|
|
* Author: DONGSK |
|
|
|
* Datetime: 2024/4/25 14:08 |
|
|
|
* Description: 登录服务 |
|
|
|
* History: |
|
|
|
* 作者姓名 --修改时间 --版本号--描述 |
|
|
|
*/ |
|
|
|
package com.digiwin.athena.app.service.basic; |
|
|
|
|
|
|
|
import com.digiwin.athena.app.infra.constant.GlobalConstants; |
|
|
|
import com.digiwin.athena.app.infra.entity.DigiwinSummit; |
|
|
|
import com.digiwin.athena.app.infra.service.DigiwinSummitService; |
|
|
|
import org.apache.commons.codec.binary.Base64; |
|
|
|
import org.slf4j.Logger; |
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
|
import org.springframework.http.*; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
import org.springframework.web.client.RestTemplate; |
|
|
|
|
|
|
|
import javax.annotation.Resource; |
|
|
|
import java.security.KeyPair; |
|
|
|
import java.security.KeyPairGenerator; |
|
|
|
import java.security.NoSuchAlgorithmException; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
/** |
|
|
|
* LoginService |
|
|
|
* 登录服务 |
|
|
|
* |
|
|
|
* @author DONGSK 2024/4/25 14:08 |
|
|
|
* @since 1.0.0 |
|
|
|
*/ |
|
|
|
@Service |
|
|
|
public class LoginService { |
|
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(LoginService.class); |
|
|
|
|
|
|
|
public static final Map<String, DigiwinSummit> loginDataMap = new HashMap<>(); |
|
|
|
|
|
|
|
public static final String mapKey = "%s_%s_%s"; |
|
|
|
|
|
|
|
@Value("${iamApTokenForLogin}") |
|
|
|
private String iamApToken; |
|
|
|
|
|
|
|
@Value("${iamUrl}") |
|
|
|
private String iamURL; |
|
|
|
|
|
|
|
@Resource |
|
|
|
RestTemplate restTemplate; |
|
|
|
|
|
|
|
@Resource |
|
|
|
DigiwinSummitService digiwinSummitService; |
|
|
|
|
|
|
|
public Object login(String userId, String tenantId, String productKey) { |
|
|
|
String uri = iamURL + "/api/iam/v2/identity/login"; |
|
|
|
try { |
|
|
|
initLoginMap(); |
|
|
|
|
|
|
|
String mapKey = String.format(LoginService.mapKey, userId, tenantId, productKey); |
|
|
|
DigiwinSummit digiwinSummit = loginDataMap.get(mapKey); |
|
|
|
|
|
|
|
if (digiwinSummit == null) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
// password |
|
|
|
String password = digiwinSummit.getRefUserPassword(); |
|
|
|
//1.客户端生成公私钥 |
|
|
|
HashMap<String, String> keyMap = getKeyPairMap(); |
|
|
|
String clientPublicKey = keyMap.get("publicKey"); |
|
|
|
String privateKey = keyMap.get("privateKey"); |
|
|
|
//2.获取服务端公钥 |
|
|
|
String serverPublicKey = getServerPublicKey(); |
|
|
|
//3.根据服务端公钥加密客户端公钥 |
|
|
|
String encryptPublicKey = RSAUtils.encryptByPublicKey(clientPublicKey, serverPublicKey); |
|
|
|
//4.获取加密后的AES的key值 |
|
|
|
String encryptAesKey = getAesPublicKey(encryptPublicKey); |
|
|
|
//5.根据客户端私有解密加密的aes的key值 |
|
|
|
String aesKey = new String(RSAUtils.decryptByPrivateKey(Base64.decodeBase64(encryptAesKey), privateKey)); |
|
|
|
String passwordHash = AESUtils.aesEncryptByBase64(password, aesKey); |
|
|
|
//6.登录 |
|
|
|
HttpHeaders headers = new HttpHeaders(); |
|
|
|
headers.setContentType(MediaType.APPLICATION_JSON); |
|
|
|
headers.add(GlobalConstants.HTTP_HEADER_APP_TOKEN_KEY, iamApToken); |
|
|
|
Map<String, String> requestEntity = new HashMap<>(3); |
|
|
|
requestEntity.put("identityType", "token"); |
|
|
|
requestEntity.put("userId", digiwinSummit.getRefUserId()); |
|
|
|
requestEntity.put("passwordHash", passwordHash); |
|
|
|
requestEntity.put("clientEncryptPublicKey", encryptPublicKey); |
|
|
|
HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(requestEntity, headers); |
|
|
|
ResponseEntity<Map> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, Map.class); |
|
|
|
// 切租户 |
|
|
|
return changeTenant(Long.valueOf(digiwinSummit.getRefTenantSid()), response.getBody().get("token").toString()); |
|
|
|
|
|
|
|
} catch (Exception ex) { |
|
|
|
logger.error("登录失败:{}", ex.getMessage(), ex); |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
private Object changeTenant(Long sid, String userToken) { |
|
|
|
String uri = iamURL + "/api/iam/v2/identity/token/refresh/tenant"; |
|
|
|
try { |
|
|
|
HttpHeaders headers = new HttpHeaders(); |
|
|
|
headers.setContentType(MediaType.APPLICATION_JSON); |
|
|
|
headers.add(GlobalConstants.HTTP_HEADER_APP_TOKEN_KEY, iamApToken); |
|
|
|
headers.add(GlobalConstants.HTTP_HEADER_USER_TOKEN_KEY, userToken); |
|
|
|
Map<String, Long> requestEntity = new HashMap<>(); |
|
|
|
requestEntity.put("tenantSid", sid); |
|
|
|
HttpEntity<Map<String, Long>> httpEntity = new HttpEntity<>(requestEntity, headers); |
|
|
|
ResponseEntity<Map> exchange = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, Map.class); |
|
|
|
return exchange.getBody(); |
|
|
|
} catch (Exception e) { |
|
|
|
logger.error("切换失败:{}", e.getMessage(), e); |
|
|
|
} |
|
|
|
return ""; |
|
|
|
} |
|
|
|
|
|
|
|
private HashMap<String, String> getKeyPairMap() throws NoSuchAlgorithmException { |
|
|
|
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); |
|
|
|
generator.initialize(1024); |
|
|
|
KeyPair keyPair = generator.generateKeyPair(); |
|
|
|
String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded())); |
|
|
|
String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded())); |
|
|
|
HashMap<String, String> keyMap = new HashMap<>(); |
|
|
|
keyMap.put("privateKey", privateKey); |
|
|
|
keyMap.put("publicKey", publicKey); |
|
|
|
return keyMap; |
|
|
|
} |
|
|
|
|
|
|
|
private String getServerPublicKey() { |
|
|
|
String uri = iamURL + "/api/iam/v2/identity/publickey"; |
|
|
|
try { |
|
|
|
HttpHeaders headers = new HttpHeaders(); |
|
|
|
headers.setContentType(MediaType.APPLICATION_JSON); |
|
|
|
headers.add(GlobalConstants.HTTP_HEADER_APP_TOKEN_KEY, iamApToken); |
|
|
|
HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(headers); |
|
|
|
ResponseEntity<Map> response = restTemplate.exchange(uri, HttpMethod.GET, httpEntity, Map.class); |
|
|
|
return String.valueOf(response.getBody().get("publicKey")); |
|
|
|
} catch (Exception e) { |
|
|
|
logger.error("登录失败:{}", e.getMessage(), e); |
|
|
|
} |
|
|
|
return ""; |
|
|
|
} |
|
|
|
|
|
|
|
private String getAesPublicKey(String encryptPublicKey) { |
|
|
|
String uri = iamURL + "/api/iam/v2/identity/aeskey"; |
|
|
|
try { |
|
|
|
HttpHeaders headers = new HttpHeaders(); |
|
|
|
headers.setContentType(MediaType.APPLICATION_JSON); |
|
|
|
headers.add(GlobalConstants.HTTP_HEADER_APP_TOKEN_KEY, iamApToken); |
|
|
|
Map<String, String> requestEntity = new HashMap<>(1); |
|
|
|
requestEntity.put("clientEncryptPublicKey", encryptPublicKey); |
|
|
|
HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(requestEntity, headers); |
|
|
|
ResponseEntity<Map> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, Map.class); |
|
|
|
return String.valueOf(response.getBody().get("encryptAesKey")); |
|
|
|
} catch (Exception e) { |
|
|
|
logger.error("登录失败:{}", e.getMessage(), e); |
|
|
|
} |
|
|
|
return ""; |
|
|
|
} |
|
|
|
|
|
|
|
private void initLoginMap() { |
|
|
|
if (loginDataMap.isEmpty()) { |
|
|
|
digiwinSummitService.list().forEach(item -> { |
|
|
|
loginDataMap.put(String.format(mapKey, item.getUserId(), item.getTenantId(), item.getRefProd()), item); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public void clearLoginMap() { |
|
|
|
loginDataMap.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
} |