是否有加密tomcat server.xml中的keystorePass值的选项?我不希望它是纯文本
<Connector port="8403" //...
keystorePass="myPassword" />
是否有加密tomcat server.xml中的keystorePass值的选项?我不希望它是纯文本
<Connector port="8403" //...
keystorePass="myPassword" />
除了使用 XML 编码之外,还有一种更好的方法。
创建一个加密类来加密和解密您的密码。
并覆盖Http11Nio2Protocol类,类似于下面的代码。
public class Http11Nio2Protocol extends org.apache.coyote.http11.Http11Nio2Protocol {
@Override
public void setKeystorePass(String s) {
try {
super.setKeystorePass(new EncryptService().decrypt(s));
} catch (final Exception e){
super.setKeystorePass("");
}
}
}
注意:EncryptService是我们自己的加密类。
并在server.xml的协议属性中配置被覆盖的类,如下所示。
<Connector port="8443" protocol="<com.mypackage.overridden_Http11Nio2Protocol_class>"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="conf/.ssl/keystore.jks"
keystorePass="<encrypted_password>"/>
希望这可以帮助。
如果有人可以访问您的 server.xml,那么出现的 keystorePass 的纯文本值只是您的担忧之一。
如果有人可以从那里访问,他们可能会造成更大的伤害。在这里加密密码实际上只是将问题转移到其他地方,因为然后有人可以找到此加密密钥的加密密钥(有点像俄罗斯娃娃)。
如果你想加密密码,你必须重写连接器实现来解密加密的密码,以便tomcat可以访问或使用真正的密码。
面临同样的问题。客户要求“隐藏”所有密码。
因此,通过审核的最简单方法 - 来自Tomcat Wiki。
转到页面http://coderstoolbox.net/string/#!encoding=xml&action=encode&charset=none并编码您传递给 XML-view。
因此 -<Connector>
元素看起来像:
<Connector
port="8443"
protocol="HTTP/1.1"
SSLEnabled="true"
enableLookups="false"
disableUploadTimeout="true"
scheme="https"
secure="true"
clientAuth="want"
sslProtocol="TLS"
keystoreFile="conf/.ssl/keystore.jks"
keyAlias="tomcat"
keystorePass="chiks"
truststoreFile="conf/.ssl/trustedstore.jks"
truststorePass="chiks"
/>
我们也面临类似的问题,但我们创建了自己的加密和解密逻辑来解决这个问题。这是代码
/* class is used to generate encrypted password */
public class ClientForPasswordGeneration {
public static void main(String[] args) {
//final String secretKey = "ssshhhhhhhhhhh!!!!";
final String secretKey = PasswordKey.getEncryptionKey();
GenerateLogic object = new GenerateLogic();
String password = PasswordField.readPassword("Enter password: ");
String encryptPassword = object.encrypt(password, secretKey);
System.out.println("Encrypted Password:");
System.out.println(encryptPassword);
}
}
另一个班级
class EraserThread implements Runnable {
private boolean stop;
/**
* @param The
* prompt displayed to the user
*/
public EraserThread(String prompt) {
System.out.print(prompt);
}
/**
* Begin masking...display asterisks (*)
*/
public void run() {
stop = true;
while (stop) {
System.out.print("\010*");
try {
Thread.currentThread().sleep(1);
// System.out.println("current thread::" + Thread.currentThread());
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
/**
* Instruct the thread to stop masking
*/
public void stopMasking() {
this.stop = false;
}
}
生成哈希码的逻辑
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class GenerateLogic {
private static SecretKeySpec secretKey;
private static byte[] key;
public static void setKey(String myKey) {
MessageDigest sha = null;
try {
key = myKey.getBytes("UTF-8");
sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
secretKey = new SecretKeySpec(key, "AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public static String encrypt(String strToEncrypt, String secret) {
try {
setKey(secret);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
} catch (Exception e) {
System.out.println("Error while encrypting: " + e.toString());
}
return null;
}
public static String decrypt(String strToDecrypt) {
try {
//System.out.println("decryptedString methods");
//String secret = "ssshhhhhhhhhhh!!!!";
String secret = PasswordKey.getEncryptionKey();
setKey(secret);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
//System.out.println("testing string values::" + new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt))));
return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)));
} catch (Exception e) {
System.out.println("Error while decrypting: " + e.toString());
}
return null;
}
public static void main(String[] args) {
final String secretKey = "ssshhhhhhhhhhh!!!!";
String originalString = "changeit";
String encryptedString = GenerateLogic.encrypt(originalString, secretKey);
String decryptedString = GenerateLogic.decrypt(encryptedString);
System.out.println(originalString);
System.out.println(encryptedString);
System.out.println(decryptedString);
}
}
这是我们扩展类 org.apache.coyote.http11.Http11Nio2Protocol 的地方,该类存在于 tomcat 8 的 lib 文件夹中的 tomcat-coyote-8.0.29.jar 中。因此,在编译这些类时,tomcat-coyote-8.0。 29.jar 应该存在。
public class Http11Nio2Protocol extends org.apache.coyote.http11.Http11Nio2Protocol {
@Override
public void setKeystorePass(String s) {
try {
super.setKeystorePass(new GenerateLogic().decrypt(s));
} catch (final Exception e) {
super.setKeystorePass("");
}
}
}
这是用户必须在 cmd 中输入密码的地方,该密码应该被散列
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class PasswordField {
/**
* @param prompt
* The prompt to display to the user
* @return The password as entered by the user
*/
public static String readPassword(String prompt) {
EraserThread et = new EraserThread(prompt);
Thread mask = new Thread(et);
mask.start();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String password = "";
try {
password = in.readLine();
} catch (IOException ioe) {
ioe.printStackTrace();
}
// stop masking
et.stopMasking();
// return the password entered by the user
return password;
}
}
这是您保存密码密钥的地方。你应该改变它。
public class PasswordKey {
private static String ENCRYPTION_KEY = "myKeysecretkey";
protected static String getEncryptionKey()
{
return ENCRYPTION_KEY;
}
}
编译上面的类以在 cmd 中使用以下命令生成类文件。请记住,tomcat-coyote-8.0.29.jar 应该存在于所有 java 文件所在的同一文件夹中。
javac -cp ".;tomcat-coyote-8.0.29.jar" *.java
在 cmd 中使用此命令使用生成的类文件制作一个 jar
jar -cvf PasswordEncryptor.jar *.class
这将创建一个 jar 文件 PasswordEncryptor.jar
将生成的 PasswordEncryptor.jar 粘贴到 Tomcat8 的 lib 文件夹中。即 apache-tomcat-8.5.9\lib
现在转到此位置并键入以下命令以生成散列密码。
java -cp ".;PasswordEncryptor.jar" ClientForPasswordGeneration
现在转到 apache-tomcat-8.5.9\conf 并编辑 server.xml
在证书的 keytorpasss 中使用散列密码
<Connector port="9443" protocol="Http11Nio2Protocol" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="C:\Certificates\SSLCert.cert" keystorePass="nOS74yuWW4s18TsL2UJ51A=="/>
注意协议是自定义类名。
希望这会帮助你。
谢谢
1)创建CustomEncryptService
加密和解密您的密码。
2)覆盖Http11Nio2Protocol
类,类似于下面的代码。(如上面 user3675974 所述)
public class CustomHttp11Nio2Protocol extends org.apache.coyote.http11.Http11Nio2Protocol {
@Override
public void setKeystorePass(String s) {
try {
super.setKeystorePass(new CustomEncryptService().decrypt(s));
} catch (final Exception e){
super.setKeystorePass("");
}
}
}
3) 在 server.xml 的协议属性中配置被覆盖的类,如下所示。
<Connector port="8443"
protocol="<com.mypackage.xyz....CustomHttp11Nio2Protocol>"
maxThreads="150"
SSLEnabled="true"
scheme="https"
secure="true"
clientAuth="false"
sslProtocol="TLS"
keystoreFile="conf/.ssl/keystore.jks"
keystorePass="<encrypted_password>"/>
4)由于这个CustomHttp11Nio2Protocol
类应该在启动时可用,创建具有CustomHttp11Nio2Protocol
andCustomEncryptService
类的 Jar,并将其放入您的tomcat/lib
.
希望这可以帮助。
我们需要创建 jar 文件来解密放置在 keyStorePass 中的密码。以下是使用 Eclipse IDE 创建 jar 文件的步骤。:
第 1 步:在 Eclipse IDE 中,转到New->Other->Java Project。单击 Next。输入项目名称。单击下一步并完成。
第 2 步:展开新创建的项目。右键单击src->新建->包。创建包名称为“com.apache”
第三步:在 com.apache 包中创建一个类来解密密码:
package com.apache;
public class DecryptPassword {
public static synchronized String decrypt(String str) throws Exception {
/* Decryption Logic*/
}
}
第 4 步:在 com.apache 包中创建一个名为 CustomHttp11Nio2Protocol 的新类,以扩展 org.apache.coyote.http11.Http11Nio2Protocol 类
package com.apache;
public class CustomHttp11Nio2Protocol extends org.apache.coyote.http11.Http11Nio2Protocol {
@Override
public void setKeystorePass(String s) {
try {
super.setKeystorePass(DecryptPassword.decrypt(s));
} catch (final Exception e){
super.setKeystorePass("");
}
}
}
第 5 步:您将在上述课程中收到一些错误。通过右键单击项目名称然后属性->构建路径->在库选项卡中->单击添加外部 jar 来解决它们。在tomcat的bin文件夹中选择tomcat-coyote.jar和tomcat-util.jar。还要选择tomcat的bin文件夹中的tomcat-juli.jar。现在两个类中的错误不应该是可见的。
第 6 步:将项目导出为 JAR 文件。右键单击项目名称->导出->在 Java 下选择 JAR 文件->单击下一步-> 选择导出目标作为 Tomcat 的 lib 文件夹。单击完成。
第 7 步:将以下连接器粘贴到 tomcat 的 server.xml 中。观察协议值包含我们在步骤 2 中定义的包名以及在步骤 4 中使用的类名。加密密码必须放在连接器的 keystorePass 中。
<Connector
protocol="com.apache.CustomHttp11Nio2Protocol"
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="serverCert.p12"
keystorePass="<encrypted_password>"
clientAuth="false" sslProtocol="TLS"/>
第 8 步:重新启动 Tomcat。
这是一个方便的 Perl 单线 XML 编码密码:
$ perl -pe 's/(.)/"&#".ord($1).";"/eg;' <<< 'secret'
# secret