抱歉我的英文。我尝试使用libruary OKhttp,并使用 https 进行帖子请求。现在我有错误,当我尝试发布我的例子时,这是错误:
java.net.UnknownServiceException: Unable to find acceptable protocols. isFallback=false, modes=[ConnectionSpec(cipherSuites=[TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA], tlsVersions=[TLS_1_2], supportsTlsExtensions=true)], supported protocols=[SSLv3, TLSv1]
我尝试修复它,但我不能这样做。我不知道我有什么错误
吼叫我的代码:
public class PostOKhttp extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String...ulr) {
Response response = null;
OkHttpClient client = new OkHttpClient();
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
.build();
client.setConnectionSpecs(Collections.singletonList(spec));
RequestBody postForm = new FormEncodingBuilder()
.add("name", "name")
.build();
Request request = new Request.Builder()
.url(ulr[0])
.addHeader("id", "--")
.addHeader("key", "--")
.post(postForm)
.build();
try {
response = client.newCall(request).execute();
Log.e("post", response.body().string());
} catch (Exception e) {
Log.e("error", e.toString());
}
return null;
}
@Override
protected void onPostExecute(String result) {
}
UDP:
使用 CertificatePinner
我添加此代码
String link = "example.net";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(link, "sha1/DmxUShsZuNiqPQsX2Oi9uv2sCnw=")
.add(link, "sha1/SXxoaOSEzPC6BgGmxAt/EAcsajw=")
.add(link, "sha1/blhOM3W9V/bVQhsWAcLYwPU6n24=")
.add(link, "sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=")
.build();
client.setCertificatePinner(certificatePinner);
现在我有这个错误:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
答案 0 :(得分:10)
实际上,默认情况下 Android&lt; 5 上的问题 TLSv1.1 和 TLSv1.2 未启用,并且使用这些最新版连接我们必须在Android&lt; 5设备中启用安全协议。
因为默认情况下,Android设备选择支持最高的协议来建立连接,但默认情况下不启用最高/最新安全协议(例如TLSV1.1或TLSV1.2)(仅启用SSLV3.0或TLSV1。 0)。
在Android&lt;中启用TLSV1.1和TLSV1.2 5 强>
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
/**
* @author Bajrang Hudda
*/
public class MyTLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
public MyTLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
internalSSLSocketFactory = context.getSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if(socket != null && (socket instanceof SSLSocket)) {
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
}
return socket;
}
}
现在将其添加到您的Okhttpclient中 -
protected static OkHttpClient getHttpClient(long timeout){
String hostname = Constants.HOST_NAME_DEBUG;
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, "sha1/mBN/TTGneHe2Hq0yFG+SRt5nMZQ=")
.add(hostname, "sha1/6CgvsAgBlX3PYiYRGedC0NZw7ys=")
.build();
//specifying the specs; this is impotent otherwise android <5 won't work
//And do note to include the android < 5 supported specs.
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_1, TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
.build();
final OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setCertificatePinner(certificatePinner);
okHttpClient.setConnectionSpecs(Collections.singletonList(spec));
try
{
// enabling the tlsv1.1 and tlsv.2
okHttpClient.setSslSocketFactory(new MyTLSSocketFactory());
} catch (KeyManagementException e)
{
e.printStackTrace();
} catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
return okHttpClient;
}
现在最后在你的改造中添加它 -
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(Constants.API_URL)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setErrorHandler(new ErrorHandler())
.setClient(getHttpClient())
.setRequestInterceptor(new SecureHeaderInterceptor(null))
.build();
就是这样,Happy Coding: - )
答案 1 :(得分:4)
如果需要TLS支持,您需要使用ProviderInstaller
检查并安装。在您的条目Activity
上使用类似的内容,它应该可以解决问题。查看更多信息here
protected void checkTls() {
if (android.os.Build.VERSION.SDK_INT < 21) {
try {
ProviderInstaller.installIfNeededAsync(this, new ProviderInstaller.ProviderInstallListener() {
@Override
public void onProviderInstalled() {
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
SSLEngine engine = sslContext.createSSLEngine();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
@Override
public void onProviderInstallFailed(int i, Intent intent) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}