IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 微信退款 No appropriate protocol (protocol is disabled or cipher suites are inappropriate) -> 正文阅读

[网络协议]微信退款 No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

提供给正在弄微信支付踩坑的你,赶快弄完去干其他重要的事情!!!

测微信支付然后退款,出现这种问题是不是觉着很神奇,代码也没动,啥也没改为啥就出现问题了。线上也好好的,本地一测试就报出了下面的错误:

[ERROR][11:42:56] WechatRefundHelper:161 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)
	at sun.security.ssl.HandshakeContext.<init>(HandshakeContext.java:171)
	at sun.security.ssl.ClientHandshakeContext.<init>(ClientHandshakeContext.java:98)
	at sun.security.ssl.TransportContext.kickstart(TransportContext.java:220)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:428)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:395)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:354)
	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134)
	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)

出现这个问题的原因其实是 微信支付系统JDKjre 的不兼容,解决方式也主要针对于这两个方面,遇到的时候可以都尝试一下。建议先尝试修改代码,不行的话去查找对应的环境,真不行的话最后去修改 JDK 目录

1. 直接更改微信支付提供的代码(推荐)

这里就还是需要吐槽一下,这代码是不是好久没有更新了,哈哈哈!!!
官方 SDK 地址: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1

// 官方提供的坑代码
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());

SSLConnectionSocketFactory sslConnectionSocketFactory = 
				new SSLConnectionSocketFactory(
	                    sslContext,
	                    // 问题就出在下面这句话,直接改为 null
	                    new String[]{"TLSv1"},
                    	null,
                    	new DefaultHostnameVerifier());
                    	
      connManager = new BasicHttpClientConnectionManager(
      RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http",
                            PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", sslConnectionSocketFactory)
                            .build(), null, null, null
);

修改后如下:

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());

SSLConnectionSocketFactory sslConnectionSocketFactory = 
				new SSLConnectionSocketFactory(
	                    sslContext,
	                    null,
                    	null,
                    	new DefaultHostnameVerifier());
                    	
      connManager = new BasicHttpClientConnectionManager(
      RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http",
                            PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", sslConnectionSocketFactory)
                            .build(), null, null, null
);

【注】如果这种方式可以的话就强烈建议这种方式,不行的话就继续往下看。。。

2. 查找匹配的 JDK/jre 环境

如果是一上来开发就遇到还真的不好排查,但是我遇到的是线上没有问题,本地出现了这种问题,刚开始以为还是代码出现了 bug 后来发现,其实就是 JDK/jre 的问题。线上使用的是 OpenJDK,版本如下:

openjdk version "1.8.0_282"
OpenJDK Runtime Environment (build 1.8.0_282-b08)
OpenJDK 64-Bit Server VM (build 25.282-b08, mixed mode)

然而我本地使用的是:

openjdk version "1.8.0_292"
OpenJDK Runtime Environment (build 1.8.0_292-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)

但是版本差的那么小,应该是没啥问题,但是实际就是有这样的问题,最终也是换到与线上环境版本一致的 JDK 版本然后就没有问题。

这让我想起来之前遇到的也是 JDK 的版本问题: Error:(16, 42) java: package com.sun.org.apache.regexp.internal does not exist

都是泪 !!!

【注】如果是高于 JDK/jre 8 的还是使用先尝试第一种方式。不行的话就往下降低版本,然后结合方法三查找合适的 JDK/jre 版本。

3. 直接修改 jre 中 java.security 的默认限制

其实是不推荐这样改的,如果真到了这一步(第一种和第二种方式都阵亡了),那么就使用这种方式吧。

其实第二种换版本的方式也是为了解决 java.security 的默认限制,方法二示例中这两个 JDK/jrejava.security 配置。

  • 线上 OpenJDK 1.8.0_282java.security
// ....

jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
    EC keySize < 224, 3DES_EDE_CBC, anon, NULL
    
// ....
  • 本地 OpenJDK 1.8.0_292java.security
// ....

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    include jdk.disabled.namedCurves
    
// ....

【注】jdk.tls.disabledAlgorithmstls 的禁用策略。注释中也明确说明了:Disabled algorithms will not be negotiated for SSL/TLS connections, even if they are enabled explicitly in an application. (禁用的算法将不会为SSL/TLS连接进行协商,即使它们在应用程序中显式地启用)。

解决方法:

方法也不麻烦,先找到 JDK/jre 的位置(因为 Java 项目运行的时候使用的是 jre ,只有在开发和编译的时候才会使用 JDK。这里要注意下,因为 JDK 是包含 jre 的,线上改的时候可以只改 jre 目录即可;如果是本地开发,记得也要修改 JDK 中的配置):

# 以 jre 为例:

# 查找 java 命令的位置,一般 java 应该在 jre/bin 目录下;有的环境也有可能被设置为一个链接
which java
/usr/local/openjdk-8/bin/java

# 根据实际路径处理, jre 的位置一般在 JAVA_HOME 目录下(我这里的是 /usr/local/openjdk-8 )

# 进入 java.security 所在的目录
cd /usr/local/openjdk-8/jre/lib/security

# 接下来修改 java.security 即可,主要是修改 jdk.tls.disabledAlgorithms,对于微信的退款来说
# 将 TLSv1 从里面删掉即可,这样的话就可以使用了。
vim java.security

【注】其实这个方式还是有点坑的,就是使用的自定义修改后的 JDK/jre 环境,对于协同开发来说做不到很好的统一,所以不是很推荐,建议还是查找合适的 JDK/jre 处理。

个人博客:Roc’s Blog

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-11-28 11:37:38  更:2021-11-28 11:37:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年7日历 -2024/7/6 8:26:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码