我正在尝试使用Https over http,我使用bouncy castle生成CA证书并从 .cer
文件生成 jks
文件,Spring启动成功启动了嵌入式tomcat提供的属性 .
问题是我从浏览器总是 insecure ssl certificate (例如从chrome: This CA Root certificate is not trusted because it is not in the Trusted Root Certification Authorities store.
),而我用另一个配置类以编程方式添加信任库 .
这是我的代码:
import org.apache.commons.codec.binary.Base64; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.cmp.CertRepMessage; import org.bouncycastle.asn1.cmp.PKIBody; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.cert.CertException; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.cert.cmp.CMPException; import org.bouncycastle.cert.cmp.ProtectedPKIMessage; import org.bouncycastle.cert.cmp.ProtectedPKIMessageBuilder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.ContentVerifierProvider; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.math.BigInteger; import java.security.*; import java.security.cert.X509Certificate; import java.util.Date;
public class generateService {
private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
private static X509CertificateHolder makeV3Certificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN)
throws GeneralSecurityException, IOException, OperatorCreationException, CertException
{
PublicKey subPub = subKP.getPublic();
PrivateKey issPriv = issKP.getPrivate();
PublicKey issPub = issKP.getPublic();
X509v3CertificateBuilder v1CertGen = new JcaX509v3CertificateBuilder(
new X500Name(_issDN),
BigInteger.valueOf(System.currentTimeMillis()),
new Date(System.currentTimeMillis()),
new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)),
new X500Name(_subDN),
subPub);
ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA").setProvider(BC).build(issPriv);
X509CertificateHolder certHolder = v1CertGen.build(signer);
ContentVerifierProvider verifier = new JcaContentVerifierProviderBuilder().setProvider(BC).build(issPub);
return certHolder;
}
public X509Certificate test(KeyPair kp) throws OperatorCreationException, GeneralSecurityException, CertException, IOException, CMPException {
Provider bcProvider = new BouncyCastleProvider();
Security.addProvider(bcProvider);
X509CertificateHolder cert = makeV3Certificate(kp, "CN=CA", kp, "CN=CA");
GeneralName sender = new GeneralName(new X500Name("CN=CA"));
GeneralName recipient = new GeneralName(new X500Name("CN=CA"));
ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider(BC).build(kp.getPrivate());
ProtectedPKIMessage message = new ProtectedPKIMessageBuilder(sender, recipient)
.setBody(new PKIBody(PKIBody.TYPE_INIT_REP, CertRepMessage.getInstance(new DERSequence(new DERSequence()))))
.addCMPCertificate(cert)
.build(signer);
X509Certificate jcaCert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(message.getCertificates()[0]);
return jcaCert;
}
public void generateJKS() throws GeneralSecurityException, IOException, OperatorCreationException, CMPException, CertException {
Provider bcProvider = new BouncyCastleProvider();
Security.addProvider(bcProvider);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
X509Certificate certificate = test(keyPair);
final FileOutputStream os = new FileOutputStream("E:\\cert4.cer");
os.write("-----BEGIN CERTIFICATE-----\n".getBytes("US-ASCII"));
os.write(Base64.encodeBase64(certificate.getEncoded(), true));
os.write("-----END CERTIFICATE-----\n".getBytes("US-ASCII"));
os.close();
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null,null);
X509Certificate[] certChain = new X509Certificate[1];
certChain[0] = certificate;
keyStore.setKeyEntry("myaliaskey", (Key)keyPair.getPrivate(), "secret".toCharArray(), certChain);
OutputStream outputStream = new FileOutputStream("E:\\keystoreRSA4.jks");
keyStore.store(outputStream, "secret".toCharArray());
outputStream.flush();
outputStream.close();
}
public static void main(String[] args) throws Exception {
new generateService().generateJKS();
} }
Application.properties:
server.port = 8443 server.http.port = 8080 server.ssl.key-store = E:\\keystoreRSA4.jks server.ssl.key-password = secret server.ssl.keyAlias = myaliaskey
/ ******************* ************ /
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration public class SSLConfig {
@PostConstruct
private void configureSSL() {
System.setProperty("https.protocols", "TLSv1.2");
System.setProperty("javax.net.ssl.trustStore", "E:\\keystoreRSA4.jks");
System.setProperty("javax.net.ssl.keyStore", "E:\\keystoreRSA4.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "secret");
} }
import org.apache.catalina.Context; import org.apache.catalina.connector.Connector; import org.apache.tomcat.util.descriptor.web.SecurityCollection; import org.apache.tomcat.util.descriptor.web.SecurityConstraint; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class TomcatConfig {
@Value("${server.http.port}")
private int httpPort;
@Value("${server.port}")
private int httpsPort;
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(initiateHttpConnector());
return tomcat;
}
public Connector initiateHttpConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("https");
connector.setPort(httpPort);
connector.setSecure(true);
connector.setRedirectPort(httpsPort);
return connector;
} }
任何帮助将不胜感激,并提前感谢您 .
1 回答
幸运的是,您可以't. There'讨论主题in this question:
您必须在浏览器中添加例外以接受您的证书 . 通常在开发期间 . 对于 生产环境 用途,您必须从可信赖的供应商处购买证书,例如Verisign .
要在浏览器中添加例外,请参阅this other question .
干杯!