手记

记一次部署在docker环境项目发送邮件出现No appropriate protocol

前言

部门有个项目涉及到邮件发送,发送功能在本地测试可以成功发送,但是打包部署到docker环境中,却出现

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

后面在网上搜索了一下,查到了这篇文章

这篇文章有个答主提到,他使用的版本的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内容,通过其他方式改,但暂时又没其他思路,如果有更好的方案,大家可以留言告知

0人推荐
随时随地看视频
慕课网APP