java - 在 tomcat server.xml 中保护密码

标签 java tomcat configuration password-protection

为了保护 Server.xml 文件中的密码,我在其中加密了密码并覆盖了 org.apache.coyote.http11.Http11Nio2Protocol: ,如下所示:

Server.xml 看起来像这样:

 <Resource name="jdbc/HasanDB" auth="Container" type="javax.sql.DataSource"
              maxTotal="10" maxIdle="15" minIdle="3" initialSize="2" maxWaitMillis="10000"
              removeAbondend="true" removeAbondendTimeout="300"
              username="hasan" password="<encryptedpass>" driverClassName="com.mysql.jdbc.Driver"
              url="jdbc:mysql://localhost:3306/HasanDB"/>

package hasan;
public class Http11Nio2Protocol extends org.apache.coyote.http11.Http11Nio2Protocol  {
    @Override
    public void setKeystorePass(String certificateKeystorePassword) {
        try {
            System.out.println("..............===============certificateKeystorePassword===========................");
            super.setKeystorePass(EncryptService.decrypt(certificateKeystorePassword));
        } catch (final Exception e){
            super.setKeystorePass("");
        }
    }
}

package hasan;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

public class EncryptService {
    private static SecretKeySpec createSecretKey(char[] password, byte[] salt, int iterationCount, int keyLength) throws NoSuchAlgorithmException, InvalidKeySpecException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
        PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterationCount, keyLength);
        SecretKey keyTmp = keyFactory.generateSecret(keySpec);
        return new SecretKeySpec(keyTmp.getEncoded(), "AES");
    }
    private static byte[] base64Decode(String property) throws IOException {
        return Base64.getDecoder().decode(property);
    }
    static String decrypt(String string) throws GeneralSecurityException, IOException {
        String password = "password";
        byte[] salt = new String("salt").getBytes();
        int iterationCount = 100;
        int keyLength = 128;
        SecretKeySpec key = createSecretKey(password.toCharArray(),
                salt, iterationCount, keyLength);
        String iv = string.split(":")[0];
        String property = string.split(":")[1];
        Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        pbeCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(base64Decode(iv)));
        return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
    }
}

我已经把上面代码的Jar文件放到了tomcat_home/lib文件夹下。

当我运行 tomcat 8.5 服务器时,上面代码中的 setKeystorePass 方法没有执行。

我必须做什么才能让它正常?

最佳答案

  1. 配置您的数据源

<Resource name="jdbc/yourDB" 
auth="Container" 
type="javax.sql.DataSource" 
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
factory="org.junjun.util.secured.resources.datasource.EncryptedDataSourceFactory"
url="e6nNC2NVXThPKSyKMvCiZTa4beL/BHxyu+188EeeNWq10ynepC2f4fXHzlKKdo9288uNOStZwa6Ztu0h7TrWVAJIrurKQkfO" 
username="PzyHPd4xkXJYvoN6ztoLWg==" 
password="zeBxd99nNw2Hg6f4g/Rt8PkB7+uHOwVD"
maxActive="20" 
maxIdle="10" 
maxWait="-1" />
<ResourceLink name="jdbc/yourDB" global="jdbc/yourDB" type="javax.sql.DataSource" />
</Context>
  1. 创建您自己的数据源工厂

    包 org.junjun.util.secured.resources.datasource;

    import java.util.Enumeration;
    import java.util.Hashtable;
    
    import javax.naming.Context;
    import javax.naming.Name;
    import javax.naming.RefAddr;
    import javax.naming.Reference;
    import javax.naming.StringRefAddr;
    
    import org.apache.commons.dbcp.BasicDataSourceFactory;
    import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
    
    public class EncryptedDataSourceFactory extends BasicDataSourceFactory {
    
        private String USERNAME_TAG = "username";
    
        private String PASSWORD_TAG = "password";
    
        private String URL_TAG = "url";
    
        private StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
    
        private String password = System.getenv("secret-key");
    
        public EncryptedDataSourceFactory() {
            encryptor.setPassword(this.password);
        }
    
        @Override
        public Object getObjectInstance(Object obj, Name name, Context ctx, Hashtable env) throws Exception {
            if (obj instanceof Reference) {
                setUsername((Reference) obj);
                setPassword((Reference) obj);
                setURL((Reference) obj);
            }
            return super.getObjectInstance(obj, name, ctx, env);
        }
    
        private void setUsername(Reference ref) {
            findDecryptAndReplace(USERNAME_TAG, ref);
        }
    
        private void setPassword(Reference ref) {
            findDecryptAndReplace(PASSWORD_TAG, ref);
        }
    
        private void setURL(Reference ref) {
            findDecryptAndReplace(URL_TAG, ref);
        }
    
        private void findDecryptAndReplace(String refType, Reference ref) {
            Integer idx = find(refType, ref);
            if (idx == null) {
                System.out.println("The \"" + refType + "\" name/value pair was not found"
                        + " in the Reference object.  The reference Object is" + " " + ref.toString());
            } else {
                String decrypted = decrypt(ref.get(refType).getContent().toString());
                replace(idx, refType, decrypted, ref);
            }
        }
    
        private void replace(int idx, String refType, String newValue, Reference ref) {
            ref.remove(idx);
            ref.add(idx, new StringRefAddr(refType, newValue));
        }
    
        private String decrypt(String input) {
            return encryptor.decrypt(input);
        }
    
        private Integer find(String addrType, Reference ref) {
            Integer index = null;
            Enumeration<RefAddr> enu = ref.getAll();
            for (int i = 0; enu.hasMoreElements(); i++) {
                RefAddr addr = (RefAddr) enu.nextElement();
                if (addr.getType().compareTo(addrType) == 0)
                    index = i;
            }
            return index;
        }
    }
    
  2. 将您自己的数据源工厂构建到 Jar 文件中

  3. 复制 Jar 文件到 Tomcat
  4. 启动Tomcat

关于java - 在 tomcat server.xml 中保护密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45636379/

相关文章:

java - 使用反射调用方法的性能

java - 如何将spannablestring添加到android中的列表中?

java - Tomcat、HTTP Keep-Alive 和 Java 的 HttpsUrlConnection

tomcat - Liferay 文件入口 0 字节

configuration - 在 nginx 上设置子域?

java - Spring Boot未加载@ConfigurationProperties

java - 如何在android应用程序中添加http服务器并从移动浏览器访问

使用 inpout32.dll 的 Java I/O

java - 如何在 spring boot 应用程序中检查嵌入式 tomcat 的健康状况?

windows - 如何更改 stack.yaml 在 Windows 上的默认位置?