ssl新闻资讯

文档中心

Java鑷鍚岺TTPS璇佷功瀹炴垬鎸囧崡浠庣敓鎴愬埌閮ㄧ讲鐨勫畬鏁存祦绋?txt

时间 : 2025-09-27 16:22:17浏览量 : 2

什么是自签名HTTPS证书?

2Java鑷鍚岺TTPS璇佷功瀹炴垬鎸囧崡浠庣敓鎴愬埌閮ㄧ讲鐨勫畬鏁存祦绋?txt

想象一下你要给朋友寄一封机密信件,自签名证书就像是你自己制作的印章,而不是去公安局申请官方印章。在HTTPS世界中,它是由你自己而非受信任的证书颁发机构(CA)创建的加密凭证。

自签名证书与CA签发的证书在技术实现上几乎相同,都使用相同的加密算法(如RSA或ECC),关键区别在于缺少第三方认证。这就好比你自己写的工作推荐信和前任雇主写的推荐信之间的区别。

为什么需要自签名证书?

1. 开发测试环境:当你在本地开发一个需要HTTPS的Java应用时,比如开发一个支付系统模拟器

2. 内部系统:公司内部的管理后台,如员工考勤系统

3. 成本考虑:小型项目或原型验证阶段不愿购买商业证书

4. 特殊需求:物联网设备间的加密通信

我曾在金融项目测试阶段使用自签名证书,节省了数十个测试环境的证书费用。但切记:永远不要在生产环境的用户-facing服务中使用自签名证书!

Java中生成自签名证书的三种方法

方法1:使用keytool工具(JDK自带)

```bash

keytool -genkeypair -alias mydomain -keyalg RSA -keysize 2048 \

-validity 365 -keystore keystore.jks -storetype JKS

```

这个命令会生成一个有效期为1年的RSA密钥对。执行时会交互式询问:

- 姓名/组织等基本信息(可以全部填localhost)

- 密钥库密码(建议不少于12位)

- 私钥密码(通常与密钥库相同)

方法2:OpenSSL + keytool组合拳

生成私钥

openssl genrsa -out myprivate.key 2048

创建CSR

openssl req -new -key myprivate.key -out mycsr.csr

自签名

openssl x509 -req -days 365 -in mycsr.csr -signkey myprivate.key -out mycert.crt

转换为Java可用的格式

openssl pkcs12 -export -in mycert.crt -inkey myprivate.key \

-out keystore.p12 -name "mydomain"

JKS格式转换(可选)

keytool -importkeystore -srckeystore keystore.p12 \

-srcstoretype PKCS12 -destkeystore keystore.jks

这种方法更灵活,适合需要精细控制证书属性的场景。

方法3:程序化生成(Bouncy Castle示例)

```java

Security.addProvider(new BouncyCastleProvider());

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", "BC");

keyGen.initialize(2048);

KeyPair keyPair = keyGen.generateKeyPair();

X500Name issuer = new X500Name("CN=localhost");

BigInteger serial = BigInteger.valueOf(System.currentTimeMillis());

Date notBefore = new Date(System.currentTimeMillis());

Date notAfter = new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(365));

ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA").build(keyPair.getPrivate());

JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(

issuer, serial, notBefore, notAfter, issuer, keyPair.getPublic());

X509CertificateHolder certHolder = certBuilder.build(signer);

X509Certificate cert = new JcaX509CertificateConverter().getCertificate(certHolder);

// 保存到KeyStore

KeyStore ks = KeyStore.getInstance("JKS");

ks.load(null, null);

ks.setKeyEntry("mydomain", keyPair.getPrivate(), "changeit".toCharArray(),

new Certificate[]{cert});

try (FileOutputStream fos = new FileOutputStream("keystore.jks")) {

ks.store(fos, "changeit".toCharArray());

}

这种方法适合需要动态生成证书的场景,比如SaaS平台为每个租户创建独立证书。

Spring Boot配置示例

在application.properties中:

```properties

server.ssl.enabled=true

server.ssl.key-store-type=JKS

server.ssl.key-store=classpath:keystore.jks

server.ssl.key-store-password=yourpassword

server.ssl.key-alias=mydomain

或者YAML格式:

```yaml

server:

ssl:

enabled: true

key-store-type: JKS

key-store: classpath:keystore.jks

key-store-password: yourpassword

key-alias: mydomain

Tomcat配置示例

在server.xml的Connector节点添加:

```xml

maxThreads="150" SSLEnabled="true">

certificateKeystorePassword="yourpassword"

type="RSA" />

Jetty配置示例

通过start.ini文件:

```ini

--module=https

jetty.sslContext.keyStorePath=/path/to/keystore.jks

jetty.sslContext.keyStorePassword=yourpassword

jetty.sslContext.keyManagerPassword=yourpassword

jetty.https.port=8443

Android客户端处理方案

当Android应用访问自签名HTTPS服务时会出现安全警告,可以通过以下方式解决:

1. 自定义TrustManager(不推荐用于生产环境):

```java

TrustManager[] trustAllCerts = new TrustManager[] {

new X509TrustManager() {

public void checkClientTrusted(X509Certificate[] chain, String authType) {}

public void checkServerTrusted(X509Certificate[] chain, String authType) {}

public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }

}

};

SSLContext sc = SSLContext.getInstance("TLS");

sc.init(null, trustAllCerts, new SecureRandom());

HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

2. 预置证书法(推荐):

将服务器公钥(.crt文件)放入assets目录:

InputStream caInput = context.getAssets().open("mycert.crt");

Certificate ca = CertificateFactory.getInstance("X.509")

.generateCertificate(caInput);

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

keyStore.load(null, null);

keyStore.setCertificateEntry("ca", ca);

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

tmf.init(keyStore);

SSLContext sslContext = SSLContext.getInstance("TLS");

sslContext.init(null, tmf.getTrustManagers(), null);

iOS客户端处理方案

类似地,iOS也需要特殊处理:

```swift

let sessionDelegate = SelfSignedCertSessionDelegate()

let session = URLSession(configuration: .default,

delegate: sessionDelegate,

delegateQueue: nil)

class SelfSignedCertSessionDelegate: NSObject, URLSessionDelegate {

func urlSession(_ session: URLSession,

didReceive challenge: URLAuthenticationChallenge,

completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

guard let serverTrust = challenge.protectionSpace.serverTrust else {

return completionHandler(.cancelAuthenticationChallenge, nil)

}

// ??生产环境应该验证证书指纹等属性!

let credential = URLCredential(trust: serverTrust)

completionHandler(.useCredential, credential)

Chrome/Firefox信任自签名证书的方法

浏览器访问时会显示警告页面:

1. Chrome中点击"高级"→"继续前往"

2. Firefox点击"高级"→"接受风险并继续"

要永久信任:

- Chrome/Edge:将.crt文件导入到"受信任的根证书颁发机构"

- Firefox:单独设置→隐私与安全→查看证书→导入

在Mac上双击.crt文件→钥匙串访问→登录钥匙串→找到该证书→右键"显示简介"→信任设置为始终信任

Windows上右键.crt文件→安装证书→当前用户→将所有证书放入下列存储→浏览选择"受信任的根..."

Java代码验证HTTPS连接示例

// HttpsURLConnection方式

URL urlObj=new URL("https://localhost:8443/api/test");

HttpsURLConnection conn=(HttpsURLConnection)urlObj.openConnection();

// Apache HttpClient方式

CloseableHttpClient httpClient=HttpClients.custom()

.setSSLSocketFactory(new SSLConnectionSocketFactory(

SSLContexts.custom()

.loadTrustMaterial((chain,authType)->true) // ??不安全!

.build()))

.build();

// OkHttp方式

OkHttpClient client=new OkHttpClient.Builder()

.hostnameVerifier((hostname,session)->true) // ??不安全!

.build();

生产环境应该替换掉这些跳过验证的逻辑!

Jenkins等CI工具的特殊处理

许多自动化工具默认拒绝自签名证书。以Jenkins为例解决方式:

1)全局配置添加参数:

-Djavax.net.debug=ssl

-Djavax.net.ssl.trustStore=/path/to/cacerts

-Djavax.net.ssl.keyStore=/path/to/keystore.jks

-Djavax.net.disableSSLHostnameVerification=true

??仅限测试环境!

2)或者在Groovy脚本中:

System.setProperty('jsse.enableSNIExtension', 'false')

System.setProperty('javax.net.debug', 'all')

System.setProperty('jdk.tls.client.protocols', 'TLSv1,TLSv1,TLSv1')

System.setProperty('https.protocols', 'TLSv1,TLSv1,TLSv1')

3)Maven构建时添加参数:

mvn clean install \

-Dmaven.wagon.http.ssl.insecure=true \

-Dmaven.wagon.http.auth.insecure=true \

-Dmaven.wagon.http.pool=false

4)Gradle解决方案:

gradle build --no-daemon \

-Djavax.net.debug=all \

-Djdk.tls.client.protocols=TLSv1 \

-Dhttps.protocols=TLSv1

5)Docker容器内运行Java应用时可能需要额外挂载:

docker run ... \

-v /host/path/to/cacerts:/etc/ssl/certs/java/cacerts \

-e JAVA_OPTS="-Djavax.net.debug=all ..."

Kubernetes Ingress使用自签名证书记录

虽然不推荐生产环境这样做但测试集群可以:

```yaml apiVersion:

networking.k8s.io/v1 kind:

Ingress metadata:

name:

test-ingress annotations:

nginx.

ingress.

kubernetes.

io/

force-

ssl-

redirect:

"

true"

spec:

tls:

hosts:

example.

com secretName:

selfsigned-

cert rules:

host:

com http:

paths:

pathType:

Prefix path:

"/"

backend:

service:

web-

service port:

number:

80 apiVersion:

v1 kind:

Secret metadata:

name:selfsigned-cert namespace:

default type:

kubernetes.io/tls data:tls.

crt:| base64编码的crt内容 tls.

key:| base64编码的私钥内容 ```

生成base64内容命令:`cat server.crt | base64 | tr-d '\n'`

也可以使用cert-manager自动创建:`kubectl apply-f https://github.com/jetstack/cert-manager/releases/download/vx.y.z/cert-manager.yaml`

然后创建ClusterIssuer:`apiVersion:cert-manager.io/v1 kind:C lusterIssuer metadata:n ame:selfsigned-prod spec:s elfSigned:{ }`

最后修改Ingress注解:`cert-manager.io/cluster-issuer:"selfsigned-prod"`

这种方案适合多团队共享的开发集群。

Java各版本差异注意事项

不同JDK版本对TLS的支持有差异需要注意:

-JDK7默认只支持TLS1.

0建议升级或强制协议版本-JDK8u161后默认禁用DES相关弱密码套件-JDK11开始默认要求最小1024位RSA密钥-JDK16+默认禁用SHA-

TAG:java自签名https证书,ssl证书安装指南,iis ssl证书安装,ssl证书安装教程,ip地址ssl证书,ssl证书安装用pem还是key,ssl证书怎么安装到服务器,ssl证书安装到域名上还是服务器上,iis证书安装