test: 添加证书编号
parent
23d682431d
commit
b9d0eb3b4d
|
|
@ -32,5 +32,18 @@
|
||||||
<artifactId>httpclient5</artifactId>
|
<artifactId>httpclient5</artifactId>
|
||||||
<version>5.2.3</version>
|
<version>5.2.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>1.2.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-core</artifactId>
|
||||||
|
<version>1.2.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
||||||
|
|
@ -22,4 +22,9 @@ public interface CertificateProvider {
|
||||||
* @return X.509证书实例
|
* @return X.509证书实例
|
||||||
*/
|
*/
|
||||||
X509Certificate getAvailableCertificate();
|
X509Certificate getAvailableCertificate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验证书是否有效
|
||||||
|
*/
|
||||||
|
boolean isAvailableCertificate(String serialNumber);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,16 @@ public final class DefaultValidator implements Validator {
|
||||||
validateResponseSignature(response, channel);
|
validateResponseSignature(response, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate(HttpRequest newRequest) {
|
||||||
|
// 校验证书
|
||||||
|
CertificateProvider provider = getProfile().getSignature().getCertificateProvider();
|
||||||
|
Signer signer = getProfile().getSignature().getSigner();
|
||||||
|
if (!provider.isAvailableCertificate(signer.getCertificateSerial())) {
|
||||||
|
throw new ValidationException(String.format("证书已失效, 序列号:%s", signer.getCertificateSerial()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void isInvalidHttpCode(OriginalResponse response) {
|
public void isInvalidHttpCode(OriginalResponse response) {
|
||||||
if (response.getStatusCode() < HTTP_OK || response.getStatusCode() >= HTTP_MULT_CHOICE) {
|
if (response.getStatusCode() < HTTP_OK || response.getStatusCode() >= HTTP_MULT_CHOICE) {
|
||||||
throw new ValidationException(String.format("校验失败, HttpStatusCode=%s, Request-Id=%s, HttpResponseBody=%s",
|
throw new ValidationException(String.format("校验失败, HttpStatusCode=%s, Request-Id=%s, HttpResponseBody=%s",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import static com.czcb.scfs.api.core.util.Strings.timeRange;
|
import static com.czcb.scfs.api.core.util.Strings.timeRange;
|
||||||
|
|
@ -24,11 +25,9 @@ public final class LocalCertificateProvider implements CertificateProvider {
|
||||||
private X509Certificate availableCertificate;
|
private X509Certificate availableCertificate;
|
||||||
|
|
||||||
public LocalCertificateProvider(List<X509Certificate> certificates) {
|
public LocalCertificateProvider(List<X509Certificate> certificates) {
|
||||||
if (certificates.isEmpty()) {
|
if (certificates != null && !certificates.isEmpty()) {
|
||||||
throw new IllegalArgumentException("The parameter list of constructor is empty.");
|
certificates.forEach(this::addX509Certificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
certificates.forEach(this::addX509Certificate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -44,8 +43,9 @@ public final class LocalCertificateProvider implements CertificateProvider {
|
||||||
|
|
||||||
public void addX509Certificate(X509Certificate certificate) {
|
public void addX509Certificate(X509Certificate certificate) {
|
||||||
if (!validity.withinValidity(certificate)) {
|
if (!validity.withinValidity(certificate)) {
|
||||||
logger.error("证书已失效, 序列号:{}, 有效范围:[{}]", toHexUpper(certificate.getSerialNumber()), timeRange(certificate));
|
String serialNumberHexUpper = toHexUpper(certificate.getSerialNumber());
|
||||||
return;
|
String timeRange = timeRange(certificate);
|
||||||
|
logger.error("证书已失效, 序列号:{}, 有效期:[{}]", serialNumberHexUpper, timeRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
certificates.put(toHexUpper(certificate.getSerialNumber()), certificate);
|
certificates.put(toHexUpper(certificate.getSerialNumber()), certificate);
|
||||||
|
|
@ -62,10 +62,12 @@ public final class LocalCertificateProvider implements CertificateProvider {
|
||||||
availableCertificate = validity.getLongestCertificate(certificates);
|
availableCertificate = validity.getLongestCertificate(certificates);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (availableCertificate == null) {
|
|
||||||
throw new IllegalArgumentException("没有有效的证书");
|
|
||||||
}
|
|
||||||
|
|
||||||
return availableCertificate;
|
return availableCertificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailableCertificate(String serialNumber) {
|
||||||
|
X509Certificate certificate = getCertificate(serialNumber);
|
||||||
|
return Objects.nonNull(certificate) && validity.withinValidity(certificate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,9 @@ public abstract class AbstractApiClient implements ApiClient {
|
||||||
public <T> HttpResponse<T> exchange(HttpRequest request, Class<T> responseClass) {
|
public <T> HttpResponse<T> exchange(HttpRequest request, Class<T> responseClass) {
|
||||||
// 组装请求对象
|
// 组装请求对象
|
||||||
HttpRequest newRequest = assembleRequest(request);
|
HttpRequest newRequest = assembleRequest(request);
|
||||||
|
// 请求校验
|
||||||
|
validateRequest(newRequest);
|
||||||
|
|
||||||
// 打印请求数据
|
// 打印请求数据
|
||||||
httpLogger.logRequest(newRequest, getHttpVersion());
|
httpLogger.logRequest(newRequest, getHttpVersion());
|
||||||
|
|
||||||
|
|
@ -155,6 +158,10 @@ public abstract class AbstractApiClient implements ApiClient {
|
||||||
return credential.buildRequestAuthorization(request, channel);
|
return credential.buildRequestAuthorization(request, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateRequest(HttpRequest newRequest) {
|
||||||
|
validator.validate(newRequest);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验响应
|
* 校验响应
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class ApiClientBuilderTest {
|
||||||
list.add(certificate);
|
list.add(certificate);
|
||||||
CertificateProvider certificateProvider = new LocalCertificateProvider(list);
|
CertificateProvider certificateProvider = new LocalCertificateProvider(list);
|
||||||
Privacy privacy = new TestPrivacy(privateKey, certificateProvider);
|
Privacy privacy = new TestPrivacy(privateKey, certificateProvider);
|
||||||
Signature signature = new DefaultSignature(certificateProvider, new TestSigner(privateKey,""), new TestVerifier(certificateProvider));
|
Signature signature = new DefaultSignature(certificateProvider, new TestSigner(privateKey, ""), new TestVerifier(certificateProvider));
|
||||||
|
|
||||||
return new TestProfile(
|
return new TestProfile(
|
||||||
privacy,
|
privacy,
|
||||||
|
|
@ -106,7 +106,7 @@ class ApiClientBuilderTest {
|
||||||
list.add(certificate);
|
list.add(certificate);
|
||||||
CertificateProvider certificateProvider = new LocalCertificateProvider(list);
|
CertificateProvider certificateProvider = new LocalCertificateProvider(list);
|
||||||
Privacy privacy = new TestPrivacy(privateKey, certificateProvider);
|
Privacy privacy = new TestPrivacy(privateKey, certificateProvider);
|
||||||
Signature signature = new DefaultSignature(certificateProvider, new TestSigner(privateKey,""), new TestVerifier(certificateProvider));
|
Signature signature = new DefaultSignature(certificateProvider, new TestSigner(privateKey, ""), new TestVerifier(certificateProvider));
|
||||||
|
|
||||||
return new TestProfile(
|
return new TestProfile(
|
||||||
privacy,
|
privacy,
|
||||||
|
|
@ -126,7 +126,7 @@ class ApiClientBuilderTest {
|
||||||
list.add(certificate);
|
list.add(certificate);
|
||||||
CertificateProvider certificateProvider = new LocalCertificateProvider(list);
|
CertificateProvider certificateProvider = new LocalCertificateProvider(list);
|
||||||
Privacy privacy = new TestPrivacy(privateKey, certificateProvider);
|
Privacy privacy = new TestPrivacy(privateKey, certificateProvider);
|
||||||
Signature signature = new DefaultSignature(certificateProvider, new TestSigner(privateKey,""), new TestVerifier(certificateProvider));
|
Signature signature = new DefaultSignature(certificateProvider, new TestSigner(privateKey, ""), new TestVerifier(certificateProvider));
|
||||||
|
|
||||||
return new TestProfile(
|
return new TestProfile(
|
||||||
privacy,
|
privacy,
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ class ApacheHttpclientV3Test {
|
||||||
CertificateProvider certificateProvider = new LocalCertificateProvider(list);
|
CertificateProvider certificateProvider = new LocalCertificateProvider(list);
|
||||||
Privacy privacy = new TestPrivacy(privateKey, certificateProvider);
|
Privacy privacy = new TestPrivacy(privateKey, certificateProvider);
|
||||||
Signature signature = new DefaultSignature(certificateProvider,
|
Signature signature = new DefaultSignature(certificateProvider,
|
||||||
new TestSigner(privateKey,"6CDDAA92CAD75998325027647847330C1756291"),
|
new TestSigner(privateKey, "6CDDAA92CAD75998325027647847330C1756291"),
|
||||||
new TestVerifier(certificateProvider));
|
new TestVerifier(certificateProvider));
|
||||||
|
|
||||||
return new TestProfile(
|
return new TestProfile(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDeTCCAmGgAwIBAgIhAII88+MQ8uLtGvhVBudKldxDAQBv3vL9AZlT+vTeEqi/MA0GCSqGSIb3
|
||||||
|
DQEBCwUAMIGNMQswCQYDVQQGEwJDTjESMBAGA1UECAwJ5rWZ5rGf55yBMRIwEAYDVQQHDAnmna3l
|
||||||
|
t57luIIxITAfBgNVBAoMGOa1meaxn+eooOW3nuWVhuS4mumTtuihjDEYMBYGA1UECwwP5pWw5a2X
|
||||||
|
6YeR6J6N6YOoMRkwFwYDVQQDDBBzY2ZzLmN6Y2IuY29tLmNuMB4XDTIzMDYxODA5MDczMVoXDTI0
|
||||||
|
MDYxODA5MDczMVowUjELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCea1meaxn+ecgTESMBAGA1UEBwwJ
|
||||||
|
5p2t5bee5biCMRswGQYDVQQKDBLnqKDlt57llYbkuJrpk7booYwwggEiMA0GCSqGSIb3DQEBAQUA
|
||||||
|
A4IBDwAwggEKAoIBAQCfHOgnUYbFi780EX9xQTdWPvCyBhaEnU5Y2p1bW4dHoumgEtjQOkLlRe3U
|
||||||
|
g1lu6TfhuE9YOQ9+V+Dsnzt7MXIRI7KlOuwpfwXn3e/MYP5ZtDBUiuSGNNVSP39wgb6aYXhvFY/L
|
||||||
|
m9gaO8Q4rauzK94Clw4sH3a7J6ST50xHss8VjSVFUkcPhpH+OJBTUrXWiccZCn01XDz0vmq6J3Au
|
||||||
|
jM55WBEmoz2r9iiVdCjZsgB4veQIpCKuMvJsEXVgRzULUnaqdX+7BTDBs30kCGyyBarR+wXLAKNQ
|
||||||
|
1nENFs1IGM99I+O8UsD6CvUnt2t7l3B8/qIlOSfds8x+BoUxQwhmUaMjAgMBAAEwDQYJKoZIhvcN
|
||||||
|
AQELBQADggEBACRCHOYH8ncOiYjMm3As7OFdnVDuGByMoZsDucqwrs0mJZVdp3OMgvGhC9zkzdZX
|
||||||
|
sJFKQeIRp/13cD1SKxtwfU7w4J+/FWpWPEG9Jf2bLqurYivu0tTa1xe5SDL4unNaj/o7BA0vaKJe
|
||||||
|
gagyULAilNCGBCfy59BSR/GQbgAC6pdl3soMx/s1c9BcZVplbq12/rmStGce6h3QqNjwpRMowbVW
|
||||||
|
XswXhr08AUevF7UriDjHkCsa6MqQ5x+ShV9qO1f2LDYBQRnM2Ty44EV5eUbHyKOJAYF+WqT6IRiA
|
||||||
|
2sMZrKRTHaNZB4j0Vc87HuxDtTNh/EEXU2sO31WZHs3ymAChbC4=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCfHOgnUYbFi780EX9xQTdWPvCy
|
||||||
|
BhaEnU5Y2p1bW4dHoumgEtjQOkLlRe3Ug1lu6TfhuE9YOQ9+V+Dsnzt7MXIRI7KlOuwpfwXn3e/M
|
||||||
|
YP5ZtDBUiuSGNNVSP39wgb6aYXhvFY/Lm9gaO8Q4rauzK94Clw4sH3a7J6ST50xHss8VjSVFUkcP
|
||||||
|
hpH+OJBTUrXWiccZCn01XDz0vmq6J3AujM55WBEmoz2r9iiVdCjZsgB4veQIpCKuMvJsEXVgRzUL
|
||||||
|
UnaqdX+7BTDBs30kCGyyBarR+wXLAKNQ1nENFs1IGM99I+O8UsD6CvUnt2t7l3B8/qIlOSfds8x+
|
||||||
|
BoUxQwhmUaMjAgMBAAECggEAQ+meKz4QdJvnse0wBKKN4Hl/2bRggxzzVliFJnvEG27tIb45nXLo
|
||||||
|
n5x/3R9tGjpf+C9namP8eXQ/1C9Iv5XEto0SkJS8PR/y4NspIYZaueX/ZO5diOzfCjqBBf/S32jv
|
||||||
|
8xX0aLbtf5D3+SsjaJe2LEvWKD4Luuk6RUjJlaa73dnSuGFSuvYV8MvFdHtfU8L8ZRoqZwmM9QTg
|
||||||
|
+Gpix4z6Hy/Mmi1xRl0EhIITq+mV9wR9Ock/0o12nvsNDyDSyrrt3niXTTkVCbct+t4UFwtnrZyH
|
||||||
|
dwl1OQ+WleTkUQY+wNgpq4jLjwGowXnqXlKff3tvXEt+3tpdOS8i+kXYwIrvIQKBgQDVnldDo2iq
|
||||||
|
TwLcZjXbreHskn/4hvWYUPqucEZ93jmyYNKUKPlXkVnc+kXnS0uuM5JZpi/7+FDkTqwHK83ET4/n
|
||||||
|
kTC9zM+K7KyIBbljclPjzXYJAW7nwD8A/vKx6CWi++f4buYc+lttsTprdAZ4/kWPTnvNJSjhSTAR
|
||||||
|
SQ32HxkiIQKBgQC+rjujW31WN4d2j48+K0B+7bIQON+VtmBZ48u2ZIQOi4PdoBvHv8HqQyhJlR+6
|
||||||
|
z49k5WczSqAXdG2+nIgs8fpjj0lc7YiMIYs0VsLodOToH9J2MfXjWi+A4Y2vbfcjfUuCWhKSZs6B
|
||||||
|
eMLNe1LPIBDmlT3A1X83qkCpvAYYQWAkwwKBgFVtslZRZk0dtfYwRf+phT1XxSe9yT/1uprCOd6i
|
||||||
|
XY6RnAU2cajsbvSpfgUmnoh3BWMmy+/HeYokUDW59ds5OkKQVN7CpolXZxQqvd4gXZ4vj7HASfsS
|
||||||
|
bd/XFXXCcjLA7R70MsCJ+sBebQ+F4gTHI0hRSb9bygJ2g2uWPKgd/a4hAoGABCtZIHxKpEz4iE4h
|
||||||
|
SrG1alEWOKaVtPdU6gJCHQ3bmVnRm1H56Yc23UF0qw84r2QEdadSd1ulXn3sPGO90oXD/NNQPljv
|
||||||
|
SGkfWxiekGil7LFtb6ot/zeknEPSTkiwQ7VkpkgD6fGXiFs0nzuYFvFTjUcsH4BLlNMDMPLsizE6
|
||||||
|
wfMCgYANvw4Lq1cVfHAl3f6IZlpWHPFEEJbPcBLu9+qtUlZjleCaWA8WXuiBxkqaIkeVi3JMst34
|
||||||
|
adfIfBsAk4FeyLpkiTYNjOckZvXFXYKA3a05l/RJ5rsnnI9GRh+3Gk3V+87OU7HwMU6jNZmQiPIO
|
||||||
|
/jerEvZ9A5tbuzKkfJj2F0ZXfw==
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
Loading…
Reference in New Issue