Android中使用Retrofit发起HTTPS请求失败问题求助
Hey there! Let's figure out why your HTTPS request isn't working while HTTP does. I've gone through your code and spotted a few key issues that might be causing the problem.
First, Let's Fix the Obvious Issues
1. Incorrect Basic Authentication Header
Your current interceptor adds a Basic header directly, which isn't the standard way to send HTTP Basic auth. The correct approach is to use the Authorization header with a value formatted as Basic [base64-encoded credentials].
For example, if your API key is the username with an empty password, you need to encode apikey: (note the colon) to Base64 and prepend Basic .
2. Hostname Verifier Compatibility
You're using Apache's SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER, which might not play nicely with OkHttp. Instead, implement a simple custom HostnameVerifier that trusts all hostnames (for testing only, of course).
3. OkHttpClient Construction
While OkHttp 2 allows direct set calls, using the Builder pattern ensures all your configurations are properly applied to the client instance.
Corrected Code for getUnsafeOkHttpClient()
public static OkHttpClient getUnsafeOkHttpClient() { try { final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } }; final SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustAllCerts, new SecureRandom()); final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.sslSocketFactory(sslSocketFactory); // Custom hostname verifier for testing builder.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); // Fixed authentication header builder.addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { // Encode your API key properly for Basic auth String credentials = "apikey:"; // Adjust if you have a password String base64Encoded = Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); Request request = chain.request().newBuilder() .header("User-Agent", "Android") .header("Authorization", "Basic " + base64Encoded) .build(); return chain.proceed(request); } }); return builder.build(); } catch (Exception e) { throw new RuntimeException(e); } }
Why This Fixes the Problem
- Auth Header Fix: Servers often enforce strict header validation for HTTPS requests (since it's supposed to be secure), so the malformed
Basicheader was likely being rejected. HTTP might have been more lenient or not requiring auth at all. - Hostname Verifier: Using OkHttp's native
HostnameVerifierinterface avoids compatibility issues with Apache's implementation. - Builder Pattern: Ensures all your SSL settings and interceptors are attached to the client that Retrofit uses, instead of potentially modifying a separate instance.
Important Note for Production
Trusting all certificates (trustAllCerts) is only safe for testing. In production, you should import your server's CA certificate into your app to establish a secure HTTPS connection. This prevents man-in-the-middle attacks and complies with security best practices.
内容的提问来源于stack exchange,提问作者Mihovil Maricic

