如何让Android Retrofit的GET请求强制返回HTTPS响应?
问题
在个人Android应用中对接openexchangerates.org的API,使用两个接口:
https://openexchangerates.org/api/currencies.jsonhttps://openexchangerates.org/api/latest.json
调用currencies.json请求正常,日志如下:
0001 https://openexchangerates.org/currencies.json 0001 0.001 callStart --> GET https://openexchangerates.org/currencies.json Accept: application/json --> END GET 0001 0.010 proxySelectStart 0001 0.011 proxySelectEnd 0001 0.012 dnsStart 0001 0.052 dnsEnd 0001 0.061 connectStart 0001 0.174 secureConnectStart 0001 0.658 secureConnectEnd 0001 0.660 connectEnd 0001 0.661 connectionAcquired 0001 0.663 requestHeadersStart 0001 0.664 requestHeadersEnd 0001 0.864 responseHeadersStart 0001 0.864 responseHeadersEnd 0001 0.866 responseBodyStart 0001 0.867 responseBodyEnd 0001 0.871 requestHeadersStart 0001 0.872 requestHeadersEnd 0001 0.984 responseHeadersStart 0001 0.984 responseHeadersEnd <-- 200 OK https://openexchangerates.org/api/currencies.json (982ms) Access-Control-Allow-Origin: * Cache-Control: public Content-Type: application/json; charset=utf-8 Date: Wed, 27 Dec 2023 13:04:55 GMT Last-Modified: Thu, 23 Dec 2021 13:45:36 GMT Server: nginx/1.12.2 Vary: Accept-Encoding Connection: keep-alive 0001 0.988 responseBodyStart 0001 0.988 responseBodyEnd { "AED": "United Arab Emirates Dirham", "AFN": "Afghan Afghani", "ALL": "Albanian Lek",
但调用latest.json时出现异常:请求目标是HTTPS端点,响应却跳转到HTTP地址,日志如下:
0002 https://openexchangerates.org/latest.json?app_id=sdfgsdfgsdgsdfgsdgsdgsdgsdgsdgsdgsdg 0002 0.000 callStart --> GET https://openexchangerates.org/latest.json?app_id=sdfgsdfgsdgsdfgsdgsdgsdgsdgsdgsdgsdg Accept: application/json --> END GET 0002 0.003 connectionAcquired 0002 0.004 requestHeadersStart 0002 0.005 requestHeadersEnd 0002 0.008 responseFailed 0002 0.010 connectionReleased 0002 0.011 connectStart 0002 0.142 secureConnectStart 0002 0.554 secureConnectEnd 0002 0.555 connectEnd 0002 0.555 connectionAcquired 0002 0.556 requestHeadersStart 0002 0.558 requestHeadersEnd 0002 0.962 responseHeadersStart 0002 0.963 responseHeadersEnd 0002 0.964 responseBodyStart 0002 0.965 responseBodyEnd 0002 0.968 connectionReleased 0002 0.969 proxySelectStart 0002 0.970 proxySelectEnd 0002 0.971 dnsStart 0002 0.992 dnsEnd 0002 0.994 connectStart 0002 1.110 connectEnd 0002 1.111 connectionAcquired 0002 1.112 requestHeadersStart 0002 1.114 requestHeadersEnd 0002 1.224 responseHeadersStart 0002 1.225 responseHeadersEnd <-- 200 OK http://openexchangerates.org/api/latest.json?app_id=sdfgsdfgsdgsdfgsdgsdgsdgsdgsdgsdgsdg (1224ms) Access-Control-Allow-Origin: * Cache-Control: public Content-Type: application/json; charset=utf-8 Date: Wed, 27 Dec 2023 13:07:34 GMT Etag: W/"3c46229cfde06a956ce1b6198e484341" Last-Modified: Wed, 27 Dec 2023 13:00:00 GMT Server: nginx/1.12.2 Vary: Accept-Encoding Connection: keep-alive 0002 1.229 responseBodyStart 0002 1.230 responseBodyEnd
配置Retrofit禁止跟随重定向后,返回301响应,Location指向HTTP地址:
0002 https://openexchangerates.org/latest.json?app_id=sdfgsdfgsdgsdfgsdgsdgsdgsdgsdgsdgsdg 0002 0.000 callStart --> GET https://openexchangerates.org/latest.json?app_id=sdfgsdfgsdgsdfgsdgsdgsdgsdgsdgsdgsdg Accept: application/json User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 --> END GET 0002 0.002 connectionAcquired 0002 0.003 requestHeadersStart 0002 0.004 requestHeadersEnd 0002 0.155 responseHeadersStart 0002 0.156 responseHeadersEnd 0002 0.157 responseBodyStart 0002 0.157 responseBodyEnd <-- 301 Moved Permanently https://openexchangerates.org/latest.json?app_id=sdfgsdfgsdgsdfgsdgsdgsdgsdgsdgsdgsdg (157ms) Content-Type: text/html; charset=utf-8 Date: Wed, 27 Dec 2023 14:19:31 GMT Location: http://openexchangerates.org/api/latest.json?app_id=sdfgsdfgsdgsdfgsdgsdgsdgsdgsdgsdgsdg Referrer-Policy: strict-origin-when-cross-origin Server: nginx/1.12.2 Strict-Transport-Security: max-age=2592000 X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-Powered-By: PHP/5.5.9-1ubuntu4.21 Content-Length: 0 Connection: keep-alive <-- END HTTP (0-byte body) 0002 0.161 connectionReleased 0002 0.161 callEnd
请问为何目标是HTTPS端点却返回HTTP响应?有什么方法可以修正该问题?
原因分析
- 请求路径错误:调用
latest.json时使用的URL是https://openexchangerates.org/latest.json,缺少了正确的/api/前缀(和currencies.json的标准路径一致),触发了服务器的301永久重定向。 - 服务器配置问题:服务器返回的重定向Location头错误地使用了HTTP协议,尽管返回了HSTS头强制HTTPS,但自身重定向逻辑未正确生成HTTPS目标地址。
解决方法
1. 修正请求URL(推荐)
直接使用包含/api/前缀的正确HTTPS路径:https://openexchangerates.org/api/latest.json,从根源避免重定向触发,这是最简洁可靠的方案。
2. 拦截重定向并修正协议
如果无法修改请求URL,可在OkHttp(Retrofit底层依赖)中添加拦截器,自动将Location中的HTTP替换为HTTPS:
val redirectInterceptor = Interceptor { chain -> val originalResponse = chain.proceed(chain.request()) val location = originalResponse.header("Location") if (originalResponse.isRedirect && location?.startsWith("http://") == true) { val secureLocation = location.replaceFirst("http://", "https://") originalResponse.newBuilder() .header("Location", secureLocation) .build() } else { originalResponse } } val okHttpClient = OkHttpClient.Builder() .addInterceptor(redirectInterceptor) .build() val retrofit = Retrofit.Builder() .baseUrl("https://openexchangerates.org/") .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build()
3. 强制仅使用HTTPS连接
配置OkHttp的ConnectionSpec,拒绝HTTP连接,防止意外的HTTP跳转带来的安全风险:
val secureSpec = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .allEnabledCipherSuites() .allEnabledTlsVersions() .build() val okHttpClient = OkHttpClient.Builder() .connectionSpecs(listOf(secureSpec)) .build()
内容的提问来源于stack exchange,提问作者Hector
相关产品推荐
相关产品推荐

