如何在Square MockWebServer中使用SSL?

8cdiaqws  于 2022-09-21  发布在  Android
关注(0)|答案(4)|浏览(235)

我尝试在Square's MockWebServer上启用SSL,以模拟我测试下的Android应用中的所有WebService调用。我希望使SSL能够像在真实条件下一样获得相同的错误。我不想为测试禁用SSL,也不想实现忽略SSL的HTTPClient。

每次请求时,我都会收到这个javax.net.ssl.SSLPeerUnverifiedExceptionecxeption

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://localhost:42451/api/blabla": No peer certificate; nested exception is javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

我似乎需要为MockWebServer设置证书。但我不知道怎么..。

以下是我尝试启用SSL的方法:

SSLContext sslContext = new SslContextBuilder(InetAddress.getLocalHost().getHostName()).build();
server.useHttps(sslContext.getSocketFactory(), true);

或者:

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, null, null);
server.useHttps(sslContext.getSocketFactory(), false);

有人能帮忙吗?

bvhaajcl

bvhaajcl1#

您将需要创建自己的密钥库:

keytool -genkey -v -keystore mystore.keystore.jks -alias alias_name -keyalg RSA -keysize 2048 -validity 10000

或参阅:https://developer.android.com/studio/publish/app-signing.html

创建密钥库后,将其加载到您的代码中并按以下方式使用它:

FileInputStream stream = new FileInputStream("mystore.keystore.jks");
        char[] serverKeyStorePassword = "yourcode".toCharArray();
        KeyStore serverKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        serverKeyStore.load(stream, serverKeyStorePassword);

        String kmfAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgorithm);
        kmf.init(serverKeyStore, serverKeyStorePassword);

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(kmfAlgorithm);
        trustManagerFactory.init(serverKeyStore);

        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(kmf.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
        SSLSocketFactory sf = sslContext.getSocketFactory();
        mockWebServer.useHttps(sf, false);
w9apscun

w9apscun2#

here所述,实现此目的的一种方法是执行以下操作:

首先创建自签名证书和私钥,并将它们添加到项目中。一个文件应该同时包含证书和私钥,这将与MockWebServer一起使用。另一个只包含证书,这将在网络安全配置中使用。

val localhost = InetAddress.getByName("localhost").getCanonicalHostName()
val localhostCertificate = HeldCertificate.Builder()
    .addSubjectAlternativeName(localhost)
    .duration(10 * 365, TimeUnit.DAYS)
    .build()
// Print public key
println(localhostCertificate.certificatePem())
// Print private key
println(localhostCertificate.privateKeyPkcs8Pem())

将证书添加到网络安全配置

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <debug-overrides>
        <trust-anchors>
            <certificates src="@raw/debug_cert"/>
        </trust-anchors>
    </debug-overrides>
</network-security-config>

然后将证书与MockWebServer一起使用

val localhostCertificate =
        HeldCertificate.decode("instrumentation_cert.pem".loadString())

    val serverCertificates = HandshakeCertificates.Builder()
        .heldCertificate(localhostCertificate)
        .build()

    server.useHttps(
        serverCertificates.sslSocketFactory(),
        tunnelProxy = false,
    )
xxslljrj

xxslljrj3#

您可以使用okhttp-tls中的帮助器生成本地主机证书,并将其用于MockWebServerOkHttpClient
使用TLS的简单易用的API。

HeldCertificate是证书及其私钥。使用构建器创建测试服务器可用于HTTPS的自签名证书:

String localhost = InetAddress.getByName("localhost").getCanonicalHostName();
HeldCertificate localhostCertificate = new HeldCertificate.Builder()
   .addSubjectAlternativeName(localhost)
   .build();

HandshakeCertificates保留用于TLS握手的证书。使用其构建器定义HTTPS服务器向其客户端返回哪些证书。返回的示例可以创建实现此策略的SSLSocketFactory

HandshakeCertificates serverCertificates = new HandshakeCertificates.Builder()
    .heldCertificate(localhostCertificate)
    .build();
MockWebServer server = new MockWebServer();
server.useHttps(serverCertificates.sslSocketFactory(), false);
server.start();

HandshakeCertificates还适用于其工作是定义要信任的根证书的客户端。在这个简化的示例中,我们信任服务器的自签名证书:

andshakeCertificates clientCertificates = new HandshakeCertificates.Builder()
    .addTrustedCertificate(localhostCertificate.certificate())
    .build();
OkHttpClient client = new OkHttpClient.Builder()
    .sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager())
    .build();
kkbh8khc

kkbh8khc4#

我是这样做的:

MockWebServer serverForHttps = new MockWebServer();
 serverForHttps .useHttps(SslContextBuilder.localhost().getSocketFactory(), false);
 serverForHttps .start()

这对我很管用。

相关问题