https请求报错:javax.net.ssl.SSLHandshakeException:Received fatal alert: unrecognized_name 的解决过程

项目场景:

提示:本地调试正常:
项目场景:
部署到WebSphere服务器上就会报上述错误;
一度认为是WebSphere服务器上的配置有问题,经过多次偿试,最终解决问题发现和服务配置无关;
测试环境使用HttpClient发送https请求下载附件时报错:


问题描述

提示:项目地址是http,需要访问的地址是https:

因为访问https地址所以默认信任所有证书:

    /**
     * 创建 HttpClient 客户端代码
     * @return org.apache.http.impl.client.CloseableHttpClient
     * @Author xianzi
     * @CreateTime 2022/10/17 15:53
     * @Description 信任所有证书
     **/
    public static CloseableHttpClient createSSLClientDefault() {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                // 信任所有
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
            HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
            //"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"
//            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"SSLv1.2"}, null, hostnameVerifier);
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();

    }

使用httpclient发送https请求下载附件时报错:

javax.net.ssl.SSLHandshakeException: Received fatal alert: unrecognized_name
at com.ibm.jsse2.i.a(i.java:31)
~[?:8.0 build 201512221
at com.ibm.jsse2.i.ali.java:43)~?:8.0 build 201512221
at com.ibm.jsse2.as.blas.java:816) -?:8.0 build 201512221
at com.ibm.jsse2.as.alas. java: 752)
~?:8.0 build 201512221
at
com.ibm.jsse2.as.i(as.java:130)
~?:8.0 build 201512221
at
com.ibm.jssez.as.a(as.java:483) ~ ?:8.0 build 201512221
com.ibm.jsse2.as.startHandshake(as.java:160)
~[?:8.0 build 201512221

附图:在这里插入图片描述
此处看报错信息曾怀疑是服务器使用的是ibmjdk导致的错误,但是后续解决问题之后证实这个方向是错误的


原因分析:

https认证方式分为2种(单向认证、双向认证):

单向认证:

单向认证一般是指客户端确认服务端身份(也就是我常用的不安全认证模式)
上面代码也确实证实了单向认证请求https是没有问题的;

双向认证:

双向认证则是指在客户端需要确认服务端身份的同时,服务端也需要确认客户端的身份。
接下来也是我解决此错误的原因


网上搜索到的解决方案,偿试无效的有

一、设置系统属性,在启动类加上下列代码无效:

System.setProperty ("jsse.enableSNIExtension", "false");

二、在JVM启动命令中加入指令无效:
-Djsse.enableSNIExtension=false

三、将上面指令配置到tomcat中(没有偿试过)
最终也不是通过此方案解决错误

解决方案:

请求双向认证的https地址时,客户端需要初始化证书及证书版本,客户端会根据根证书生成携带公钥的子证书发服务端发送二次握手,服务端会验证客户端的请求是否合法,至此问题解决.代码如下:

    /**
     * 双向认证请求客户端创建
     * @Author xiangzi
     * @CreateTime 2022/10/17 16:29
     */
    public static CloseableHttpClient creatTwoWayHttpClient() {
        try {
            CloseableHttpClient httpclient;
            //     SSLContext ctx = SSLContexts.createSystemDefault();
            //      SSLConnectionSocketFactory fac =
            //          new SSLConnectionSocketFactory(ctx, new String[] {"TLSv1.2"}, null,
            //              SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            //      httpclient = HttpClientBuilder.create().setSSLSocketFactory(fac).build();
            SSLContext ctx = SSLContexts.custom().useProtocol("TLSv1.2").build();
            httpclient = HttpClientBuilder.create().setSslcontext(ctx).build();
//            HttpPost httpPost = new HttpPost(url);
//            CloseableHttpResponse resp = httpclient.execute(httpPost);
//            System.out.println("===SSL版本:   "+v+"测试附件test====结束"+resp.toString());
            return httpclient;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }

暂未实现 单向验证和双向验证请求兼容初始化客户端代码,只是在使用时加了一个参数区分;代码如下:

    /**
     * @param isTwoWayAuthentication true 表示发送HTTPS请求对方为双向验证域名
     * 创建 HttpClient 客户端代码
     * @return org.apache.http.impl.client.CloseableHttpClient
     * @Author xianzi
     * @CreateTime 2022/10/17 15:53
     * @Description 信任所有证书
     **/
    public static CloseableHttpClient createSSLClientDefault(Boolean isTwoWayAuthentication) {
        try {
            if (isTwoWayAuthentication) {
                return creatTwoWayHttpClient();
            }
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                // 信任所有
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
            HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
            //"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"
//            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"SSLv1.2"}, null, hostnameVerifier);
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();

    }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值