javax.net.ssl.SSLPeerUnverifiedException: No peer certificate【已解决】

本文详细介绍了使用新浪微博Android SDK进行分享操作时遇到的SSL证书验证错误,并提供了具体的解决方案,包括添加信任管理器和必要的权限。

新浪微博 Android SDK 分享时出错,错误信息:

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
com.weibo.net.WeiboException: javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
	at com.weibo.net.Utility.openUrl(Utility.java:352)
	at com.weibo.net.Utility.openUrl(Utility.java:286)
	at com.weibo.net.Weibo.request(Weibo.java:149)
	at com.weibo.net.AsyncWeiboRunner$1.run(AsyncWeiboRunner.java:46)
	at com.weibo.net.AsyncWeiboRunner.request(AsyncWeiboRunner.java:52)


我看在Utility类中已经有了下面这段代码,不知道为什么还会出错.. Mark一下先


public static HttpClient getNewHttpClient(Context context) {
        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);

            SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            HttpParams params = new BasicHttpParams();

            HttpConnectionParams.setConnectionTimeout(params, 10000);
            HttpConnectionParams.setSoTimeout(params, 10000);

            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

            SchemeRegistry registry = new SchemeRegistry();
            registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            registry.register(new Scheme("https", sf, 443));

            ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

            // Set the default socket timeout (SO_TIMEOUT) // in
            // milliseconds which is the timeout for waiting for data.
            HttpConnectionParams.setConnectionTimeout(params, Utility.SET_CONNECTION_TIMEOUT);
            HttpConnectionParams.setSoTimeout(params, Utility.SET_SOCKET_TIMEOUT);
            HttpClient client = new DefaultHttpClient(ccm, params);
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            if (!wifiManager.isWifiEnabled()) {
                // 获取当前正在使用的APN接入点
                Uri uri = Uri.parse("content://telephony/carriers/preferapn");
                Cursor mCursor = context.getContentResolver().query(uri, null, null, null, null);
                if (mCursor != null && mCursor.moveToFirst()) {
                    // 游标移至第一条记录,当然也只有一条
                    String proxyStr = mCursor.getString(mCursor.getColumnIndex("proxy"));
                    if (proxyStr != null && proxyStr.trim().length() > 0) {
                        HttpHost proxy = new HttpHost(proxyStr, 80);
                        client.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, proxy);
                    }
                    mCursor.close();
                }
            }
            return client;
        } catch (Exception e) {
            return new DefaultHttpClient();
        }
    }

    public static class MySSLSocketFactory extends SSLSocketFactory {
        SSLContext sslContext = SSLContext.getInstance("TLS");

        public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException,
                KeyManagementException, KeyStoreException, UnrecoverableKeyException {
            super(truststore);

            TrustManager tm = new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType)
                        throws CertificateException {
                }

                public void checkServerTrusted(X509Certificate[] chain, String authType)
                        throws CertificateException {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };

            sslContext.init(null, new TrustManager[] { tm }, null);
        }

        @Override
        public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
                throws IOException, UnknownHostException {
            return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
        }

        @Override
        public Socket createSocket() throws IOException {
            return sslContext.getSocketFactory().createSocket();
        }
    }


最终我发现,原因是缺少个权限:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

新浪微博这个Android SDK写的也太差了, 好歹出个日志呢!浪费了我2个小时!

    public static HttpClient getNewHttpClient(Context context) {
        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);

            SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            HttpParams params = new BasicHttpParams();

            HttpConnectionParams.setConnectionTimeout(params, 10000);
            HttpConnectionParams.setSoTimeout(params, 10000);

            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

            SchemeRegistry registry = new SchemeRegistry();
            registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            registry.register(new Scheme("https", sf, 443));

            ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

            // Set the default socket timeout (SO_TIMEOUT) // in
            // milliseconds which is the timeout for waiting for data.
            HttpConnectionParams.setConnectionTimeout(params, Utility.SET_CONNECTION_TIMEOUT);
            HttpConnectionParams.setSoTimeout(params, Utility.SET_SOCKET_TIMEOUT);
            HttpClient client = new DefaultHttpClient(ccm, params);
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            if (!wifiManager.isWifiEnabled()) {
                // 获取当前正在使用的APN接入点
                Uri uri = Uri.parse("content://telephony/carriers/preferapn");
                Cursor mCursor = context.getContentResolver().query(uri, null, null, null, null);
                if (mCursor != null && mCursor.moveToFirst()) {
                    // 游标移至第一条记录,当然也只有一条
                    String proxyStr = mCursor.getString(mCursor.getColumnIndex("proxy"));
                    if (proxyStr != null && proxyStr.trim().length() > 0) {
                        HttpHost proxy = new HttpHost(proxyStr, 80);
                        client.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, proxy);
                    }
                    mCursor.close();
                }
            }
            return client;
        } catch (Exception e) {
            Log.e(TAG, e.getMessage(), e);
            return new DefaultHttpClient();
        }
    }




### Spring Boot与RabbitMQ中的SSL握手异常解决方案 在Spring Boot与RabbitMQ集成时,如果出现`javax.net.ssl.SSLHandshakeException: No trusted certificate found`的异常,通常表明客户端无法验证服务器提供的SSL证书。以下是解决此问题的详细方法: #### 1. 配置RabbitMQ服务器以支持SSL 确保RabbitMQ服务器已正确配置SSL/TLS。需要生成一个有效的SSL证书,并将其添加到RabbitMQ的配置文件中[^1]。以下是一个典型的RabbitMQ SSL配置示例: ```plaintext listeners.ssl.default = 5671 ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile = /path/to/server_certificate.pem ssl_options.keyfile = /path/to/private_key.pem ssl_options.verify = verify_peer ssl_options.fail_if_no_peer_cert = false ``` #### 2. 导入服务器证书到Java信任库 在Spring Boot应用程序中,必须将RabbitMQ服务器的SSL证书导入到Java的信任库(TrustStore)中。以下是具体步骤: - 使用`keytool`命令将服务器证书导入到Java的信任库: ```bash keytool -import -alias rabbitmq-server -keystore $JAVA_HOME/lib/security/cacerts -file server_certificate.pem ``` 默认密码为`changeit`,但可能因环境而异。 #### 3. 配置Spring Boot应用程序以支持SSL 在Spring Boot中,可以通过配置`application.properties`或`application.yml`文件来启用SSL连接。例如,在`application.properties`中添加以下内容: ```properties spring.rabbitmq.host=localhost spring.rabbitmq.port=5671 spring.rabbitmq.username=guest spring.rabbitmq.password=guest spring.rabbitmq.ssl.enabled=true ``` 如果需要自定义信任库路径和密码,可以设置以下属性: ```properties spring.rabbitmq.ssl.trust-store=/path/to/truststore.jks spring.rabbitmq.ssl.trust-store-password=your_truststore_password ``` #### 4. 自定义RabbitMQ连接工厂 如果上述配置仍无法解决问题,可以通过编程方式自定义RabbitMQ的连接工厂。以下是一个代码示例: ```java import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.net.ssl.TrustManagerFactory; import java.io.FileInputStream; import java.security.KeyStore; @Configuration public class RabbitMqConfig { @Bean public ConnectionFactory rabbitConnectionFactory() throws Exception { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setHost("localhost"); connectionFactory.setPort(5671); connectionFactory.setUsername("guest"); connectionFactory.setPassword("guest"); // 加载信任库 KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); try (FileInputStream fis = new FileInputStream("/path/to/truststore.jks")) { trustStore.load(fis, "your_truststore_password".toCharArray()); } TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(trustStore); connectionFactory.useSslProtocol(tmf.getTrustManagers()); return connectionFactory; } } ``` #### 5. 验证证书链 如果仍然遇到`No trusted certificate found`错误,可能是证书链不完整。确保服务器证书包含完整的中间证书链,并将其导出为单个PEM文件。例如: ```bash cat intermediate_ca.pem root_ca.pem > full_chain.pem ``` 然后更新RabbitMQ的`ssl_options.certfile`配置为新的完整链文件。 --- ### 总结 通过正确配置RabbitMQ服务器的SSL选项、将服务器证书导入Java信任库以及在Spring Boot应用程序中启用SSL支持,可以有效解决`javax.net.ssl.SSLHandshakeException: No trusted certificate found`问题[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值