Java and SSL certificates



我正在尝试使用安全套接字层(HTTPS)与Java中的PHP脚本建立连接,但我发现为了确保最大的安全性/有效性,我必须将我的网站使用的SSL证书导入我的应用程序…一件我不知道怎么做的事。

如果它有帮助,我的SSL证书不是自签名的,而是由StartSSL提供的,我正在使用Eclipse IDE。

谁能给我指个正确的方向?例如,我需要哪些文件,我应该在哪里导入它们,我需要哪些Java代码,等等?

我已经发现,为了确保最大的安全性/有效性,我必须将我的网站使用的SSL证书导入我的应用程序

你说的那句话有一部分是对的。您不需要导入SSL证书。导入StartSSL CA证书就足够了。

此外,不存在将证书导入Java应用程序这样的事情。Java中的SSL支持依赖于密钥库和信任库的概念,而不是依赖于应用程序中打包的某些证书。如果您发布的应用程序供最终用户下载和执行,则不需要在应用程序中发布证书或私钥。私钥和相关的证书将存储在密钥存储库中,只有您可以访问。

应用程序的最终用户将依赖于Java运行时中的SSL支持,这将使应用程序能够在验证服务器证书后建立到站点的SSL连接。Java运行时附带了信任存储库中的一组默认CA证书,成功建立SSL连接的唯一先决条件是服务器的SSL证书由信任存储库中的一个CA颁发。 StartSSL的证书不存在于Java运行时的信任存储库中,至少从版本6开始是这样,因此:

  • 您可以指示您的最终用户执行将StartSSL CA证书导入Java信任库的活动。可能有帮助的链接包括这个StartSSL论坛线程(只需要将CA证书导入信任库的前4步),GitHub项目和这篇博客文章;免责声明-我没有尝试使用任何这些,您应该自行承担风险。
  • 或者,您可以使用-Djavax.net.ssl.trustStore=<path_to_truststore> -Djavax.net.ssl.trustStorePassword=<truststore_password> JVM启动标志使用您自己的信任库初始化您的应用程序,或者在初始化SSL连接之前执行以下代码:

    System.setProperty("javax.net.ssl.trustStore","<path_to_truststore>");
    System.setProperty("javax.net.ssl.trustStorePassword","<truststore_password>");
    

    只有当您的应用程序是Java SE应用程序而不是applet(或对如何指定信任库具有类似限制的应用程序)时,这才是可行的方法。


阅读Java keytool文档也会有所帮助。

以下方法加载默认(cacerts)密钥存储库,检查是否安装了证书,如果没有安装,则安装证书。它消除了在任何服务器上手动运行keystore命令的需要。

假设默认的keystore密码changeit没有变化,如果没有,请更新CACERTS_PASSWORD。注意,该方法在添加证书后保存密钥存储库,因此运行一次后,证书将永久保存在存储库中。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
/**
 * Add a certificate to the cacerts keystore if it's not already included
 */
public class SslUtil {
    private static final String CACERTS_PATH = "/lib/security/cacerts";
    // NOTE: DO NOT STORE PASSWORDS IN PLAIN TEXT CODE, LOAD AT RUNTIME FROM A SECURE CONFIG
    // DEFAULT CACERTS PASSWORD IS PROVIDED HERE AS A QUICK, NOT-FOR-PRODUCTION WORKING EXAMPLE
    // ALSO, CHANGE THE DEFAULT CACERTS PASSWORD, AS IT IMPLORES YOU TO!
    private static final String CACERTS_PASSWORD = "changeit";
    /**
     * Add a certificate to the cacerts keystore if it's not already included
     * 
     * @param alias The alias for the certificate, if added
     * @param certInputStream The certificate input stream
     * @throws KeyStoreException
     * @throws NoSuchAlgorithmException
     * @throws CertificateException
     * @throws IOException
     */
    public static void ensureSslCertIsInKeystore(String alias, InputStream certInputStream)
            throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{
        //get default cacerts file
        final File cacertsFile = new File(System.getProperty("java.home") + CACERTS_PATH);
        if (!cacertsFile.exists()) {
            throw new FileNotFoundException(cacertsFile.getAbsolutePath());
        }
        //load cacerts keystore
        FileInputStream cacertsIs = new FileInputStream(cacertsFile);
        final KeyStore cacerts = KeyStore.getInstance(KeyStore.getDefaultType());
        cacerts.load(cacertsIs, CACERTS_PASSWORD.toCharArray());
        cacertsIs.close();
        //load certificate from input stream
        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
        final Certificate cert = cf.generateCertificate(certInputStream);
        certInputStream.close();
        //check if cacerts contains the certificate
        if (cacerts.getCertificateAlias(cert) == null) {
            //cacerts doesn't contain the certificate, add it
            cacerts.setCertificateEntry(alias, cert);
            //write the updated cacerts keystore
            FileOutputStream cacertsOs = new FileOutputStream(cacertsFile);
            cacerts.store(cacertsOs, CACERTS_PASSWORD.toCharArray());
            cacertsOs.close();
        }
    }
}

像这样使用:

SslUtil.ensureSslCertIsInKeystore("startssl", new FileInputStream("/path/to/cert.crt"));

显然mailgun工程师出于某种原因不想给我们明确的说明如何解决这个问题。这就是我所做的

我们运行tomcat8并通过jersey web服务连接到mailgun API。我按照这个用户的说明,它工作得很好。希望对大家有所帮助。

在1月22日,由于赛门铁克的PKI基础设施设置为不受信任,我们更新了SSL证书。一些旧版本的Java没有"DigiCert Global Root G2" CA。

有几个选项:

将"DigiCert Global Root G2"CA导入您的"cacerts"文件。将JRE升级到8u91(或更高版本),其中包括这个根。要导入"DigiCert Global Root G2",您可以从https://www.digicert.com/digicert-root-certificates.htm下载根文件。确保您正在下载正确的根证书。

下载证书后,您需要使用如下命令将其导入:

keytool -import -trustcacerts -keystore/path/to/cacerts -storepass changeit -noprompt -alias digicert-global-root-g2 -file/path/to/digicert.crt您需要设置您的Java Keystore的路径和您下载的根证书的位置。


1.//digicert/路径。CRT就是你刚下载的文件。2./path/to/cacerts—这是您的JRE路径。我"find/-name cacerts -print"这将帮助您快速找到文件系统上的所有java cacerts。对我来说,它是/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/security/cacerts

看看下面的文章:http://stilius.net/java/java_ssl.php它包含代码示例,这可能有助于在情况下,如果你试图从代码访问你的脚本。

请注意,您应该使用系统属性

javax.net.ssl.keyStore
javax.net.ssl.keyStorePassword

将SSL证书传递给JVM或使用keytool工具将其导入JRE密钥库

我已经发现,为了确保最大的安全性/有效性,我必须导入SSL证书

不,你没有。只有当您的客户端不相信服务器证书的签名者时,您才需要该步骤,这只有在服务器证书是自签名或由内部CA签名时才会出现

这篇文章包含更改信任存储的密码和在那里添加其他证书的代码:

thetechawesomeness.ideasmatter.info

最新更新