如何解决如何覆盖 Http11Nio2Protocol 类以加密 server.xml 中的密钥库密码
按照答案 - Encrypt tomcat keystore password
像这样扩展 Http11Nio2Protocol 类:
public class ReSetHttpProtocol extends Http11Nio2Protocol {
@Override
public void setKeystorePass(String certificateKeystorePassword) {
Decoder decoder = Base64.getDecoder();
String password = new String(decoder.decode(certificateKeystorePassword));
super.setKeystorePass(password);
}
}
我构建了一个 maven 项目并将 jar 放在 tomcat/lib 中。
/conf/server.xml:
<Connector port="8443" protocol="com.fine.security.ReSetHttpProtocol"
maxThreads="150" scheme="https" SSLEnabled="true" relaxedQueryChars="^{}[]|"" >
<SSLHostConfig sslEnabledProtocols="TLSv1.2" ciphers="TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" >
<Certificate certificateKeystoreFile="(absolute path of the .pfx file)"
certificateKeystoreType="JKS" certificateKeystorePassword="(encrypted password)" />
</SSLHostConfig>
</Connector>
当我使用原始密码时,它可以正常工作。 然后我改了certificateKeystorePassword,失败了,catalina.out中的错误信息是:
** [main] org.apache.catalina.core.StandardService.initInternal Failed to initialize connector [Connector[com.fine.security.ReSetHttpProtocol-8443]]
org.apache.catalina.LifecycleException: Protocol handler initialization failed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:1032)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
at org.apache.catalina.core.StandardService.initInternal(StandardService.java:552)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:848)
at org.apache.catalina.startup.Catalina.load(Catalina.java:662)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:472)
Caused by: java.lang.IllegalArgumentException: keystore password was incorrect
at org.apache.catalina.startup.Catalina.load(Catalina.java:639)
at org.apache.catalina.startup.Catalina.load(Catalina.java:662)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:472)
Caused by: java.lang.IllegalArgumentException: keystore password was incorrect
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:100)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:72)
at org.apache.tomcat.util.net.Nio2Endpoint.bind(Nio2Endpoint.java:158)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1118)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.init(AbstractJsseEndpoint.java:223)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:587)
at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:74)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:1030)
... 13 more
Caused by: java.io.IOException: keystore password was incorrect
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2059)
at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:238)
at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)
at java.security.KeyStore.load(KeyStore.java:1445)
at org.apache.tomcat.util.security.KeyStoreUtil.load(KeyStoreUtil.java:69)
at org.apache.tomcat.util.net.SSLUtilBase.getStore(SSLUtilBase.java:216)
at org.apache.tomcat.util.net.SSLHostConfigCertificate.getCertificateKeystore(SSLHostConfigCertificate.java:206)
at org.apache.tomcat.util.net.SSLUtilBase.getKeyManagers(SSLUtilBase.java:282)
at org.apache.tomcat.util.net.SSLUtilBase.createSSLContext(SSLUtilBase.java:246)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:98)
... 20 more
Caused by: java.security.UnrecoverableKeyException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
似乎“密钥库密码不正确”。
我在 tomcat 源代码中搜索了“setKeystorePass”,但找不到它的调用位置。那么为什么我可以扩展方法来更改协议配置?
提前致谢!
解决方法
您找不到对 setKeystorePass
的任何调用的原因是它是通过反射执行的,主要使用 IntrospectionUtils#setProperty(详情参见 Commons Digester)。
配置 XML 用于创建 Java 对象:
-
<Connector protocol="com.fine.security.ReSetHttpProtocol"
创建连接器和协议处理程序, - 标签
<SSLHostConfig>
创建了SSLHostConfig
的实例,结束标签</SSLHostConfig>
在连接器上调用Connector#addSslHostConfig
, - 这同样适用于
<Certificate>
,它创建SSLHostConfigCertificate
的一个实例,配置它并在最后调用SSLHostConfig#addCertificate
。 -
<Connector>
、<SSLHostConfig>
和<Certificate>
标签的所有属性调用相应对象上的适当 setter 或setProperty
。例如。port="8443"
调用 settersetPort()
,但SSLEnabled="true"
调用setProperty("SSLEnabled","true")
因为没有 setter,
因此,如果您希望引导程序代码调用 setKeystorePassword
的实现,您需要以这种方式定义连接器:
<Connector port="8443"
protocol="com.fine.security.ReSetHttpProtocol"
maxThreads="150"
scheme="https"
SSLEnabled="true"
relaxedQueryChars="^{}[]|""
sslEnabledProtocols="TLSv1.2"
ciphers="..."
keystoreFile="(absolute path of the .pfx file)"
keystoreType="JKS"
keystorePass="(encrypted password)" />
此语法自 Tomcat 8.5 起已过时,并已在 Tomcat 10 中删除,但它是完成您想要的操作的最简单方法。
如果您希望使用新语法,则需要对标准 Http11NioProtocol
进行更多修改:
- 您需要为
SSLHostConfigCertificate
创建一个仅覆盖setCertificateKeystorePassword
的代理, - 您需要为
SSLHostConfigCertificate
覆盖addCertificate
创建一个代理,它将使用第 1 点的代理调用原始addCertificate
, - 您需要通过使用上一点的代理调用原始
addSSLHostConfig
来覆盖协议中的addSSLHostConfig
。
PS:您不是加密您的密码,您是编码它。要解码编码的密码,您只需要知道转换(在您的情况下为 Base64),要解密加密的密码,您需要知道加密算法和密钥。然后你可能需要对加密密钥进行加密等等......我发现这两个程序都没用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。