https说明

http是无状态的,https是在http应用层协议和tcp传输控制层之间加了一层,主要功能包括加密传输内容,校验信息是否完整,信息是否被篡改等。http的网络传输,源端应用层发送http请求,传输到源端的控制层,网络层,物理层->到对方的物理层->网络层->传输控制层->应用层,https就是在两边的控制层和应用层之间加了一层SSL/TLS协议层。发送时将http的明文加密,接收时解密,校验是否完整,是否被篡改,在正确无误的明文发送给目标端的应用层,作为http报文。

发送方:应用层http明文->SSL/TLS->秘文->控制层 接收方:控制层秘文->SSL/TLS->明文-应用层http

加密方式,分为对称加密,非对称加密;对称加密,加密强度弱,耗时短,使用相同的key加解密;非对称加密,加密强度高,耗时长,一个使用公钥,一个使用私钥。

tls握手流程:

步骤一:tls握手和密钥交换(非对称加密阶段)

1.客户端发送自己tls版本,支持的加密方式,随机数

2.服务器回复选择的加密方式,随机数和证书,证书包括认证机构,服务器地址,公钥,有效期等

3.客户端验证证书。查看证书的公钥,服务器地址,过期时间ca签名等

4.客户端生成一个用于对数据加密的对称密钥,并用服务器的公钥将这个对称密钥加密,传输给服务器

5.服务器用私钥解密,获取到对称密钥。

步骤二:数据传输,对称加密阶段

每次发送数据,使用对称密钥对数据进行加密,服务器解密后传输给应用层。再将引用层的响应信息加密发送给客户端。

java发送https请求需要怎么做

1.生产环境必须使用权威CA颁发的证书,禁止信任所有证书。

2.自签名证书仅限测试环境,生产环境使用会到安全风险。

3.导入证书到JVM信任库

通过keytool将CA证书导入JVM默认信任库cacerts:

复制代码
keytool -import -alias server_cert -file server.crt -keystore $JAVA_HOME/lib/security/cacerts

输入默认密码changeit,完成后重启应用生效。

若需要隔离应用证书,可创建独立的信任库:

复制代码
keytool -import -alias my_ca -file ca.crt -keystore /path/to/my_truststore.jks
​
#启动时指定JVM参数:
-Djavax.net.ssl.trustStore=/path/to/my_truststore.jks -Djavax.net.ssl.trustStorePassword=your_password
```[6,8](@ref)
https请求实现方式:

1.使用JAVA标准库

复制代码
import javax.net.ssl.HttpsURLConnection;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
​
public class HttpsExample {
    public static void main(String[] args) throws Exception {
        URL url = new URL("https://api.example.com/data");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
​
        // 验证响应
        try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
            String line;
            while ((line = in.readLine()) != null) {
                System.out.println(line);
            }
        }
    }
}

2.使用Apache HttpClient(推荐)

复制代码
#maven依赖
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
​
public class HttpClientExample {
    public static void main(String[] args) throws Exception {
        // 加载信任库(可选,默认使用JVM信任库)
        SSLContext sslContext = SSLContexts.custom()
                .loadTrustMaterial(null, (chain, authType) -> true) // 生产环境需替换为证书验证逻辑
                .build();
​
        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLContext(sslContext)
                .build()) {
            
            HttpGet httpGet = new HttpGet("https://api.example.com/data");
            HttpResponse response = httpClient.execute(httpGet);
            String result = EntityUtils.toString(response.getEntity());
            System.out.println(result);
        }
    }
}

3.使用OkHttp(高性能首选)

复制代码
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.11.0</version>
</dependency>
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
​
public class OkHttpExample {
    public static void main(String[] args) throws Exception {
        OkHttpClient client = new OkHttpClient.Builder()
                .sslSocketFactory(sslContext.getSocketFactory(), trustManager) // 生产环境需配置真实TrustManager
                .build();
​
        Request request = new Request.Builder()
                .url("https://api.example.com/data")
                .build();
​
        try (Response response = client.newCall(request).execute()) {
            System.out.println(response.body().string());
        }
    }
}
为什么客户端需要安装CA证书?

1.验证服务器身份(核心作用)

  • 服务器证书的合法性验证:当客户端(java程序)访问HTTPS服务器时,服务器会返回它的数字证书,客户端需要使用CA证书验证服务器证书是否由可信结构签发,是否被篡改,域名是否匹配等。

2.信任链的建立

  • 证书链验证:服务器证书通常由中间CA签发,而中间CA的合法性需由根CA证书验证。java默认信任库(cacerts)内置了权威CA的根证书,用于逐级验证整个证书链。

  • 未安装CA证书的后果:若服务器证书的签发CA不在客户端信任库中,Java会抛出异常,拒接链接。

开发环境与生产环境为什么不同?

1.开发环境:开发测试时使用自签名证书(非CA签发),浏览器或Java默认不信任此类证书。

验证方式:

1.忽略验证(仅限测试):通过自定义TrustManager跳过证书检查(高风险,生产禁用)

2.手动导入信任库:将自签名证书导入JVM的cacerts文件,使java临时信任该证书。

复制代码
keytool -import -alias dev_cert -file dev.crt -keystore $JAVA_HOME/lib/security/cacerts

目的:快速测试HTTPS功能,避免频繁申请CA证书的成本。

2.生产环境:必须使用权威CA(如Let's Encrypt,DigiCert)签发的证书,确保全局可信

验证机制:

1.自动信任链验证:依赖JVM内置的cacerts信任库(含主流CA根证书),无需额外配置。

2.证书生命周期管理:需监控有效期,及时续期,避免服务中断

生产环境代码应该如何修改?

复制代码
//替换开发代码中的跳过验证部分.loadTrustMaterial(null,(chain,authType)->true)
KeyStore trustStore = KeyStore.getInstance("JKS");
try (InputStream is = new FileInputStream("truststore.jks")) {
    trustStore.load(is, "truststore_password".toCharArray());
}
​
SSLContext sslContext = SSLContexts.custom()
    .loadTrustMaterial(trustStore, null) // 启用信任库验证
    .build();
双向验证:

若需客户端证书认证(如银行接口):

复制代码
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("client.p12"), "client_pass".toCharArray());
​
SSLContext sslContext = SSLContexts.custom()
    .loadKeyMaterial(keyStore, "client_pass".toCharArray()) // 加载客户端证书
    .loadTrustMaterial(trustStore, null) // 加载信任库
    .build();
生产环境完整代码示例:
复制代码
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import java.io.FileInputStream;
import java.security.KeyStore;

public class ProductionHttpsClient {
    public static void main(String[] args) throws Exception {
        // 1. 加载信任库(生产环境使用CA证书)
        KeyStore trustStore = KeyStore.getInstance("JKS");
        try (InputStream is = new FileInputStream("/path/to/truststore.jks")) {
            trustStore.load(is, "truststore_pass".toCharArray());
        }

        // 2. 初始化SSLContext(启用完整证书验证)
        SSLContext sslContext = SSLContexts.custom()
                .loadTrustMaterial(trustStore, null) // 关键修改:启用CA验证
                .build();

        // 3. 创建HttpClient(使用默认域名校验)
        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLContext(sslContext)
                .build()) {

            // 4. 发送请求
            HttpGet httpGet = new HttpGet("https://api.example.com/data");
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                String result = EntityUtils.toString(response.getEntity());
                System.out.println(result);
            }
        }
    }
}
生产环境注意事项

1.证书管理

  • 监控CA证书有效期,提前续期(如Let's Encrypt证书90天有效期)

  • 定期更新JVM信任库(cacerts),确保包含最新根证书。

2.协议与加密套件

  • 强制使用TLSv1.2+,禁用弱算法(如SSLv3,TLSv1.0)
复制代码
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");

3.异常处理

  • 捕获SSLHandshakeExceptioni并记录详细日志,快速定位证书问题

4.性能开销

  • 复用CloseableHttpClient实例,减少SSL握手开销

为什么开发环境不能共用生产的根证书

1.安全漏洞放大
  • 开发环境常使用自签名证书,若将其导入生产信任库,攻击者可通过伪造相同域名的自签名证书劫持通信

  • 生产根证书被用于开发环境时,测试证书的泄露可能危及生产系统信任链

2.证书管理混乱
  • 开发证书频繁变更:测试需快速迭代,证书常重置或替换,若共用会导致生产信任库频繁更新,引发服务中断
3.验证策略冲突
  • 开发环境往往需跳过严格验证(如 NoopHostnameVerifier),而生产环境必须启用完整验证(域名匹配、证书链校验

  • 共用配置会强制生产环境降低安全标准,或让开发环境无法调试

4.合规与审计风险
  • 行业标准(如 PCI DSS)要求生产环境证书必须由公共 CA 签发并独立管理,共用会导致审计失败
相关推荐
Elohim8158 小时前
基于Webserver的数据采集
http·modbus tcp·webserver
物联网嵌入式小冉学长11 小时前
3.TCP回响服务器实现及源码分析上
stm32·网络协议·tcp/ip·嵌入式
靡樊13 小时前
应用层协议HTTP
网络·网络协议·http
笨手笨脚の13 小时前
Nginx-2 详解处理 Http 请求
运维·网络协议·nginx·http
magic 24513 小时前
@RequestHeader(“Authorization“) 解析:HTTP 请求头中的 Authorization 字段
网络·网络协议·http
DjangoJason13 小时前
计算机网络 : 应用层协议HTTP
网络协议·计算机网络·http
llwszx13 小时前
“从HTTP到TCP/IP的旅程“-----深入浅出Java Web通信
java·websocket·网络协议·tcp/ip·spring·http
只喜欢赚钱的棉花没有糖1 天前
http的缓存问题
前端·javascript·http
小疆智控1 天前
从离散控制到集成管理:Modbus TCP转CANopen网关重构烟丝膨胀生产线
网络协议·tcp/ip·重构