前言
部门有个项目涉及到邮件发送,发送功能在本地测试可以成功发送,但是打包部署到docker环境中,却出现
No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
后面在网上搜索了一下,查到了这篇文章
https://stackoverflow.com/questions/67742776/docker-container-error-javax-mail-messagingexception-no-appropriate-protocol
这篇文章有个答主提到,他使用的版本的jdk 8u292,这个版本已经禁用了不安全的TLSv1&TLSv1.1,于是我就查了一下我们部署的docker基础镜像jdk版本,为jdk8u332。后面再搜索了一下解决方案,大部分的解决方案都是通过修改java.security文件中的jdk.tls.disabledAlgorithms配置,删除掉TLSv1&TLSv1.1来解决
但是这种方案给我的感觉,有那么点欠妥。毕竟jdk禁用TLSv1&TLSv1.1应该是经过考量的。所以一开始我就先把这个方案作为其他方案都无法解决的时候,最终兜底方案。下面就来回顾 一下,我的解决历程
解决历程
方案一:将mail.smtp.ssl.protocols配置为TLSv1.2
但改完后,报了如下异常
The server selected protocol version TLS10 is not accepted by client preferences [TLS12]
因为server端支持的TLSv1.0,因此没招,mail.smtp.ssl.protocols就不能改为TLSv1.2
方案二:将javax.mail的包换成com.sun.mail
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
该方案是来源如下博文
https://blog.csdn.net/qq_33601179/article/details/123069499
他通过调整mail的gav解决,但我经过实验,发现该方案并没解决我的问题,仍然会报
No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
方案三:进入docker容器内部,修改java.security文件中的jdk.tls.disabledAlgorithms配置,删除掉TLSv1&TLSv1.1
网上查了资料,大多数都是通过宿主机去修改java.security,通过docker去修改,基本上没看到。
不过我们可以通过进入容器docker内部,进行修改。但要修改java.security,首先就得知道java.security文件的位置。不同的基础镜像,java.security文件的位置可能是不一样的。
那如何知道java.security的具体位置呢? 这边提供一个思路,如果是自制的基础镜像,可以去问公司自制这个镜像的作者,如果是公有的镜像,可以通过docker hub,比如我们这个项目的镜像是用到skywalking-java-agent:8.11.0-java8,因此我们就可以去docker hub,搜索该镜像,然后点开详情,里面有的会有IMAGE LAYERS
由这个就可以知道java的基本路径,然后进入容器内部
我们就可以通过vim命令去修改java.security文件内容,不过正常修改的时候,要装下vim
apt-get update
apt-get install vim
修改完重启一下容器,然后通过访问 ip:端口/actuator/health,前提要引入actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
并配置
endpoint:
health:
show-details: always
查看mail的健康状态
或者可以直接发送测试邮件,验证也可以
方案四:调整Dockerfile
其实方案四的实现逻辑和方案三是一样的,核心也是修改java.security文件中的jdk.tls.disabledAlgorithms配置,删除掉TLSv1&TLSv1.1。但方案三有个弊端是,每次发版后,都要重新进入docker容器内部修改。方案四的方案是
在Dcokerfile文件里面添加如下内容
RUN sed -i 's/jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1/jdk.tls.disabledAlgorithms=SSLv3/g' /opt/java/openjdk/lib/security/java.security
本质就是在构建业务镜像时,同时修改java.security内容,最终达到和方案三一样的效果
方案五:降低jdk版本
这种方案虽然也可以达到效果,但是不建议就是,毕竟换了jdk,可能会导致其他不可预知的问题
总结
这几种方案,因为1,2方案达不到目的,所以只能在3,4,5这三种方案选,基本上大多数都会选择方案四。不过虽然是解决问题,但是始终感觉不是最佳方案,最佳方案可能是不改jdk内容,通过其他方式改,但暂时又没其他思路,如果有更好的方案,大家可以留言告知