Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
设置Java SSL服务器套接字使用的证书_Java_Ssl - Fatal编程技术网

设置Java SSL服务器套接字使用的证书

设置Java SSL服务器套接字使用的证书,java,ssl,Java,Ssl,我想在Java服务器应用程序中打开一个安全侦听套接字。我知道建议的方法是这样做: SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); ServerSocket ss = ssf.createServerSocket(443); 但这需要在启动java时将服务器的证书传递给JVM。因为这会使部署中的一些事情对我来说更加复杂,所以我更愿意在运行时加载证书 所以我有一个密

我想在Java服务器应用程序中打开一个安全侦听套接字。我知道建议的方法是这样做:

SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket ss = ssf.createServerSocket(443);
但这需要在启动java时将服务器的证书传递给JVM。因为这会使部署中的一些事情对我来说更加复杂,所以我更愿意在运行时加载证书

所以我有一个密钥文件和密码,我想要一个服务器套接字。我怎么去那里?嗯,我阅读了文档,我能找到的唯一方法是:

// these are my parameters for SSL encryption
char[] keyPassword =  "P@ssw0rd!".toCharArray();
FileInputStream keyFile = new FileInputStream("ssl.key"); 

// init keystore
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(keyFile, keyPassword);
// init KeyManagerFactory
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyPassword);
// init KeyManager
KeyManager keyManagers[] = keyManagerFactory.getKeyManagers();
// init the SSL context
SSLContext sslContext = SSLContext.getDefault();
sslContext.init(keyManagers, null, new SecureRandom());
// get the socket factory
SSLServerSocketFactory socketFactory = sslContext.getServerSocketFactory();

// and finally, get the socket
ServerSocket serverSocket = socketFactory.createServerSocket(443);

这甚至没有任何错误处理。真的有那么复杂吗?难道没有更简单的方法吗?

如果你看一下代码,你就会明白为什么它一定很复杂。此代码将SSL协议的实现与以下内容分离:

  • 关键材料的来源(
    KeyStore
  • 证书算法选择和密钥管理(
    KeyManager
  • 对等信任规则的管理(
    TrustManager
    )-此处不使用
  • 安全随机算法(
    SecureRandom
  • NIO或套接字实现(
    SSLServerSocketFactory
    )-可以对NIO使用
    SSLEngine
考虑一下,如果您试图达到相同的目标,您自己的实现会是什么样子

但这需要在启动java时将服务器的证书传递给JVM

不,没有。在创建
SSLServerSocket:

javax.net.ssl.keyStore ssl.key
javax.net.ssl.keyStorePassword P@ssw0rd!
您可以使用
System.setProperties()
或在命令行上执行此操作。

使用此选项

public class KeyMaster
{
     public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String sslAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

        SSLContext context = SSLContext.getInstance(sslAlgorithm);//"SSL" "TLS"
        context.init(null, tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }
    catch(Exception e)
    {
        Assistance.log("Err: getSSLSocketFactory(), ");
    }

    return null;
}

public static SSLServerSocketFactory getSSLServerSocketFactory(KeyStore trustKey, String sslAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

        SSLContext context = SSLContext.getInstance(sslAlgorithm);//"SSL" "TLS"
        context.init(null, tmf.getTrustManagers(), null);

        return context.getServerSocketFactory();
    }
    catch(Exception e)
    {
        Assistance.log("Err: getSSLSocketFactory(), ");
    }

    return null;
}

public static SSLServerSocket getSSLServerSocket(SSLServerSocketFactory socketFactory, int port)
{
    try
    {
        return (SSLServerSocket) socketFactory.createServerSocket(port);
    }
    catch(Exception e)
    {Assistance.log("Err: getSSLSocket(), ");}

    return null;
}

public static KeyStore getFromPath(String path, String algorithm, String filePassword)//PKSC12
{
    try
    {
        File f = new File(path);

        if(!f.exists())
            throw new RuntimeException("Err: File not found.");

        FileInputStream keyFile = new FileInputStream(f);
        KeyStore keystore = KeyStore.getInstance(algorithm);
        keystore.load(keyFile, filePassword.toCharArray());
        keyFile.close();

        return keystore;
    }
    catch(Exception e)
    {
        Assistance.log("Err: getFromPath(), " + e.toString());
    }

    return null;
}
基本上

 KeyStore key = KeyMaster.getFromPath(".\\cssl.pfx", "PKCS12", "123");
        SSLServerSocketFactory fac = KeyMaster.getSSLServerSocketFactory(key, "TLS");
        listener = KeyMaster.getSSLServerSocket(fac, 49015);

这个问题主要是关于设置证书的问题。你的标题没有突出这一点(到目前为止,有一个答案似乎没有抓住这一点),所以我冒昧地修改了它。如果你愿意的话,请进一步改进标题。我认为你迄今为止提出的代码(a)非常可怕,(b)尽管如此,很可能是实现这一点的“正确”方式。Java并不总是过于冗长,但是当它是的时候,它确实是非常非常冗长的。如果你认为这很复杂,试着用NIO来做。但是我使用默认值来完成所有这些。应该有更直接的方法。@Philipp没有默认的密钥库。不建议这样做。任何事情都不要依赖于系统属性:/n您可能无法创建每个证书都不同的并发套接字。我亲自跟随