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

错误信息

The server selected protocol version TLS10 is not accepted by client preferences [TLS13, TLS12]

也可能输出为

  • javax.net.ssl.SSLHandshakeException: (protocol_version) The server selected protocol version TLS10 is not accepted by client preferences [TLS13, TLS12]

所选版本(TLS10、TLS11)和方括号中的列表,取决于服务器以及 JVM 启用的协议。JDK 21 及更高版本会在异常文本前加上“(protocol_version) ”。直接拒绝而不是降级的服务器,会导致“Received fatal alert: protocol_version”。

Java (JSSE) — the server picked a TLS version the JVM does not allow

含义

JVM 提供的是 TLS 1.3 和 1.2,但服务器无视这一点,以 TLS 1.0(TLS10)或 1.1(TLS11)作出回应,而 JVM 不接受这两个版本。Java 在自己这一端中止握手。服务器对当前的客户端来说太旧了;任何已更新到最新的 JDK、浏览器和 curl 都会有同样的反应。

原因

修复方法

  1. 1.

    在服务器上启用 TLS 1.2 或更高版本

    这是对所有客户端都有效的修复方法。TLS 1.0 和 1.1 已被正式弃用(RFC 8996)。

    text
    # Enable TLS 1.2 (and 1.3) on the server or appliance
    ssl_protocols TLSv1.2 TLSv1.3;                 # nginx
    SSLProtocol -all +TLSv1.2 +TLSv1.3             # Apache httpd
  2. 2.

    确认服务器缺少 TLS 1.2

    如果 TLS 1.2 握手失败而 TLS 1.0 成功,就必须升级服务器。

    bash
    echo | openssl s_client -connect legacy.example.com:443 -servername legacy.example.com -tls1_2 -brief
  3. 3.

    最后手段:在单个隔离的 JVM 中允许 TLS 1.0/1.1

    以 JDK 自身的取值为基础构建的安全属性覆盖,只会为那个 JVM 重新启用旧版本。TLS 1.0/1.1 依赖存在已知弱点的 SHA-1 和 CBC 构造,因此只能在受信任的网络中这样做,并在设备更换后立即删除这项覆盖。

    bash
    # Last resort for ONE JVM that must reach the legacy server: drop TLSv1/TLSv1.1 from
    # this JDK's own jdk.tls.disabledAlgorithms value and pass it as an override
    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

相关错误

浏览完整的签名错误库