gpt4 book ai didi

android - 有没有办法在旧设备上的 Picasso 库中启用 TLS 1.2?

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:36:25 24 4
gpt4 key购买 nike

我的应用正在使用来自 HTTPS 源的图像,Solar Dynamics Observatory ,并且这些图像在具有 API 21 (5.0)(我认为 API 20 也可以工作)或更高版本的 Android 版本上加载得很好,但我无法从 API 16(最小 API)在 Android 版本上加载这些图像我将我的应用程序设置为 API 19。这是加载图像的代码,它非常基本 -

Picasso.with(this)
.load("https://sdo.gsfc.nasa.gov/assets/img/latest/latest_2048_HMIIC.jpg")
.placeholder(R.drawable.placeholdernew)
.error(R.drawable.errornew)
.into(mImageView, new com.squareup.picasso.Callback() {
@Override
public void onSuccess() {
mAttacher = new PhotoViewAttacher(mImageView); //this adds the zoom function after the picture is loaded successfully, so the user couldn't zoom the placeholder or error picture :)
}

@Override
public void onError() {
Log.d("Pic Error", "Loading Error");
}
});

如您所见,我的代码中没有错误(我认为 :P)。我用 SSLLabs 站点检查了 SDO 站点,这个站点说这个 SDO 服务器不接受 API 20 之前的 Android 设备上的 TLS 握手。有什么方法可以在旧的 Android 版本的 Picasso 中启用 TLS 1.2?帮助将不胜感激!提前致谢:)

最佳答案

好吧,这可行,但它很丑。

在你的项目的依赖中,添加:

compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.squareup.okhttp3:okhttp:3.6.0'
compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2'

(您可能已经有了 picasso 行——我只是确保您使用的是最新版本)

接下来,将此类添加到您的项目中(基于 this answer ):

  public static class TLSSocketFactory extends SSLSocketFactory {

private SSLSocketFactory internalSSLSocketFactory;

public TLSSocketFactory(SSLSocketFactory delegate) throws
KeyManagementException, NoSuchAlgorithmException {
internalSSLSocketFactory = delegate;
}

@Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}

@Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}

@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 {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}

@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
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));
}

/*
* Utility methods
*/

private static Socket enableTLSOnSocket(Socket socket) {
if (socket != null && (socket instanceof SSLSocket)
&& isTLSServerEnabled((SSLSocket) socket)) { // skip the fix if server doesn't provide there TLS version
((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2"});
}
return socket;
}

private static boolean isTLSServerEnabled(SSLSocket sslSocket) {
System.out.println("__prova__ :: " + sslSocket.getSupportedProtocols().toString());
for (String protocol : sslSocket.getSupportedProtocols()) {
if (protocol.equals("TLSv1.1") || protocol.equals("TLSv1.2")) {
return true;
}
}
return false;
}
}

(该类是public static,因此被设计成嵌套在其他东西中的类——如果你想让它成为一个独立类)

然后,在您使用 Picasso 的类中,添加此方法,基于 this issue comment :

  public X509TrustManager provideX509TrustManager() {
try {
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init((KeyStore) null);
TrustManager[] trustManagers = factory.getTrustManagers();
return (X509TrustManager) trustManagers[0];
}
catch (NoSuchAlgorithmException exception) {
Log.e(getClass().getSimpleName(), "not trust manager available", exception);
}
catch (KeyStoreException exception) {
Log.e(getClass().getSimpleName(), "not trust manager available", exception);
}

return null;
}

最后,这段代码应该会成功下载您的图片:

    SSLContext sslContext=SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
SSLSocketFactory noSSLv3Factory;

if (Build.VERSION.SDK_INT<=Build.VERSION_CODES.KITKAT) {
noSSLv3Factory=new TLSSocketFactory(sslContext.getSocketFactory());
}
else {
noSSLv3Factory=sslContext.getSocketFactory();
}

OkHttpClient.Builder okb=new OkHttpClient.Builder()
.sslSocketFactory(noSSLv3Factory, provideX509TrustManager());
OkHttpClient ok=okb.build();

Picasso p=new Picasso.Builder(getActivity())
.downloader(new OkHttp3Downloader(ok))
.build();

p.load(
"https://sdo.gsfc.nasa.gov/assets/img/latest/latest_2048_HMIIC.jpg")
.fit().centerCrop()
.placeholder(R.drawable.owner_placeholder)
.error(R.drawable.owner_error).into(icon);

(您可以在其中将我的 fit() 和后续调用替换为适合您的项目的调用)

如果您碰巧认识维护该 NASA 服务器的人员……他们真的应该升级他们的 SSL 支持。只是说说。

关于android - 有没有办法在旧设备上的 Picasso 库中启用 TLS 1.2?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42166667/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com