提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
需要接入华为云lts日志查询功能,但是lts请求需要token或者ak、sk加密才能请求成功。
华为云lts日志查询接口:POST /v2/{project_id}/groups/{log_group_id}/streams/{log_stream_id}/content/query
提示:以下是本篇文章正文内容,下面案例可供参考
一、接入步骤
1.引入maven配置
<!-- 华为云 LTS日志 -->
<dependency>
<groupId>com.huawei.apigateway</groupId>
<artifactId>java-sdk-core</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.openeuler</groupId>
<artifactId>bgmprovider</artifactId>
<version>1.0.3</version>
</dependency>
2.ssl加密客户端
package com.csdn.doaudit.tools;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.prng.SP800SecureRandomBuilder;
import org.openeuler.BGMProvider;
import javax.net.ssl.*;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;
/**
* ssl加密工具
* @author hext
* @version 1.0
* @description
* @date 2023/6/19
*/
@Slf4j
public class SSLCipherSuiteUtil {
private static final int ENTROPY_BITS_REQUIRED = 384;
private static final int CIPHER_LEN = 256;
public static final String GM_PROTOCOL = "GMTLS";
public static final String INTERNATIONAL_PROTOCOL = "TLSv1.2";
public static final String SIGNATURE_ALGORITHM_SDK_HMAC_SHA256 = "SDK-HMAC-SHA256";
public static final String[] SUPPORTED_CIPHER_SUITES = {"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"};
private static OkHttpClient okHttpClient;
private static CloseableHttpClient httpClient;
public static OkHttpClient createOkHttpClient(String protocol) throws Exception {
SSLContext sslContext = getSslContext(protocol);
// Create an ssl socket factory with our all-trusting manager
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, new TrustAllManager())
.hostnameVerifier(new TrustAllHostnameVerifier());
okHttpClient = builder.connectTimeout(10, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).build();
return okHttpClient;
}
public static HttpClient createHttpClient(String protocol) throws Exception {
SSLContext sslContext = getSslContext(protocol);
// create factory
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
new String[]{protocol}, SUPPORTED_CIPHER_SUITES, new TrustAllHostnameVerifier());
httpClient = HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory).build();
return httpClient;
}
private static SSLContext getSslContext(String protocol) throws Exception,
NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
if (!GM_PROTOCOL.equals(protocol) && !INTERNATIONAL_PROTOCOL.equals(protocol)) {
log.info("Unsupport protocol: {}, Only support GMTLS TLSv1.2", protocol);
throw new Exception("Unsupport protocol, Only support GMTLS TLSv1.2");
}
// Create a trust manager that does not validate certificate chains
TrustAllManager[] trust = {new TrustAllManager()};
KeyManager[] kms = null;
SSLContext sslContext;
sslContext = SSLContext.getInstance(INTERNATIONAL_PROTOCOL, "SunJSSE");
if (GM_PROTOCOL.equals(protocol)) {
Security.insertProviderAt(new BGMProvider(), 1);
sslContext = SSLContext.getInstance(GM_PROTOCOL, "BGMProvider");
}
SecureRandom secureRandom = getSecureRandom();
sslContext.init(kms, trust, secureRandom);
sslContext.getServerSessionContext().setSessionCacheSize(8192);
sslContext.getServerSessionContext().setSessionTimeout(3600);
return sslContext;
}
// 不校验服务端证书
private static class TrustAllManager implements X509TrustManager {
private X509Certificate[] issuers;
public TrustAllManager() {
this.issuers = new X509Certificate[0];
}
public X509Certificate[] getAcceptedIssuers() {
return issuers;
}
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
}
private static SecureRandom getSecureRandom() {
SecureRandom source;
try {
source = SecureRandom.getInstanceStrong();
} catch (NoSuchAlgorithmException e) {
log.error("get SecureRandom failed", e);
throw new RuntimeException("get SecureRandom failed");
}
boolean predictionResistant = true;
BlockCipher cipher = new AESEngine();
boolean reSeed = false;
return new SP800SecureRandomBuilder(source, predictionResistant).setEntropyBitsRequired(
ENTROPY_BITS_REQUIRED).buildCTR(cipher, CIPHER_LEN, null, reSeed);
}
// 不校验域名
private static class TrustAllHostnameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
}
3.request签名请求
Request request = new Request();
request.setKey("ak");
request.setSecret("sk");
request.setMethod("POST");
String formatUrl = "https://lts.%s.myhuaweicloud.com/v2/%s/groups/%s/streams/%s/content/query";
String url = String.format(this.formatUrl, huaWeiLogConfig.getRegion(), huaWeiLogConfig.getProjectId(), huaWeiLogConfig.getLogGroupId(), logStreamId);
request.setUrl(url);
request.addHeader("Host", "lts." + huaWeiLogConfig.getRegion() + ".myhuaweicloud.com");
request.addHeader("Content-Type", "application/json");
JSONObject params = new JSONObject();
params.put("start_time", startTime);
params.put("end_time", endTime);
params.put("keywords", query);
// 不高亮
params.put("highlight", false);
request.setBody(params.toString());
// Sign the request.
okhttp3.Request signedRequest = Client.signOkhttp(request, SSLCipherSuiteUtil.SIGNATURE_ALGORITHM_SDK_HMAC_SHA256);
OkHttpClient okHttpClient = SSLCipherSuiteUtil.createOkHttpClient(SSLCipherSuiteUtil.INTERNATIONAL_PROTOCOL);
Response response = okHttpClient.newCall(request).execute();
String result = response.body().string();
log.info("result:{}", result);
response.close();
二、遇到的问题
1.Signer实例化InstantiationError
提示Signer实例化InstantiationError(当一个应用试图通过Java的new操作符构造一个抽象类或者接口时抛出该异常.)
搜Singn发现有两个包也一样的类,不过一个是interface、一个是class。看来是运行时用的interface实例化才报的错
解决办法:找到Singn接口对应是哪个包,排除对应的jar包,以自己导入的版本为准
2.请求参数配置错误
华为云提供了调试接口,需配置正确的region、projectId、logGroupId、logStreamId,调试效果如下:
调试接口地址:https://console.huaweicloud.com/apiexplorer/#/openapi/LTS/debug?api=ListLogs
三、代码优化
创建OkHttpClient或httpClient是比较耗费资源的动作,不应该每次请求都创建一次,加载对象应该做成单例
代码如下:
package com.csdn.doaudit.utils;
import com.csdn.doaudit.tools.SSLCipherSuiteUtil;
import lombok.Getter;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import org.apache.http.client.HttpClient;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import java.io.IOException;
/**
* SSL加密HttpClient端
* @author hext
* @version 1.0
* @description
* @date 2023/6/20
*/
@Component
public class SSLHttpClient implements InitializingBean, DisposableBean {
@Getter
private OkHttpClient okHttpClient;
// @Getter
// private HttpClient httpClient;
@Override
public void destroy() throws Exception {
this.okHttpClient = null;
}
@Override
public void afterPropertiesSet() throws Exception {
this.okHttpClient = SSLCipherSuiteUtil.createOkHttpClient(SSLCipherSuiteUtil.INTERNATIONAL_PROTOCOL);
}
public Response execute(okhttp3.Request request) throws IOException {
return this.okHttpClient.newCall(request).execute();
}
}
使用时:
Response response = this.sslHttpClient.execute(signedRequest);
总结
1、lts日志查询的http请求需将ak、sk加密认证才能生效
2、避免jar包冲突,maven冲突需排除
3、可根据接口测试工具验证
参考文档
1、签名 sdk api:https://support.huaweicloud.com/devg-apisign/api-sign-sdk-java.html
2、接口文档:https://support.huaweicloud.com/api-lts/lts-api.pdf、https://support.huaweicloud.com/api-lts/lts_api_0028.html
3、接口测试地址:https://console.huaweicloud.com/apiexplorer/#/openapi/LTS/debug?api=ListLogs