解决Java REST客户端SSL握手异常:绕过证书与主机名验证

解决java rest客户端ssl握手异常:绕过证书与主机名验证

本文旨在解决Java REST客户端在使用`HttpURLConnection`调用HTTPS服务时遇到的`SSLHandshakeException`,特别是“No subject alternative names present”错误。文章将详细指导如何利用Apache HttpClient库,通过配置自定义SSL上下文来信任自签名或非标准证书,并禁用主机名验证,从而成功建立安全连接,克服原生API在严格证书校验下的限制。

理解SSL握手异常:证书与主机名验证

当Java应用程序通过HTTPS协议连接外部服务时,会执行SSL/TLS握手过程以建立加密通道。此过程中,客户端会验证服务器提供的SSL证书。javax.net.ssl.SSLHandshakeException,特别是其内部的java.security.cert.CertificateException: No subject alternative names present错误,通常发生在以下场景:

证书不匹配主机名: 服务器的SSL证书中,Subject Alternative Name (SAN) 字段未包含客户端尝试连接的主机名(或IP地址)。Java的默认SSL实现(如HttpURLConnection)会严格校验此项,如果证书的CN(Common Name)或SAN与URL中的主机名不符,即使证书本身有效,也会拒绝连接。自签名或非信任证书: 服务器使用自签名证书,或者其证书链未被Java默认的信任库(cacerts)所信任。

原生HttpURLConnection在处理这些非标准或特定场景的证书时,缺乏灵活的配置选项,导致开发者难以绕过严格的校验机制。

解决方案:使用Apache HttpClient进行灵活的SSL配置

为了解决上述问题,推荐使用功能更强大、配置更灵活的Apache HttpClient库。它允许开发者自定义SSL上下文,从而实现信任策略和主机名验证行为的定制。

立即学习“Java免费学习笔记(深入)”;

1. 引入Apache HttpClient依赖

首先,确保项目中包含了Apache HttpClient的相关依赖。在Maven项目中,可以添加如下依赖:

闪念贝壳 闪念贝壳

闪念贝壳是一款AI 驱动的智能语音笔记,随时随地用语音记录你的每一个想法。

闪念贝壳 218 查看详情 闪念贝壳

    org.apache.httpcomponents    httpclient    4.5.13     org.apache.httpcomponents    httpcore    4.4.13 

2. 配置自定义SSL上下文与连接管理器

以下代码示例展示了如何使用Apache HttpClient配置一个能够信任自签名证书并禁用主机名验证的REST客户端:

import org.apache.http.auth.AuthenticationException;import org.apache.http.auth.UsernamePasswordCredentials;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpPost;import org.apache.http.config.Registry;import org.apache.http.config.RegistryBuilder;import org.apache.http.conn.socket.ConnectionSocketFactory;import org.apache.http.conn.socket.PlainConnectionSocketFactory;import org.apache.http.conn.ssl.NoopHostnameVerifier;import org.apache.http.conn.ssl.SSLConnectionSocketFactory;import org.apache.http.conn.ssl.TrustSelfSignedStrategy;import org.apache.http.entity.StringEntity;import org.apache.http.impl.auth.BasicScheme;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;import org.apache.http.ssl.SSLContextBuilder;import org.apache.http.protocol.HTTP; // For HTTP.UTF_8import javax.net.ssl.SSLContext;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.security.KeyManagementException;import java.security.KeyStoreException;import java.security.NoSuchAlgorithmException;public class RestClientWithCustomSSL {    public static void main(String[] args) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException, AuthenticationException, ClientProtocolException, IOException {        String requestBody = "{"key": "value"}"; // 示例JSON请求体        String targetUrl = "https://xxx.xx.xxx.xx:port/restService"; // 目标URL        String username = "USERNAME";        String password = "PASSWORD";        // 1. 构建SSLContext,信任所有自签名证书        SSLContext sslContext = SSLContextBuilder.create()                .loadTrustMaterial(null, new TrustSelfSignedStrategy()) // 信任自签名证书策略                .build();        // 2. 创建SSLConnectionSocketFactory,禁用主机名验证        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(                sslContext,                NoopHostnameVerifier.INSTANCE // 禁用主机名验证        );        // 3. 注册HTTP和HTTPS连接工厂        Registry socketFactoryRegistry = RegistryBuilder.create()                .register("http", PlainConnectionSocketFactory.getSocketFactory())                .register("https", sslConnectionSocketFactory)                .build();        // 4. 使用连接管理器创建HttpClient        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);        cm.setMaxTotal(100); // 设置最大连接数        cm.setDefaultMaxPerRoute(20); // 设置每个路由的最大连接数        CloseableHttpClient client = HttpClients.custom()                .setSSLSocketFactory(sslConnectionSocketFactory) // 应用自定义的SSL Socket Factory                .setConnectionManager(cm)                .build();        try {            // 5. 创建POST请求            HttpPost request = new HttpPost(targetUrl);            // 6. 添加Basic认证头            UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);            request.addHeader(new BasicScheme().authenticate(creds, request, null));            // 7. 设置请求体和内容类型            StringEntity entity = new StringEntity(requestBody, HTTP.UTF_8);            request.setEntity(entity);            request.setHeader("Content-type", "application/json");            // 8. 执行请求并处理响应            CloseableHttpResponse response = client.execute(request);            try {                System.out.println("Response Status Line: " + response.getStatusLine());                BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));                String line = "";                StringBuilder result = new StringBuilder();                while ((line = rd.readLine()) != null) {                    result.append(line);                }                System.out.println("Response Body:n" + result.toString());            } finally {                response.close();            }        } finally {            client.close(); // 关闭HttpClient        }    }}

3. 核心组件解析

SSLContextBuilder: 用于构建自定义的SSLContext。TrustSelfSignedStrategy(): 这是一个TrustStrategy实现,它指示SSLContext信任所有自签名证书。在更严格的场景中,可以实现自定义的TrustStrategy来仅信任特定证书。NoopHostnameVerifier.INSTANCE: 这是一个HostnameVerifier实现,它不做任何主机名验证,直接返回true。这是解决“No subject alternative names present”问题的关键。SSLConnectionSocketFactory: 结合了自定义的SSLContext和HostnameVerifier,用于创建HTTPS连接。Registry: 注册不同协议(HTTP和HTTPS)的连接工厂,允许HttpClient同时处理两种类型的连接。PoolingHttpClientConnectionManager: 一个连接池管理器,用于管理HTTP连接的生命周期,提高性能和资源利用率。HttpClients.custom(): 用于创建自定义配置的CloseableHttpClient实例。UsernamePasswordCredentials 和 BasicScheme: 用于构建HTTP Basic认证头。

注意事项与安全考量

虽然上述方法能够有效解决SSLHandshakeException和主机名验证问题,但需要注意其潜在的安全风险:

禁用主机名验证 (NoopHostnameVerifier.INSTANCE) 的风险: 禁用主机名验证意味着客户端不再检查服务器证书中的主机名是否与请求的URL匹配。这会使应用程序容易受到中间人(Man-in-the-Middle, MITM)攻击。攻击者可以冒充目标服务器,而客户端无法察觉。信任自签名证书 (TrustSelfSignedStrategy) 的风险: 信任所有自签名证书会降低安全性,因为任何自签名证书都将被接受,包括恶意证书。在生产环境中,这可能导致安全漏洞。

推荐做法:

生产环境应避免禁用主机名验证和无差别信任证书。 最安全的做法是确保服务器使用由受信任CA签发的有效证书,并且证书中的SAN字段包含所有预期的主机名或IP地址。导入服务器证书到Java信任库: 如果必须连接使用自签名或内部CA签发证书的服务器,最安全的方法是将服务器的公共证书(或其CA证书)导入到Java运行环境的信任库($JAVA_HOME/jre/lib/security/cacerts)中。这可以通过keytool命令完成。自定义TrustStrategy: 如果需要更细粒度的控制,可以实现一个自定义的TrustStrategy,仅信任特定指纹或特定CA签发的证书。

总结

当Java HttpURLConnection在面对SSL证书的主机名不匹配或自签名证书时,会因严格的校验机制而抛出SSLHandshakeException。Apache HttpClient提供了一个更灵活的框架,允许开发者通过自定义SSLContext和HostnameVerifier来适应这些特殊场景。虽然禁用主机名验证和信任自签名证书可以快速解决问题,但在生产环境中,务必充分考虑其安全影响,并优先采用更安全的证书管理和验证策略。

以上就是解决Java REST客户端SSL握手异常:绕过证书与主机名验证的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/978985.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
冰柜故障排除
上一篇 2025年12月1日 20:24:18
sql 中 limit offset 组合用法_sql 中 limit offset 分页查询技巧
下一篇 2025年12月1日 20:24:19

相关推荐

  • 《忍者龙剑传4》明日发售 制作人谈亮点:经典与创新并存!

    白金工作室今日迎来《忍者龙剑传4》(ninja gaiden 4)制作人兼导演中尾裕治的特别公告,正式确认游戏将于10月21日(周二)全球上线。中尾在声明中详细介绍了本作的核心特色,强调在传承系列精髓的同时注入全新机制,为玩家打造既怀旧又充满惊喜的忍者冒险。 特色一:传承与进化的战斗系统 系列经典操…

    2026年9月21日
    000
  • mysqlmysql如何优化in条件大列表查询

    使用EXPLAIN和慢查询日志判断IN性能问题,type为ALL且possible_keys为空或rows过大说明需优化;JOIN在有索引时通常优于IN,尤其当列表值来自另一表时;大IN列表可拆分为多个小IN结合UNION ALL,或存入临时表后用JOIN提升效率。 优化 MySQL 中 IN 条件…

    2026年9月21日
    000
  • 拍摄更强了!vivo X200系列功能升级:舞台模式双视野录像来了

    10月15日,vivo正式公布x200系列功能迭代计划,影像系统与相册体验将迎来多项重磅升级。 据悉,全新的希区柯克式Live Photo功能将支持主体智能追踪,用户可一键实现流畅变焦效果,该功能预计从11月起逐步推送。 舞台模式双视野录制功能将于12月陆续上线, 用户可一键启动前后双摄,录制视频时…

    2026年9月21日
    000
  • Linux怎么踢出指定的登录用户

    要踢出指定登录用户,首先使用w或who命令识别其TTY或会话ID,再通过pkill -KILL -t 强制终止会话,或用loginctl terminate-session 优雅结束;若需防止重新登录,可临时锁定账户(passwd -l)或将用户shell改为/sbin/nologin。 在Linu…

    2026年9月21日
    000
  • edge浏览器如何安装Chrome网上应用店的扩展_edge浏览器安装Chrome扩展方法

    答案:可通过四种方法在Edge浏览器中安装Chrome扩展。1、直接从Chrome网上应用店添加扩展,Edge会自动识别并安装;2、手动下载CRX或ZIP文件,通过开启开发者模式加载已解压的扩展程序;3、从Crx4Chrome等第三方平台下载兼容扩展并按手动方式安装;4、对扩展的manifest.j…

    2026年9月21日
    000
  • 如何在Java中实现简单的输入输出

    使用Scanner类读取键盘输入,需导入java.util.Scanner并创建实例;2. 调用nextInt、nextLine等方法获取不同类型数据,注意nextInt不读取换行符可能导致nextLine读取空字符串;3. 推荐使用后关闭Scanner;4. 输出通过System.out.prin…

    2026年9月21日
    000
  • 何小鹏称飞行汽车市场份额将超汽车 家庭生活将巨变

    在10月16日启动的可持续全球领导者大会上,小鹏汽车创始人、董事长兼首席执行官何小鹏发表了主题演讲,深入阐述了公司在智能出行与人工智能技术方面的前沿战略。他透露,小鹏汽车预计将在2026年实现飞行汽车的量产,并坚信这一新兴领域的发展速度和市场潜力将远超传统汽车产业。 ☞☞☞AI 智能聊天, 问答助手…

    2026年9月21日
    000
  • iQOO 15开售:2K珠峰屏+自研Q3芯片 重塑手游视效新标杆

    iQOO 15开售:2K珠峰屏+自研Q3芯片 重塑手游视效新标杆iQOO 15开售:2K珠峰屏+自研Q3芯片 重塑手游视效新标杆iQOO 15开售:2K珠峰屏+自研Q3芯片 重塑手游视效新标杆iQOO 15开售:2K珠峰屏+自研Q3芯片 重塑手游视效新标杆

      备受瞩目的“未来性能旗舰”iqoo 15正式开售,起售价为4199元。作为iqoo推出的重磅力作,iqoo 15不仅延续了品牌一贯的硬核性能基因,更以“性能超长板,全面无短板”的产品理念,凭借第五代骁龙8至尊版、自研电竞芯片q3、2k三星珠峰屏、超级潜望长焦等顶级配置,全面刷新了高性能智能手机的…

    2026年9月21日 用户投稿
    100
  • Safari浏览器弹窗频繁怎么办 Safari浏览器弹窗拦截设置方法

    先设置全局拦截再允许特定网站弹窗。打开Safari设置→网站→弹出式窗口,将“访问其他网站时”设为“阻止”,再针对需使用弹窗的网站单独设为“允许”;iOS端在设置App中开启“阻止弹出式窗口”即可,必要时临时关闭。 如果你在使用 Safari 浏览器时被频繁弹窗打扰,可以按需设置全局或针对特定网站的…

    2026年9月21日
    000
  • 《哈迪斯2》95分年度必玩!外媒锐评”独立游戏崛起”

    《哈迪斯2》95分年度必玩!外媒锐评”独立游戏崛起”《哈迪斯2》95分年度必玩!外媒锐评”独立游戏崛起”《哈迪斯2》95分年度必玩!外媒锐评”独立游戏崛起”《哈迪斯2》95分年度必玩!外媒锐评”独立游戏崛起”

    外媒comicbook报道,2025年是游戏界的辉煌之年,多款新作在metacritic上评分突破90分,并获得“必玩”徽章。 《哈迪斯2》以95分的成绩成为本年度评分最高的游戏,强势领跑年度最佳游戏(GOTY)的激烈竞争,独立游戏的全面崛起也成为今年最瞩目的行业亮点。 《哈迪斯2》:95分封神,战…

    2026年9月21日 用户投稿
    100
  • 如何配置mysql初始用户和密码

    答案:MySQL安装后默认用户为root,密码为空或自动生成。需先确认服务运行,再登录并设置密码;若为空密码则直接登录后用ALTER USER修改,若为临时密码需从日志获取并强制修改;可创建远程用户并授权;推荐运行mysql_secure_installation进行安全加固,包括设密码、删匿名用户…

    2026年9月21日
    000
  • iPhone SE如何录制屏幕带声音的教程

    先添加录屏到控制中心并开启麦克风,再开始录制。打开设置→控制中心,添加屏幕录制按钮;录屏前长按录屏图标开启麦克风(变红),点击开始录制,倒计时3秒后启动,操作画面与声音同步记录,结束时点红色状态栏选停止,视频自动保存至照片App。 iPhone SE录制屏幕并带上声音,操作其实很简单。关键在于正确设…

    2026年9月21日
    000
  • 抖音扫码点单小程序介绍及使用方法解析

    抖音扫码点单小程序在哪里 引言: 在移动互联网迅猛发展的背景下,小程序已深度融入人们的日常生活。作为抖音生态中的重要一环,抖音扫码点单小程序为线下消费场景注入了新的活力,搭建起商家与用户之间高效互动的桥梁。本文将围绕其核心功能、具体操作流程以及市场数据表现等方面进行全面解读,助力用户和商户更好地掌握…

    2026年9月21日
    000
  • Linux如何查看默认网关

    使用ip route命令可查看默认网关,如ip route | grep default显示default via 192.168.1.1 dev eth0,其中192.168.1.1为网关地址。 在Linux系统中,查看默认网关是网络排查中的常见操作。可以通过命令行工具快速获取当前系统的默认路由信…

    2026年9月21日
    200
  • VSCode的快捷键映射冲突怎么办?

    首先查看快捷键绑定情况,通过Ctrl+K再Ctrl+S打开键盘快捷方式界面,搜索目标键组合如Ctrl+Shift+P,查看并识别冲突命令;接着右键冲突命令选择“更改键绑定”设置新组合或删除多余绑定;为精确定位,可查看命令ID如workbench.action.quickOpen区分相似命令;若调整较…

    2026年9月21日
    000
  • 打工人的全能 AI 搭档,就是戴尔灵越 16 Plus?

    打工人的全能 AI 搭档,就是戴尔灵越 16 Plus?打工人的全能 AI 搭档,就是戴尔灵越 16 Plus?打工人的全能 AI 搭档,就是戴尔灵越 16 Plus?打工人的全能 AI 搭档,就是戴尔灵越 16 Plus?

    进入2024年,无论是硬件厂商还是软件供应商,都开始加大力度,向公众宣扬ai对工作生活乃至游戏的影响。在这样的背景下,选择购买一台全新的笔记本,很难不考量它的ai能力对自身使用的影响。因此,我们可以看到办公轻薄本的 ” 常青树 ” ——戴尔灵越系列,也凭借搭载的英特尔酷睿 u…

    2026年9月21日 用户投稿
    400
  • mysql如何排查磁盘IO瓶颈

    首先检查系统级磁盘IO,使用iostat、iotop等工具分析磁盘利用率和进程IO行为;再通过MySQL慢查询日志、sys.schema视图及SHOW ENGINE INNODB STATUS排查高IO消耗的SQL与内部等待事件;接着评估innodb_buffer_pool_size、innodb_…

    2026年9月21日
    000
  • 在Java中如何创建一个天气查询小应用

    注册OpenWeatherMap获取API密钥;2. 使用Java 11+的HttpClient发送HTTP请求;3. 构造带城市参数的URL并调用天气接口;4. 解析返回的JSON数据提取温度和天气描述;5. 在控制台输出结果,支持中文城市需URL编码。 在Java中创建一个天气查询小应用,核心是…

    2026年9月21日
    000
  • MAC怎么查询硬件序列号_Mac查找本机序列号与保修信息

    首先可通过“关于本机”查看Mac序列号,依次点击苹果菜单→“关于本机”即可获取;也可通过“系统信息”或“终端”命令ioreg -l | grep IOPlatformSerialNumber查找;若无法操作设备,可登录Apple ID账户在线查询;最后访问苹果官网保修查询页面输入序列号,即可验证保修…

    2026年9月21日
    200
  • 在VSCode中如何安全地切换分支而不丢失当前修改?

    先处理未提交修改再切换分支。可通过提交更改、使用Stash保存临时修改,或选择性暂存部分文件来安全切换,并在切换后恢复贮藏的更改,避免代码丢失。 在 VSCode 中切换分支时,如果当前有未提交的修改,直接切换可能会导致冲突或代码丢失。要安全切换分支,关键是先处理好当前的更改。以下是几种稳妥的方法。…

    2026年9月21日
    100

发表回复

登录后才能评论
关注微信