跳到主要内容
ecdsa.com
Java (JSSE)Java

错误信息

No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

也可能输出为

  • javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

从 JDK 8 的各个更新版本到 JDK 25,措辞都一样。JVM 作为服务端时,如果自身的协议全部被禁用,同样的情况会显示为“No appropriate protocol”。

Java (JSSE) — the client itself has no enabled protocol/cipher combination left

含义

JVM 连 ClientHello 都没能构建出来:去掉 jdk.tls.disabledAlgorithms 中列出的所有协议和密码套件之后,应用请求的内容一项都不剩了。通常是代码或配置坚持要用 TLS 1.0、TLS 1.1 或 SSLv3,而当前的 JDK 已全部禁用它们。没有向服务器发送任何数据。

原因

修复方法

  1. 1.

    找出在哪里请求了旧协议

    在代码和 JVM 选项中搜索显式写出的协议名称;-XshowSettings:security:tls 会显示 JDK 启用了哪些内容。

    bash
    grep -rnE 'SSLContext.getInstance\("(TLSv1|TLSv1\.1|SSL)"\)|setEnabledProtocols|https\.protocols' src/
    java -XshowSettings:security:tls -version 2>&1 | sed -n '/Enabled Protocols/,/Enabled Cipher/p'
  2. 2.

    请求“TLS”,由 JSSE 自行协商

    在当前的 JDK 上,SSLContext.getInstance("TLS") 会启用 TLS 1.3 和 1.2。

    java
    // Let JSSE negotiate the best version (TLS 1.3 / 1.2)
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(null, null, null);
  3. 3.

    最后手段:为单个旧端点做小范围覆盖

    如果某台设备无法升级,可以用单独的安全属性文件,为与它通信的那个 JVM 从 jdk.tls.disabledAlgorithms 中去掉 TLSv1/TLSv1.1。以 JDK 当前的完整取值为基础,只修改协议相关的条目,并把这个 JVM 隔离开。

    bash
    # Last resort for ONE legacy endpoint: take this JDK's own value and drop only TLSv1/TLSv1.1
    v=$(sed -n '/^jdk.tls.disabledAlgorithms=/,/[^\\]$/p' "$JAVA_HOME/conf/security/java.security" | sed 's/\\$//' | tr -d '\n')
    printf '%s\n' "$v" | sed -E 's/ TLSv1(\.1)?,//g' > legacy-tls.security
    java -Djava.security.properties=legacy-tls.security -jar legacy-client.jar

相关错误

浏览完整的签名错误库