烂笔头笔记:为JDK安装Charles证书,让你的请求能够像在浏览器中那样被抓包

为什么要为JDK安装Charles证书

众所周知,https就是为了防止中间过程被拦截从而导致数据泄密的。若强行加入Charles代理,数据被解密后再被其重新加密,数据已经被"破坏",客户端从而拒绝建立连接或解析内容。
发起请求并加密 拆包解密再加密 加密 拆包解密再加密 浏览器/移动设备 Charles代理 接口服务端

以往想要在浏览器或者移动设备环境中抓取到调用了哪些https接口,需要向系统或者移动设备中安装Charles根证书,并添加信任。具体操作方式为:
安装 信任区 安装 信任 网络库 中间根证书 浏览器 系统证书管理 移动设备 证书信任 APP

但是JDK或者JVM有点特殊,它有它自己的证书管理体系(keystore),按照以往的方式安装并信任Charles根证书是不起作用的。

保存Charles根证书

在菜单Help一栏中找到SSL Proxying项目,选择"Save Charles Root Certificate",如下图所示:

找一个目录,输入文件名,将其保存。这里注意选择文件类型为:Base 64 encoded certificate(.pem)格式的:

将Charles根证书添加至JDK(JVM)的证书信任区(keystore)

打开命令终端(Linux/macOS)或者命令提示符(Windows)。将当前目录切换至JAVA_HOME。
注意:如果你的系统中有多个版本的JDK(JVM),或者重新安装了JDK(JVM),则需要重复本步骤

然后进入相对的这个目录(Linux/macOS):

复制代码
jre/lib/security

或者(Windows)

复制代码
jre\lib\security

执行如下命令(以Windows环境为例,可能需要管理员权限):

复制代码
keytool -import -alias charles -keystore cacerts -file d://docs/cert//charles_root_certificate.pem

JDK(JVM)默认的keystore是一个名为"cacerts"的文件。命令中给新导入的根证书取了一个别名,叫做:"charles"。最后一个参数为上一步保存的Charles根证书完整文件名

执行过程中会提示用户输入"输入密钥库口令",默认为空

执行后会读取Charles根证书的基本信息。大概内容如下:

复制代码
所有者: C=NZ, ST=Auckland, L=Auckland, O=XK72 Ltd, OU=https://charlesproxy.com/ssl, CN="Charles Proxy CA (31 May 2024, MYPCNAME)"
发布者: C=NZ, ST=Auckland, L=Auckland, O=XK72 Ltd, OU=https://charlesproxy.com/ssl, CN="Charles Proxy CA (31 May 2024, MYPCNAME)"
序列号: 18fcd412aae
生效时间: Thu May 30 14:05:51 CST 2024, 失效时间: Fri May 30 14:05:51 CST 2025

随后会询问用户:"是否信任此证书? 否: ",此处输入:Y

当看到"证书已添加到密钥库中"这样的提示时,说明已经添加成功。

验证根证书

根证书导入完毕,以后如何验证是否添加了该证书呢?仍然可以使用keytool工具进行读取。

跳转至上一步中介绍到的目录,使用如下命令(Linux/macOS):

复制代码
keytool -list -keystore cacerts | grep charles

或者(Windows)

复制代码
keytool -list -keystore cacerts | findstr charles

工具提示用户输入keystore的密码,默认为空。

若看到类似如下内容即说明已经安装:

复制代码
charles, 2024-6-18, trustedCertEntry,

经验分享,在IDE中如何结合Charles调试https接口调用

在系统对接过程中,往往会出现一些非常低级的错误。例如,对方要求POST方式以表单形式提交数据,结果以POST JSON body方式提交了。那么如何能够快速验证自己写的代码是否正确呢?

打开charles后(假设本地IP:192.168.100.1,代理端口为:8888,并且启用了SSL代理),回到IDE,在待调试项目的启动入口处修改JVM选项,增加如下JVM参数:

复制代码
-Dhttp.proxyHost=192.168.100.1 -Dhttp.proxyPort=8888 -Dhttps.proxyHost=192.168.100.1 -Dhttps.proxyPort=8888

注意:只设置http.proxyHost和http.proxyPort是无法抓取到https请求的

这样当程序调用了外部https协议的接口时,请求就会经过Charles代理,在代理抓取到的请求记录中,即可看到自己的请求是否符合要求。

相关推荐
JAVA面经实录9173 分钟前
线上故障标准处理流程【完整版|面试背诵+生产落地】
java·面试·职场和发展
殷色玫瑰14 分钟前
C++入门基础复习:从命名空间到引用与nullptr,一篇重新捡回C++基础
java·开发语言·c++
javaDocker1 小时前
16.5 小时,我打掉了两只「SSL 握手失败」的怪
网络·网络协议·ssl
大侠归来1 小时前
C语言素数判断:从入门到进阶
java·c语言·算法
谢亮_vipxieliang2 小时前
Spring Boot 自动配置原理:从 @SpringBootApplication 到自定义 Starter
java·spring boot·后端
朝朝辞暮i2 小时前
C++ 第 25 课:getter / setter + this
java·javascript·c++
蜗牛互联网2 小时前
Python接入Gemini 3.8 Flash实现票据视觉抽取与规则校验
java·javascript·网络·人工智能·python
用户094248568032 小时前
第22章:JIT编译分层——Interpreter、C1、C2与热点探测
java·jvm
周杰偷奶茶2 小时前
【JavaSE】类和对象基础
java·开发语言
ly76892 小时前
Redis 主从复制全解析:从 PSYNC 协议到复制积压缓冲区的故障切换边界
java·数据库·redis·主从复制·故障切换·psync