代码之家  ›  专栏  ›  技术社区  ›  Hasan

保护tomcat server.xml中的密码

  •  1
  • Hasan  · 技术社区  · 9 年前

    服务器。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 回复  |  直到 9 年前
        1
  •  3
  •   upog    7 年前
    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. 创建自己的数据源工厂

      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