You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android使用OkHttp连接带自签名证书的WebSocket服务器失败

问题解决指南

先搞定域名解析错误(UnknownHostException)

你遇到的java.net.UnknownHostException是Android设备无法解析www.wslphone.com域名导致的,和WSS证书无关——毕竟连服务器地址都找不到,证书验证根本轮不上。

排查&修复步骤:

  • 先在Android设备的浏览器里输入https://www.wslphone.com,如果连证书警告都出不来,直接显示无法访问,说明确实是DNS问题:
    • 检查设备的DNS设置,切换到公共DNS(比如8.8.8.8或1.1.1.1)试试
    • 如果是本地测试的WSL服务器,必须给Android设备添加域名映射:
      1. 在WSL终端执行ip addr,找到eth0网卡的inet地址(比如192.168.1.100)
      2. 给Android设备的hosts文件加映射:
        • 已root设备:直接编辑/system/etc/hosts,添加一行192.168.1.100 www.wslphone.com
        • 未root设备:用adb命令临时添加(需电脑和设备同局域网):
          adb shell mount -o rw,remount /system
          adb shell echo "192.168.1.100 www.wslphone.com" >> /system/etc/hosts
          adb shell mount -o ro,remount /system
          
  • 验证:修改后再用浏览器访问域名,能弹出证书不安全的警告,就说明解析正常了。

配置OkHttp信任自签名证书(实现WSS连接)

既然你已经有生成keystore.p12的证书,直接把证书导入OkHttp的信任体系即可:

代码实现

  1. 将你的自签名证书(.crt/.pem格式)放到Android项目的res/raw目录下
  2. 编写SSL工具类:
import okhttp3.OkHttpClient;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

public class WSSClientUtil {
    public static OkHttpClient getTrustSelfSignedClient(InputStream certStream) {
        try {
            // 加载自签名证书
            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) certFactory.generateCertificate(certStream);

            // 初始化KeyStore
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            keyStore.setCertificateEntry("self-signed-cert", cert);

            // 构建信任管理器
            TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmFactory.init(keyStore);
            TrustManager[] trustManagers = tmFactory.getTrustManagers();

            // 初始化SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustManagers, null);
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            // 构建OkHttpClient
            return new OkHttpClient.Builder()
                    .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustManagers[0])
                    .hostnameVerifier((hostname, session) -> true) // 本地测试可跳过域名验证,正式环境必须移除
                    .build();
        } catch (Exception e) {
            throw new RuntimeException("Failed to create WSS client", e);
        }
    }
}
  1. 发起WSS连接:
// 读取raw目录下的证书
InputStream certInputStream = getResources().openRawResource(R.raw.your_cert_filename);
OkHttpClient wssClient = WSSClientUtil.getTrustSelfSignedClient(certInputStream);

// 构建WSS请求
Request wssRequest = new Request.Builder()
        .url("wss://www.wslphone.com:你的WSS端口")
        .build();

// 建立WebSocket连接
wssClient.newWebSocket(wssRequest, new WebSocketListener() {
    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        // 连接成功,可发送消息
        webSocket.send("Hello WSS!");
    }

    @Override
    public void onMessage(WebSocket webSocket, String text) {
        // 接收服务器消息
    }

    @Override
    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
        // 连接失败,打印错误信息
        t.printStackTrace();
    }
});

关键注意事项

  • 正式环境绝对不能跳过hostname验证,必须确保证书的CN字段或SAN扩展和你的域名完全匹配
  • 如果是WSL服务器,要确保WSL防火墙开放了WSS端口(比如ufw allow 8443),且设备和WSL在同一局域网(或做了端口映射)
  • 你已经能用wscat连接,说明服务器的WSS配置没问题,只要搞定Android端的域名解析和证书信任即可

内容的提问来源于stack exchange,提问作者Jaydeep Kasture

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 13:54:53