@ -0,0 +1,103 @@ | |||||
package com.digiwin.athena.app.infra.constant; | |||||
/** | |||||
* 全局常量 | |||||
* | |||||
* @author fobgochod | |||||
* @date 2020/4/27 | |||||
*/ | |||||
public class GlobalConstants { | |||||
/** | |||||
* 访问凭证 | |||||
*/ | |||||
public static final String DIGI_MIDDLEWARE_AUTH_ACCESS = "digi-middleware-auth-access"; | |||||
/** | |||||
* 在HttpHeader中传递的User信息 | |||||
*/ | |||||
public static final String AUTH_USER = "digi-middleware-auth-user-data"; | |||||
/** | |||||
* 在HttpHeader中传递的App信息 | |||||
*/ | |||||
public static final String APP = "digi-middleware-auth-app-data"; | |||||
/** | |||||
* 在HttpHeader中传递的OTA Token信息 | |||||
*/ | |||||
public static final String HTTP_HEADER_OTA_TOKEN_KEY = "digi-middleware-auth-ota"; | |||||
/** | |||||
* 在HttpHeader中传递的Access Token信息 | |||||
*/ | |||||
public static final String HTTP_HEADER_ACCESS_TOKEN_KEY = "digi-middleware-auth-access"; | |||||
/** | |||||
* 在HttpHeader中传递的User Token信息 | |||||
*/ | |||||
public static final String HTTP_HEADER_USER_TOKEN_KEY = "digi-middleware-auth-user"; | |||||
/** | |||||
* 在HttpHeader中传递的APP Token信息 | |||||
*/ | |||||
public static final String HTTP_HEADER_APP_TOKEN_KEY = "digi-middleware-auth-app"; | |||||
/** | |||||
* 在HttpHeader中传递的Driver Token信息 | |||||
*/ | |||||
public static final String HTTP_HEADER_DRIVE_TOKEN_KEY = "digi-middleware-drive-access"; | |||||
/** | |||||
* 在HttpHeader中传递 是都需要加密 | |||||
*/ | |||||
public static final String HTTP_HEADER_DATA_MASK = "digi-middleware-data-mask"; | |||||
/** | |||||
* 在HttpHeader中传递 租户ID | |||||
*/ | |||||
public static final String HTTP_HEADER_TENANT_ID = "tenantId"; | |||||
/** | |||||
* 在HttpHeader中传递 设备信息 | |||||
*/ | |||||
public static final String HTTP_HEADER_CLIENT_AGENT = "Client-Agent"; | |||||
/** | |||||
* 查询时,若為歸戶資料,請填入固定值: iam-mapping | |||||
*/ | |||||
public static final String QUERY_PARAMETER_MAPPING = "iam-mapping"; | |||||
public static final String ZONE_OFF_SET = "+8"; | |||||
public static final String DEV_ACTIVE = "dev"; | |||||
public static final String EMPTY_STR = "[empty]"; | |||||
public static final String UPDATE_ALL = "all"; | |||||
public static final String UPDATE_ONLY_APPEND = "onlyAppend"; | |||||
public static final String ADMINISTRATORS = "administrators"; | |||||
public static final String ADMINISTRATOR = "administrator"; | |||||
public static final String INTEGRATION = "integration"; | |||||
public static final String SUPERADMIN = "superadmin"; | |||||
public static final String GUEST = "guest"; | |||||
public static final String ERROR_MESSAGE = "Server internal error"; | |||||
public static final String ENV_DEV = "dev"; | |||||
public static final String ENV_PROD = "prod"; | |||||
public static final String ENV_TEST = "test"; | |||||
public static final char AT = '@'; | |||||
public static final char DOT = '.'; | |||||
public static final char TAB = '\t'; | |||||
public static final char DASH = '-'; | |||||
public static final char COLON = ':'; | |||||
public static final char COMMA = ','; | |||||
public static final char DOLLAR = '$'; | |||||
public static final char PERCENT = '%'; | |||||
public static final char ESCAPE = '\\'; | |||||
public static final char ASTERISK = '*'; | |||||
public static final char SEMICOLON = ';'; | |||||
public static final char CURLY_LEFT = '{'; | |||||
public static final char CURLY_RIGHT = '}'; | |||||
public static final char DOUBLE_QUOTE = '"'; | |||||
public static final char SINGLE_QUOTE = '\''; | |||||
public static final char LEFT_PARENTHESIS = '('; | |||||
public static final char RIGHT_PARENTHESIS = ')'; | |||||
public static final String EMPTY = ""; | |||||
public static final String TRUE = "true"; | |||||
public static final String FALSE = "false"; | |||||
public static final String DEFAULT_VALUE_SEPARATOR = ":-"; | |||||
public static final String DEFAULT_CONTEXT_NAME = "default"; | |||||
public static final String LINE_SEPARATOR = System.getProperty("line.separator"); | |||||
public static final String ACCEPT_LANGUAGE = "Accept-Language"; | |||||
public static final String LOCALE = "Locale"; | |||||
} |
@ -0,0 +1,39 @@ | |||||
/* | |||||
* Author: DONGSK | |||||
* Datetime: 2024/4/25 16:43 | |||||
* Description: | |||||
* History: | |||||
* 作者姓名 --修改时间 --版本号--描述 | |||||
*/ | |||||
package com.digiwin.athena.app.infra.entity; | |||||
import com.baomidou.mybatisplus.annotation.TableField; | |||||
import com.baomidou.mybatisplus.annotation.TableName; | |||||
import com.baomidou.mybatisplus.extension.activerecord.Model; | |||||
import lombok.Data; | |||||
import java.io.Serializable; | |||||
/** | |||||
* DigiwinSummit | |||||
* | |||||
* @author DONGSK 2024/4/25 16:43 | |||||
* @since 1.0.0 | |||||
*/ | |||||
@Data | |||||
@TableName(value = "digiwin_summit", autoResultMap = true) | |||||
public class DigiwinSummit extends Model<DigiwinSummit> implements Serializable { | |||||
Long id; | |||||
@TableField(value = "user_id") | |||||
String userId; | |||||
@TableField(value = "tenant_id") | |||||
String tenantId; | |||||
@TableField(value = "ref_prod") | |||||
String refProd; | |||||
@TableField(value = "ref_user_id") | |||||
String refUserId; | |||||
@TableField(value = "ref_tenant_sid") | |||||
String refTenantSid; | |||||
@TableField(value = "ref_user_password") | |||||
String refUserPassword; | |||||
} |
@ -0,0 +1,48 @@ | |||||
/* | |||||
* Author: DONGSK | |||||
* Datetime: 2024/4/25 16:43 | |||||
* Description: | |||||
* History: | |||||
* 作者姓名 --修改时间 --版本号--描述 | |||||
*/ | |||||
package com.digiwin.athena.app.infra.entity; | |||||
import com.baomidou.mybatisplus.annotation.TableField; | |||||
import com.baomidou.mybatisplus.annotation.TableName; | |||||
import com.baomidou.mybatisplus.extension.activerecord.Model; | |||||
import lombok.Data; | |||||
import java.io.Serializable; | |||||
/** | |||||
* DigiwinSummit | |||||
* | |||||
* @author DONGSK 2024/4/25 16:43 | |||||
* @since 1.0.0 | |||||
*/ | |||||
@Data | |||||
@TableName(value = "layout_config", autoResultMap = true) | |||||
public class LayoutConfig extends Model<LayoutConfig> implements Serializable { | |||||
@TableField(value = "sys_id") | |||||
String sysId; | |||||
@TableField(value = "user_id") | |||||
String userId; | |||||
@TableField(value = "tenant_id") | |||||
String tenantId; | |||||
@TableField(value = "top_px") | |||||
String top; | |||||
@TableField(value = "left_px") | |||||
String left; | |||||
@TableField(value = "height_px") | |||||
String height; | |||||
@TableField(value = "width_px") | |||||
String width; | |||||
@TableField(value = "width_percent") | |||||
String widthPercent; | |||||
@TableField(value = "height_percent") | |||||
String heightPercent; | |||||
@TableField(value = "top_percent") | |||||
String topPercent; | |||||
@TableField(value = "left_percent") | |||||
String leftPercent; | |||||
} |
@ -0,0 +1,20 @@ | |||||
/* | |||||
* Author: DONGSK | |||||
* Datetime: 2024/4/25 16:49 | |||||
* Description: | |||||
* History: | |||||
* 作者姓名 --修改时间 --版本号--描述 | |||||
*/ | |||||
package com.digiwin.athena.app.infra.repository; | |||||
import com.digiwin.athena.app.infra.entity.DigiwinSummit; | |||||
import com.digiwin.athena.opt.persistence.repository.BaseRepository; | |||||
/** | |||||
* DigiwinSummitRepository | |||||
* | |||||
* @author DONGSK 2024/4/25 16:49 | |||||
* @since 1.0.0 | |||||
*/ | |||||
public interface DigiwinSummitRepository extends BaseRepository<DigiwinSummit> { | |||||
} |
@ -0,0 +1,20 @@ | |||||
/* | |||||
* Author: DONGSK | |||||
* Datetime: 2024/4/25 16:49 | |||||
* Description: | |||||
* History: | |||||
* 作者姓名 --修改时间 --版本号--描述 | |||||
*/ | |||||
package com.digiwin.athena.app.infra.repository; | |||||
import com.digiwin.athena.app.infra.entity.LayoutConfig; | |||||
import com.digiwin.athena.opt.persistence.repository.BaseRepository; | |||||
/** | |||||
* DigiwinSummitRepository | |||||
* | |||||
* @author DONGSK 2024/4/25 16:49 | |||||
* @since 1.0.0 | |||||
*/ | |||||
public interface LayoutConfigRepository extends BaseRepository<LayoutConfig> { | |||||
} |
@ -0,0 +1,7 @@ | |||||
package com.digiwin.athena.app.infra.service; | |||||
import com.digiwin.athena.app.infra.entity.DigiwinSummit; | |||||
import com.digiwin.athena.opt.persistence.service.IBaseService; | |||||
public interface DigiwinSummitService extends IBaseService<DigiwinSummit> { | |||||
} |
@ -0,0 +1,16 @@ | |||||
package com.digiwin.athena.app.infra.service.Impl; | |||||
import com.digiwin.athena.app.infra.entity.DigiwinSummit; | |||||
import com.digiwin.athena.app.infra.repository.DigiwinSummitRepository; | |||||
import com.digiwin.athena.app.infra.service.DigiwinSummitService; | |||||
import com.digiwin.athena.opt.persistence.service.impl.AbsBaseService; | |||||
import org.springframework.stereotype.Service; | |||||
/** | |||||
* @author zhenggl | |||||
* create: 2023-04-28 | |||||
* Description: | |||||
*/ | |||||
@Service | |||||
public class DigiwinSummitServiceImpl extends AbsBaseService<DigiwinSummitRepository, DigiwinSummit> implements DigiwinSummitService { | |||||
} |
@ -0,0 +1,16 @@ | |||||
package com.digiwin.athena.app.infra.service.Impl; | |||||
import com.digiwin.athena.app.infra.entity.LayoutConfig; | |||||
import com.digiwin.athena.app.infra.repository.LayoutConfigRepository; | |||||
import com.digiwin.athena.app.infra.service.LayoutConfigService; | |||||
import com.digiwin.athena.opt.persistence.service.impl.AbsBaseService; | |||||
import org.springframework.stereotype.Service; | |||||
/** | |||||
* @author zhenggl | |||||
* create: 2023-04-28 | |||||
* Description: | |||||
*/ | |||||
@Service | |||||
public class LayoutConfigServiceImpl extends AbsBaseService<LayoutConfigRepository, LayoutConfig> implements LayoutConfigService { | |||||
} |
@ -0,0 +1,7 @@ | |||||
package com.digiwin.athena.app.infra.service; | |||||
import com.digiwin.athena.app.infra.entity.LayoutConfig; | |||||
import com.digiwin.athena.opt.persistence.service.IBaseService; | |||||
public interface LayoutConfigService extends IBaseService<LayoutConfig> { | |||||
} |
@ -0,0 +1,29 @@ | |||||
package com.digiwin.athena.app.provider; | |||||
import com.digiwin.app.service.AllowAnonymous; | |||||
import com.digiwin.app.service.DWEAIResult; | |||||
import com.digiwin.app.service.DWService; | |||||
import com.digiwin.app.service.eai.EAIService; | |||||
import com.digiwin.athena.app.service.quotation.QuotationUtil; | |||||
import java.util.Map; | |||||
/** | |||||
* @author lz | |||||
* @version 1.0 | |||||
* @title QuotationRequirementEAIService | |||||
* @description | |||||
* @create 2024/4/29 10:20 | |||||
*/ | |||||
public interface QuotationRequirementEAIService extends DWService { | |||||
/** | |||||
* 报价需求查询 | |||||
* @param headers | |||||
* @param messageBody | |||||
* @return | |||||
* @throws Exception | |||||
*/ | |||||
@EAIService(id = QuotationUtil.DEMO_ATHENAOPT_REQUIREMENT_INFO_GET) | |||||
DWEAIResult get(Map<String, String> headers, String messageBody) throws Exception; | |||||
} |
@ -0,0 +1,27 @@ | |||||
package com.digiwin.athena.app.provider.impl; | |||||
import com.digiwin.app.service.DWEAIResult; | |||||
import com.digiwin.athena.app.provider.QuotationRequirementEAIService; | |||||
import com.digiwin.athena.app.service.quotation.QuotationUtil; | |||||
import com.digiwin.athena.opt.common.eai.service.EAIServiceContext; | |||||
import javax.annotation.Resource; | |||||
import java.util.Map; | |||||
/** | |||||
* @author lz | |||||
* @version 1.0 | |||||
* @title PurchaseDemoEAIServiceImpl | |||||
* @description | |||||
* @create 2023/8/30 16:50 | |||||
*/ | |||||
public class QuotationRequirementEAIServiceImpl implements QuotationRequirementEAIService { | |||||
@Resource | |||||
private EAIServiceContext eaiServiceContext; | |||||
@Override | |||||
public DWEAIResult get(Map<String, String> headers, String messageBody) throws Exception { | |||||
return eaiServiceContext.execute(QuotationUtil.DEMO_ATHENAOPT_REQUIREMENT_INFO_GET , headers, messageBody); | |||||
} | |||||
} |
@ -0,0 +1,86 @@ | |||||
package com.digiwin.athena.app.service.basic; | |||||
import org.apache.commons.codec.binary.Hex; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import javax.crypto.Cipher; | |||||
import javax.crypto.SecretKey; | |||||
import javax.crypto.spec.IvParameterSpec; | |||||
import javax.crypto.spec.SecretKeySpec; | |||||
import java.nio.charset.StandardCharsets; | |||||
import java.util.Base64; | |||||
public class AESUtils { | |||||
private static final Logger logger = LoggerFactory.getLogger(AESUtils.class); | |||||
private static final String IV_STRING = "ghUb#er57HBh(u%g"; | |||||
/** | |||||
* 加密 | |||||
* 加密失败返回原文 2021-7-21 | |||||
* | |||||
* @param src 加密字段 | |||||
* @param aesKey aesKey 长度16 | |||||
* @return 密文 string | |||||
*/ | |||||
public static String aesEncryptByBase64(String src, String aesKey) { | |||||
try { | |||||
SecretKeySpec key = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES"); | |||||
byte[] initParam = IV_STRING.getBytes(StandardCharsets.UTF_8); | |||||
IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam); | |||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |||||
cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec); | |||||
byte[] cleartext = src.getBytes(StandardCharsets.UTF_8); | |||||
byte[] ciphertextBytes = cipher.doFinal(cleartext); | |||||
Base64.Encoder encoder = Base64.getEncoder(); | |||||
return encoder.encodeToString(ciphertextBytes); | |||||
} catch (Exception ex) { | |||||
logger.error("AES加密失败[{}]", src); | |||||
return src; | |||||
} | |||||
} | |||||
public static String aesEncrypt(String src, String aesKey) { | |||||
try { | |||||
// 生成和mysql一致的加密数据 | |||||
SecretKeySpec key = generateMySQLAESKey(aesKey); | |||||
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); | |||||
cipher.init(Cipher.ENCRYPT_MODE, key); | |||||
byte[] cleartext = src.getBytes(StandardCharsets.UTF_8); | |||||
byte[] ciphertextBytes = cipher.doFinal(cleartext); | |||||
return new String(Hex.encodeHexString(ciphertextBytes)).toUpperCase(); | |||||
} catch (Exception ex) { | |||||
logger.error("AES加密失败[{}]", src); | |||||
return src; | |||||
} | |||||
} | |||||
public static String aesDecrypt(String content, String aesKey) { | |||||
try { | |||||
SecretKey key = generateMySQLAESKey(aesKey); | |||||
Cipher cipher = Cipher.getInstance("AES"); | |||||
cipher.init(Cipher.DECRYPT_MODE, key); | |||||
byte[] cleartext = Hex.decodeHex(content.toCharArray()); | |||||
byte[] ciphertextBytes = cipher.doFinal(cleartext); | |||||
return new String(ciphertextBytes, StandardCharsets.UTF_8); | |||||
} catch (Exception ex) { | |||||
logger.error("AES解密失败[{}]", content); | |||||
return content; | |||||
} | |||||
} | |||||
public static SecretKeySpec generateMySQLAESKey(final String key) { | |||||
final byte[] finalKey = new byte[16]; | |||||
int i = 0; | |||||
for (byte b : key.getBytes(StandardCharsets.UTF_8)) { | |||||
finalKey[i++ % 16] ^= b; | |||||
} | |||||
return new SecretKeySpec(finalKey, "AES"); | |||||
} | |||||
} |
@ -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(); | |||||
} | |||||
} |
@ -0,0 +1,118 @@ | |||||
package com.digiwin.athena.app.service.basic; | |||||
import org.apache.commons.codec.binary.Base64; | |||||
import javax.crypto.Cipher; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.security.Key; | |||||
import java.security.KeyFactory; | |||||
import java.security.spec.PKCS8EncodedKeySpec; | |||||
import java.security.spec.X509EncodedKeySpec; | |||||
/** | |||||
* @author zhuzcz | |||||
*/ | |||||
public class RSAUtils { | |||||
/** | |||||
* 加密算法RSA | |||||
*/ | |||||
public static final String KEY_ALGORITHM = "RSA"; | |||||
/** | |||||
* RSA最大加密明文大小 | |||||
*/ | |||||
private static final int MAX_ENCRYPT_BLOCK = 245; | |||||
/** | |||||
* RSA最大解密密文大小 | |||||
*/ | |||||
private static final int MAX_DECRYPT_BLOCK = 256; | |||||
/** */ | |||||
/** | |||||
* <P> | |||||
* 私钥解密 | |||||
* </p> | |||||
* | |||||
* @param encryptedData 已加密数据 | |||||
* @param privateKey 私钥(BASE64编码) | |||||
* @return | |||||
* @throws Exception | |||||
*/ | |||||
public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception { | |||||
byte[] keyBytes = Base64.decodeBase64(privateKey); | |||||
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); | |||||
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); | |||||
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); | |||||
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); | |||||
cipher.init(Cipher.DECRYPT_MODE, privateK); | |||||
int inputLen = encryptedData.length; | |||||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||||
int offSet = 0; | |||||
byte[] cache; | |||||
int i = 0; | |||||
// 对数据分段解密 | |||||
while (inputLen - offSet > 0) { | |||||
if (inputLen - offSet > MAX_DECRYPT_BLOCK) { | |||||
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); | |||||
} else { | |||||
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); | |||||
} | |||||
out.write(cache, 0, cache.length); | |||||
i++; | |||||
offSet = i * MAX_DECRYPT_BLOCK; | |||||
} | |||||
byte[] decryptedData = out.toByteArray(); | |||||
out.close(); | |||||
return decryptedData; | |||||
} | |||||
/** */ | |||||
/** | |||||
* <p> | |||||
* 公钥加密 | |||||
* </p> | |||||
* | |||||
* @param data 源数据 | |||||
* @param publicKey 公钥(BASE64编码) | |||||
* @return | |||||
* @throws Exception | |||||
*/ | |||||
public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception { | |||||
byte[] keyBytes = Base64.decodeBase64(publicKey); | |||||
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); | |||||
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); | |||||
Key publicK = keyFactory.generatePublic(x509KeySpec); | |||||
// 对数据加密 | |||||
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); | |||||
cipher.init(Cipher.ENCRYPT_MODE, publicK); | |||||
int inputLen = data.length; | |||||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||||
int offSet = 0; | |||||
byte[] cache; | |||||
int i = 0; | |||||
// 对数据分段加密 | |||||
while (inputLen - offSet > 0) { | |||||
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { | |||||
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); | |||||
} else { | |||||
cache = cipher.doFinal(data, offSet, inputLen - offSet); | |||||
} | |||||
out.write(cache, 0, cache.length); | |||||
i++; | |||||
offSet = i * MAX_ENCRYPT_BLOCK; | |||||
} | |||||
byte[] encryptedData = out.toByteArray(); | |||||
out.close(); | |||||
return encryptedData; | |||||
} | |||||
public static String encryptByPublicKey(String data, String clientPublicKey) throws Exception { | |||||
data = Base64.encodeBase64String(encryptByPublicKey(data.getBytes(), clientPublicKey)); | |||||
return data; | |||||
} | |||||
} |
@ -0,0 +1,109 @@ | |||||
package com.digiwin.athena.app.service.quotation; | |||||
import com.alibaba.fastjson.JSONObject; | |||||
import com.digiwin.app.service.DWEAIResult; | |||||
import com.digiwin.athena.opt.common.eai.EAIUtil; | |||||
import com.digiwin.athena.opt.common.eai.service.AbsEAIService; | |||||
import org.springframework.stereotype.Service; | |||||
import java.util.*; | |||||
/** | |||||
* @author lz | |||||
* @version 1.0 | |||||
* @title QuotationRequirement | |||||
* @description mock需求数据 | |||||
* @create 2024/4/29 10:00 | |||||
*/ | |||||
@Service | |||||
public class QuotationRequirementInfoGetService extends AbsEAIService { | |||||
@Override | |||||
public String getServiceName() { | |||||
return QuotationUtil.DEMO_ATHENAOPT_REQUIREMENT_INFO_GET; | |||||
} | |||||
@Override | |||||
public DWEAIResult execute(Map<String, String> headers, String messageBody) throws Exception { | |||||
List<Map<String, Object>> requirementInfo = getRequirementInfo(); | |||||
return EAIUtil.buildEAIResult(new JSONObject().fluentPut("requirement_info", requirementInfo)); | |||||
} | |||||
/** | |||||
* @description mock需求数据 | |||||
* @author lz | |||||
* @throws | |||||
* @time 2024/4/29 10:16 | |||||
*/ | |||||
public static List<Map<String, Object>> getRequirementInfo() { | |||||
List<Map<String, Object>> requirementInfo = new ArrayList<>(); | |||||
// 第一个需求 | |||||
Map<String, Object> requirement1 = new HashMap<>(); | |||||
List<String> correlationCode1 = Arrays.asList("100203"); | |||||
requirement1.put("correlation_code", correlationCode1); | |||||
requirement1.put("requirement_no", "100203"); | |||||
requirement1.put("requirement_name", "产品色"); | |||||
requirement1.put("requirement_description", ""); | |||||
requirementInfo.add(requirement1); | |||||
// 第二个需求 | |||||
Map<String, Object> requirement2 = new HashMap<>(); | |||||
List<String> correlationCode2 = Arrays.asList("100203", "1-1"); | |||||
requirement2.put("correlation_code", correlationCode2); | |||||
requirement2.put("requirement_no", "100203"); | |||||
requirement2.put("requirement_name", "是否定制-客户定制色或工厂标准色"); | |||||
requirement2.put("requirement_description", ""); | |||||
requirementInfo.add(requirement2); | |||||
// 第三个需求 | |||||
Map<String, Object> requirement3 = new HashMap<>(); | |||||
List<String> correlationCode3 = Arrays.asList("100203", "2-1"); | |||||
requirement3.put("correlation_code", correlationCode3); | |||||
requirement3.put("requirement_no", "100203"); | |||||
requirement3.put("requirement_name", "产品色系-2"); | |||||
requirement3.put("requirement_description", ""); | |||||
requirementInfo.add(requirement3); | |||||
// 第四个需求 | |||||
Map<String, Object> requirement4 = new HashMap<>(); | |||||
List<String> correlationCode4 = Arrays.asList("100203", "3-1"); | |||||
requirement4.put("correlation_code", correlationCode4); | |||||
requirement4.put("requirement_no", "100203"); | |||||
requirement4.put("requirement_name", "每色MOQ-2"); | |||||
requirement4.put("requirement_description", ""); | |||||
requirementInfo.add(requirement4); | |||||
// 第五个需求 | |||||
Map<String, Object> requirement5 = new HashMap<>(); | |||||
List<String> correlationCode5 = Arrays.asList("100203", "4-1"); | |||||
requirement5.put("correlation_code", correlationCode5); | |||||
requirement5.put("requirement_no", "100203"); | |||||
requirement5.put("requirement_name", "是否有文件,若有,需附上文件-2"); | |||||
requirement5.put("requirement_description", ""); | |||||
requirementInfo.add(requirement5); | |||||
// 第六个需求 | |||||
Map<String, Object> requirement6 = new HashMap<>(); | |||||
List<String> correlationCode6 = Arrays.asList("100204"); | |||||
requirement6.put("correlation_code", correlationCode6); | |||||
requirement6.put("requirement_no", "100204"); | |||||
requirement6.put("requirement_name", "是否有文件,若有,需附上文件-2"); | |||||
requirement6.put("requirement_description", ""); | |||||
requirementInfo.add(requirement6); | |||||
// 第七个需求 | |||||
Map<String, Object> requirement7 = new HashMap<>(); | |||||
List<String> correlationCode7 = Arrays.asList("100204", "5-1"); | |||||
requirement7.put("correlation_code", correlationCode7); | |||||
requirement7.put("requirement_no", "100204"); | |||||
requirement7.put("requirement_name", "需求名称"); | |||||
requirement7.put("requirement_description", ""); | |||||
requirementInfo.add(requirement7); | |||||
return requirementInfo; | |||||
} | |||||
} |
@ -0,0 +1,15 @@ | |||||
package com.digiwin.athena.app.service.quotation; | |||||
/** | |||||
* @author lz | |||||
* @version 1.0 | |||||
* @title QuotationUtil | |||||
* @description | |||||
* @create 2024/4/29 10:01 | |||||
*/ | |||||
public class QuotationUtil { | |||||
public static final String DEMO_ATHENAOPT_REQUIREMENT_INFO_GET= "demo.athenaopt.requirement.info.get"; | |||||
} |
@ -1 +1 @@ | |||||
1005 | |||||
1021 |