使用Grizzly和Jersey的SSL

yks3o0rb  于 2023-04-12  发布在  其他
关注(0)|答案(5)|浏览(132)

我正在尝试让Grizzly使用SSL加密,并且仍然可以很好地与Jersey一起工作。我已经在互联网上找过了,我找到了各种不同的尝试,使用Grizzly和Jersey进行SSL。似乎有不同的方法来做这件事,这取决于你使用的版本,以及你决定如何实现它。我还没有能够得到任何例子来与我的代码一起工作。
下面是我如何启动我的服务器:

static HttpServer startSecureServer() throws IOException{
        ResourceConfig rc=new PackagesResourceConfig("server.grizzlyresources");
        SSLContextConfigurator sslCon=new SSLContextConfigurator();

        sslCon.setKeyStoreFile(ConfigLoader.getKeystoreLocation()); // contains server keypair
        sslCon.setKeyStorePass(ConfigLoader.getKeystorePassword());

        System.out.println("Starting server on port "+ConfigLoader.getHttpsServerPort());
        HttpServer secure=GrizzlyServerFactory.createHttpServer(BASE_URI_SECURED, rc);
        secure.stop();

        HashSet<NetworkListener> lists=new HashSet<NetworkListener>(secure.getListeners());
        for (NetworkListener listener : lists){
            listener.setSecure(true);
            SSLEngineConfigurator ssle=new SSLEngineConfigurator(sslCon);
            listener.setSSLEngineConfig(ssle);
            secure.addListener(listener);
            System.out.println(listener);
        }

        secure.start();
        return secure;
}

private static URI getBaseURISecured(){
    return UriBuilder.fromUri("https://0.0.0.0/").port(ConfigLoader.getHttpsServerPort()).build();
}

private static final URI BASE_URI_SECURED = getBaseURISecured();

ConfigLoader从配置文件中加载信息。当我运行这段代码时,它启动服务器,它在server.grizzlyresources包中找到资源,它工作得很好!除了一件事。服务器不安全。我可以telnet到它,并以纯文本形式发送HTTP请求,以获取我的一个资源,它会返回它。所以这段代码用于启动服务器,但是它的整个SSL部分只是被绕过了。有什么想法如何解决这个问题或者为什么它可能会这样做吗?
下面是运行它时控制台的输出:

Starting server on port 9999
Jan 13, 2014 9:51:08 AM com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
  server.grizzlyresources
Jan 13, 2014 9:51:08 AM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
  class server.grizzlyresources.SessionResource
  class server.grizzlyresources.LoginResource
Jan 13, 2014 9:51:08 AM com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
Jan 13, 2014 9:51:08 AM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.12 02/15/2012 04:51 PM'
Jan 13, 2014 9:51:09 AM org.glassfish.grizzly.http.server.NetworkListener start
INFO: Started listener bound to [0.0.0.0:9999]
Jan 13, 2014 9:51:09 AM org.glassfish.grizzly.http.server.HttpServer start
INFO: [HttpServer] Started.
Jan 13, 2014 9:51:09 AM org.glassfish.grizzly.http.server.NetworkListener stop
INFO: Stopped listener bound to [0.0.0.0:9999]
NetworkListener{name='grizzly', host='0.0.0.0', port=9999, secure=true}
Jan 13, 2014 9:51:09 AM org.glassfish.grizzly.http.server.NetworkListener start
INFO: Started listener bound to [0.0.0.0:9999]
Jan 13, 2014 9:51:09 AM org.glassfish.grizzly.http.server.HttpServer start
INFO: [HttpServer] Started.

我用的是灰熊2.2.1和泽西1.12。
多谢了!

jgovgodb

jgovgodb1#

很抱歉花了这么长时间才把这个贴在这里。Alexey的回答让我找到了工作解决方案,这很像Wolfgang Fahl的代码。下面是我最终得到的:

static HttpServer startSecureServer() throws IOException
{
    System.out.println("Starting server on port " + ConfigLoader.getHttpsServerPort());
    ResourceConfig rc = new PackagesResourceConfig("com.kinpoint.server.grizzlyresources");

    SSLContextConfigurator sslCon = new SSLContextConfigurator();

    sslCon.setKeyStoreFile(ConfigLoader.getKeystoreLocation()); // contains server keypair
    sslCon.setKeyStorePass(ConfigLoader.getKeystorePassword());

    HttpHandler hand = ContainerFactory.createContainer(HttpHandler.class, rc);

    HttpServer secure = GrizzlyServerFactory.createHttpServer(BASE_URI_SECURED, hand, true,
            new SSLEngineConfigurator(sslCon, false, false, false));

    return secure;
}

SSLEngineConfigurator中的第二个参数告诉它不要使用客户端模式。这就是让我困惑的地方。谢谢你的帮助。

wh6knrhe

wh6knrhe2#

IMO你可以使用不同的工厂方法来初始化安全的Grizzly HttpServer:

HttpServer secure = GrizzlyServerFactory.createHttpServer(BASE_URI_SECURED,
                        ContainerFactory.createContainer(HttpHandler.class, rc),
                        true,
                        new SSLEngineConfigurator(sslCon));

如果像这样初始化服务器,则不需要停止并重新配置它。
希望这会有所帮助。

wecizke3

wecizke34#

下面的代码适用于Grizzly 2.3.7,我使用的是Jersey 1.18 -这包括SSL客户端身份验证的代码-如果您没有密钥库,此功能将被忽略。

/**
 * create a Server based on an url and possibly a ResourceConfig
 * 
 * @param url
 * @param rc
 * @param secure
 *          - true if SSL should be used
 * @param contextPath 
 * @return
 * @throws Exception
 */
public HttpServer createHttpServer(String url, ResourceConfig rc,
        boolean secure, String contextPath) throws Exception {
    // HttpServer result = GrizzlyServerFactory.createHttpServer(url, rc);
    // http://grepcode.com/file/repo1.maven.org/maven2/com.sun.jersey/jersey-grizzly2/1.6/com/sun/jersey/api/container/grizzly2/GrizzlyServerFactory.java#GrizzlyServerFactory.createHttpServer%28java.net.URI%2Ccom.sun.jersey.api.container.grizzly2.ResourceConfig%29
    HttpServer result = new HttpServer();
    final NetworkListener listener = new NetworkListener("grizzly",
            settings.getHost(), settings.getPort());
    result.addListener(listener);
    // do we need SSL?
    if (secure) {
        listener.setSecure(secure);
        SSLEngineConfigurator sslEngineConfigurator = createSSLConfig(true);
        listener.setSSLEngineConfig(sslEngineConfigurator);
    }
    // Map the path to the processor.
    final ServerConfiguration config = result.getServerConfiguration();
    final HttpHandler handler = ContainerFactory.createContainer(
            HttpHandler.class, rc);
    config.addHttpHandler(handler, contextPath);
    return result;
}

  /**
 * create SSL Configuration
 * 
 * @param isServer
 *          true if this is for the server
 * @return
 * @throws Exception
 */
private SSLEngineConfigurator createSSLConfig(boolean isServer)
        throws Exception {
    final SSLContextConfigurator sslContextConfigurator = new SSLContextConfigurator();
    // override system properties
    final File cacerts = getStoreFile("server truststore",
            "truststore_server.jks");
    if (cacerts != null) {
        sslContextConfigurator.setTrustStoreFile(cacerts.getAbsolutePath());
        sslContextConfigurator.setTrustStorePass(TRUSTSTORE_PASSWORD);
    }

    // override system properties
    final File keystore = getStoreFile("server keystore", "keystore_server.jks");
    if (keystore != null) {
        sslContextConfigurator.setKeyStoreFile(keystore.getAbsolutePath());
        sslContextConfigurator.setKeyStorePass(TRUSTSTORE_PASSWORD);
    }

    //
    boolean clientMode = false;
    // force client Authentication ...
    boolean needClientAuth = settings.isNeedClientAuth();
    boolean wantClientAuth = settings.isWantClientAuth();
    SSLEngineConfigurator result = new SSLEngineConfigurator(
            sslContextConfigurator.createSSLContext(), clientMode, needClientAuth,
            wantClientAuth);
    return result;
}
s3fp2yjn

s3fp2yjn5#

使用新的SeBootstrap功能,您可以使用以下命令启动服务器

static void startServer(CountDownLatch latch) {
        SSLContext sslContext = getSslContext();
        SeBootstrap.Configuration configuration = SeBootstrap.Configuration
                .builder()
                .sslContext(sslContext)
                .protocol("HTTPS")
                .port(6051)
                .build();
        SeBootstrap.start(Application.class, configuration).thenAccept(instance -> {
            instance.stopOnShutdown(stopResult ->
                    System.out.printf("Stop result: %s [Native stop result: %s].%n", stopResult,
                            stopResult.unwrap(Object.class)));
            final URI uri = instance.configuration().baseUri();
            System.out.printf("Instance %s running at %s [Native handle: %s].%n", instance, uri,
                    instance.unwrap(Object.class));
            System.out.println("Send SIGKILL to shutdown.");
            serverInstance = instance;
            latch.countDown();
        });
    }

(基于https://github.com/jakartaee/rest/blob/master/examples/src/main/java/jaxrs/examples/bootstrap/BasicJavaSeBootstrapExample.java
getSslContext()中的重要成分:

private static SSLContext getSslContext() {
        SSLContextConfigurator sslContextConfig = new SSLContextConfigurator();
        String keystorePath = Path.of("c:\\temp\\server.p12").toString();
        sslContextConfig.setKeyStoreFile(keystorePath);
        sslContextConfig.setKeyStorePass("changeit");
        return sslContextConfig.createSSLContext();
    }

最后一个要素是SSL证书。使用mkcert创建一个证书:
1.作为管理员choco install mkcert
1.作为管理员:mkcert -install

  1. cd c:\temp
  2. mkcert -pkcs12 myapp localhost 127.0.0.1 ::1
    1.将文件重命名为server.p12
    (基于https://stackoverflow.com/a/57511038/873282
    重要的是mkcert会自动生成替代名称,这是让Google Chrome接受SSL证书所必需的(特别是对于localhost)。有关详细信息,请参阅https://stackoverflow.com/a/42917227/873282
    官方的SSL最小示例可以在https://github.com/jakartaee/rest/blob/master/examples/src/main/java/jaxrs/examples/bootstrap/TlsJavaSeBootstrapExample.java上找到。

相关问题