在开发Java web服务客户端期间,我遇到了一个问题。web服务的身份验证使用客户端证书、用户名和密码。我从webservice背后的公司收到的客户端证书是.cer格式的。当我使用文本编辑器检查文件时,它有以下内容:

-----BEGIN CERTIFICATE-----
[Some base64 encoded data]
-----END CERTIFICATE-----

我可以在Internet Explorer中导入该文件作为证书(无需输入密码!),并使用它进行webservice的身份验证。

I was able to import this certificate into a keystore by first stripping the first and last line, converting to unix newlines and running a base64-decode. The resulting file can be imported into a keystore (using the keytool command). When I list the entries in the keystore, this entry is of the type trustedCertEntry. Because of this entry type (?) I cannot use this certificate to authenticate with the webservice. I'm beginning to think that the provided certificate is a public certificate which is being used for authentication...

我发现的一个解决办法是在IE中导入证书,并将其导出为.pfx文件。该文件可以作为密钥存储库加载,并可用于使用webservice进行身份验证。但是,我不能期望我的客户每次收到新证书时都执行这些步骤。因此,我想将.cer文件直接加载到Java中。任何想法吗?

附加信息:webservice背后的公司告诉我,应该向稍后将导入证书的PC和用户请求证书(使用IE和网站)。


您不应该对证书做任何更改。您确定您正在运行正确的导入命令吗?

以下是我的工作:

keytool -import -alias joe -file mycert.cer -keystore mycerts -storepass changeit

mycert的地方。cer包含:

-----BEGIN CERTIFICATE-----
MIIFUTCCBDmgAwIBAgIHK4FgDiVqczANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY
...
RLJKd+SjxhLMD2pznKxC/Ztkkcoxaw9u0zVPOPrUtsE/X68Vmv6AEHJ+lWnUaWlf
zLpfMEvelFPYH4NT9mV5wuQ1Pgurf/ydBhPizc0uOCvd6UddJS5rPfVWnuFkgQOk
WmD+yvuojwsL38LPbtrC8SZgPKT3grnLwKu18nm3UN2isuciKPF2spNEFnmCUWDc
MMicbud3twMSO6Zbm3lx6CToNFzP
-----END CERTIFICATE-----

If you want to authenticate you need the private key - there is no other option. A certificate is a public key with extra properties (like company name, country,...) that is signed by some Certificate authority that guarantees that the attached properties are true. .CER files are certificates and don't have the private key. The private key is provided with a .PFX keystore file normally. If you really authenticate is because you already had imported the private key. You normally can import .CER certificates without any problems with keytool -importcert -file certificate.cer -keystore keystore.jks -alias "Alias"


您已经拥有的证书可能是服务器证书,或者用于签署服务器证书的证书。您将需要它,这样您的web服务客户机才能对服务器进行身份验证。

But if additionally you need to perform client authentication with SSL, then you need to get your own certificate, to authenticate your web service client. For this you need to create a certificate request; the process involves creating your own private key, and the corresponding public key, and attaching that public key along with some of your info (email, name, domain name, etc) to a file that's called the certificate request. Then you send that certificate request to the company that's already asked you for it, and they will create your certificate, by signing your public key with their private key, and they'll send you back an X509 file with your certificate, which you can now add to your keystore, and you'll be ready to connect to a web service using SSL requiring client authentication.

要生成证书请求,使用"keytool -certreq -alias -file -keypass -keystore "。将生成的文件发送给将要签署该文件的公司。

当你取回你的证书时,运行"keytool -importcert -alias -keypass -keystore "。

如果密钥存储库受到保护(这是个好主意),那么在这两种情况下都可能需要使用-storepass。


下面是我一直用于以编程方式将.cer文件导入到新的KeyStore中的代码。

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
//VERY IMPORTANT.  SOME OF THESE EXIST IN MORE THAN ONE PACKAGE!
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

//Put everything after here in your function.
KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null);//Make an empty store
InputStream fis = /* insert your file path here */;
BufferedInputStream bis = new BufferedInputStream(fis);

CertificateFactory cf = CertificateFactory.getInstance("X.509");

while (bis.available() > 0) {
    Certificate cert = cf.generateCertificate(bis);
    trustStore.setCertificateEntry("fiddler"+bis.available(), cert);
}

将从浏览器下载的.cer证书文件(打开url并挖掘详细信息)导入到java_home\jre\lib\security中的cacerts密钥存储库中,而不是尝试生成和使用我自己的密钥存储库。

转到java_home\jre\lib\security (Windows)使用cmd和CTRL+SHIFT+ENTER打开管理命令行 2 .执行keytool命令导入证书。 (替换你的aliasname和路径\到\证书。cer)

 ..\..\bin\keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias yourAliasName -file path\to\certificate.cer

这样您就不必指定任何额外的JVM选项,并且证书应该可以被JRE识别。


这是我的工作方式:

在文本编辑器中按以下格式将证书数据保存为。txt ——开始证书 [微软数据序列化] ——结束证书 打开chrome浏览器(这一步可能也适用于其他浏览器) settings >显示高级设置> HTTPS/SSL >管理证书 在步骤1中导入.txt文件 选择并导出Base-64编码格式的证书。保存为。cer 现在可以使用keytool或Portecle将其导入java密钥存储库


下面是一个脚本,我用它将当前目录中的一堆crt文件批量导入到java密钥库中。只需将其保存到与证书相同的文件夹中,并像这样运行它:

./import_all_certs.sh

import_all_certs.sh

KEYSTORE="$(/usr/libexec/java_home)/jre/lib/security/cacerts";

function running_as_root()
{
  if [ "$EUID" -ne 0 ]
    then echo "NO"
    exit
  fi

  echo "YES"
}

function import_certs_to_java_keystore
{
  for crt in *.crt; do 
    echo prepping $crt 
    keytool -import -file $crt -storepass changeit -noprompt --alias alias__${crt} -keystore $KEYSTORE
    echo 
  done
}

if [ "$(running_as_root)" == "YES" ]
then
  import_certs_to_java_keystore
else
  echo "This script needs to be run as root!"
fi

一个开放源码的GUI工具可以在keystore-explorer.org上获得

密钥存储库浏览器 KeyStore资源管理器是Java的开源GUI替代品 命令行实用工具keytool和jarsigner。密钥存储库浏览器 通过直观的图形显示它们的功能 用户界面。

以下画面会有帮助(它们来自官方网站)

运行命令得到的默认屏幕:

shantha@shantha:~$./Downloads/kse-521/kse.sh

点击检查和检查URL选项然后给出你想导入的URL。

如果你给谷歌网站链接,结果窗口将如下所示。

这是用例之一,其余的取决于用户(所有的信用都转到keystore-explorer.org)


虽然已经提供了很多很好的答案,但我想给出一个以编程方式加载ssl材料的替代方案。您可以尝试下面的代码片段:

Path certificatePath = Paths.get("/path/to/certificate.cer");
List<Certificate> certificates = CertificateUtils.loadCertificate(certificatePath);

SSLFactory sslFactory = SSLFactory.builder()
        .withTrustMaterial(certificates)
        .build();

SSLContext sslContext = sslFactory.getSslContext();

它可以处理pem, der(二进制)和p7b格式的文件。这个示例代码片段来自库:GitHub - SSLContext Kickstart你可以添加下面的代码片段:

<dependency>
    <groupId>io.github.hakky54</groupId>
    <artifactId>sslcontext-kickstart</artifactId>
    <version>7.0.2</version>
</dependency>