2013-10-04 15 views
1

首先,我知道有一个类似的问题here,但它并不回答我的疑问。 我有一个配置了SSL的FTPS服务器(vsftpd)。如何在apache-commons中使用生成的证书配置客户端身份验证

我已经生成用适当的键:

openssl req -x509 -nodes -days 1825 -newkey rsa:2048 \ 
-keyout private/vsftpd.key \ 
-out certs/vsftpd.crt 

和配置服务器各自的conf文件。

现在,在与Apache公地网Java客户端代码,我可以像这样的东西与服务器通过SSL通信:

import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.PrintWriter; 
import org.apache.commons.net.PrintCommandListener; 
import org.apache.commons.net.ftp.FTP; 
import org.apache.commons.net.ftp.FTPReply; 
import org.apache.commons.net.ftp.FTPSClient; 

public class CommonsNetFTPSTest { 
public static void main(String[] args) throws Exception { 
    System.setProperty("javax.net.debug", "ssl"); 

    String server = "XXX.XXX.XXX.XXX"; 
    String username = "USER_TEST"; 
    String password = "ABCD1234"; 
    String remoteFile = "/Data/Input/PH240819"; 
    String localFile = "PH240819"; 
    String protocol = "SSL"; // TLS/null (SSL) 
    int port = 990; 
    int timeoutInMillis = 10000; 
    boolean isImpicit = true; 

    FTPSClient client = new FTPSClient(protocol, isImpicit); 

    client.setDataTimeout(timeoutInMillis); 
    client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); 

    System.out.println("################ Connecting to Server ################################"); 

    try 
    { 
     int reply; 
     System.out.println("################ Connect Call ################################"); 
     client.connect(server, port); 

     client.login(username, password); 

     System.out.println("################ Login Success ################################"); 

     //client.setFileType(FTP.BINARY_FILE_TYPE); 
     client.setFileType(FTP.NON_PRINT_TEXT_FORMAT); 
     client.execPBSZ(0); // Set protection buffer size 
     client.execPROT("P"); // Set data channel protection to private 
     client.enterLocalPassiveMode(); 

     System.out.println("Connected to " + server + "."); 
     reply = client.getReplyCode(); 

     if (!FTPReply.isPositiveCompletion(reply)) 
     { 
      client.disconnect(); 
      System.err.println("FTP server refused connection."); 
      System.exit(1); 
     } 

     client.listFiles(); 
     boolean retrieved = client.retrieveFile(remoteFile, new FileOutputStream(localFile)); 
    } 
    catch (Exception e) 
    { 
     if (client.isConnected()) 
     { 
      try 
      { 
       client.disconnect(); 
      } 
      catch (IOException ex) 
      { 
       ex.printStackTrace(); 
      } 
     } 
     System.err.println("Could not connect to server."); 
     e.printStackTrace(); 
     return; 
    } 
    finally 
    { 
     //client.disconnect(); 
     client.logout(); 
     System.out.println("# client disconnected"); 
    } 
} 
} 

但这种方式我的客户是接受任何证书,我想这可能是一个中间人攻击。所以我想告诉我的客户接受哪些证书,并且只在证书有效时才连接。

现在,我以前生成两个文件:vsftpd.key和vsftpd.crt,我已经导入了CRT文件在本地密钥库这样的:

keytool -import -alias alias -file vsftps.crt -keypass keypass -keystore mykeystore.jks -storepass Hello1 

我的问题是,我如何告诉我的客户使用mykeystore的证书?我还缺少什么?谢谢

回答

3

好吧,现在我拥有它。

我从一开始就做错了。首先,您需要将两个文件(vsftpd.crt和vsftpd.key)转换为一个PKCS12文件。

openssl pkcs12 -export -in vsftpd.crt -inkey vsftpd.key > vsftpd.p12 

接下来,你需要将PKCS12文件导入密钥库:

keytool -importkeystore -srckeystore vsftpd.p12 -destkeystore keystore.jks -srcstoretype pkcs12 

详细说明[这里]。 2

最后,您只需要使用生成的密钥库实例化一个信任管理器,并将其交给FTPSClient。例如:

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import javax.net.ssl.X509TrustManager; 

import org.apache.commons.net.ftp.FTP; 
import org.apache.commons.net.ftp.FTPSClient; 
import org.apache.commons.net.io.Util; 
import org.apache.commons.net.util.TrustManagerUtils; 

public method() throws IOException, GeneralSecurityException{ 

    File storeFile = new File("path/to/keystore"); 

    KeyStore keyStore = loadStore("JKS", storeFile, "password"); 
    X509TrustManager defaultTrustManager = TrustManagerUtils.getDefaultTrustManager(keyStore); 

    client = new FTPSClient(properties.getProtocol(), isImpicit); 

    client.setTrustManager(defaultTrustManager); 
    logOutput = new LogOutputStream(log, Level.INFO); 
} 

//Helper method from apache: http://commons.apache.org/proper/commons-net/apidocs/index.html?org/apache/commons/net/util/KeyManagerUtils.html 
private KeyStore loadStore(String storeType, File storePath, String storePass) 
     throws KeyStoreException, IOException, GeneralSecurityException { 
     KeyStore ks = KeyStore.getInstance(storeType); 
     FileInputStream stream = null; 
     try { 
      stream = new FileInputStream(storePath); 
      ks.load(stream, storePass.toCharArray()); 
     } finally { 
      Util.closeQuietly(stream); 
     } 
     return ks; 
    } 
相关问题