その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

Jetty を使ってWeb サーバを立ち上げ、更にSSL 接続を実装する

最近、Jetty を使ってJava でWeb サーバを立ち上げたので、その方法について備忘録的に書きます。

Jetty ?

Jetty は、100%JavaのJava Servletコンテナ・Webサーバである。WebSocketなどのプロトコルもサポートする。Jetty はオープンソースプロジェクトとして開発され、Apache 2.0 License でリリースされている。JBoss、Apache Geronimoといった他のプロジェクトでも利用されている。
単純で効率的な組み込みやすいWebサーバとなるよう意図して開発されている。サイズが小さいので、組み込み型 Java アプリケーションにWebサービスを提供するのに適している。 Jetty - Wikipedia
Wikipedia によると以上の通りだそうです。

つまり、Jetty の特徴を砕いて言うと
  • サーバの実装がかなり簡単 (←本当に)
  • Java だからクロスプラットフォーム
  • WebSocket に対応していてかなり嬉しい! (WebSocket を使う必要があったので)
みたいな感じでしょうか。他にも色々とメリットはあると思いますが。
と言うわけで、Jetty をつかってWeb サーバを立ち上げる運びとなりました。

下ごしらえ

今回はJetty を利用するに当たって、Maven を使いました。
なので、Maven のpom.xml に適宜設定を記述する必要があります。

maven2からjetty6を起動するメモ - maeda.na@はてな
や、
http://jyukutyo.hatenablog.com/entry/20101216/1292511146
を参考にして頂ければ大丈夫だと思います。

普通にHTTP 接続できるサーバをJava で書く

import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;

private void establishHttpServer() {
	HandlerList handlers = new HandlerList();
	handlers.setHandlers(new Handler[] { new DefaultHandler() }); // 他のハンドラが必要な場合はそれらも引数として与える。例えばWebSocket のハンドラとか。

	Server server = new Server(12345); // 引数には任意のポート番号を入れる。入れないとデフォルトの8080 番ポートが使用される(はず)
	server.setHandler(handlers);
}
上のコード例の場合は12345 番ポートで利用可能なWeb サーバが立ち上がります。

SSL 接続できるサーバをJava で書く

SSL 接続に係る設定等は以下を参照下さい。
Jetty/Howto/Configure SSL - Eclipsepedia
JettyでSSL for Windows 〜オレオレ証明書編 - Take action for the Future.

今回はオレオレ証明書を使う事にします。
keystore ファイルは出来ている前提です。
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;

private void establishSslServer() {
	HandlerList handlers = new HandlerList();
	handlers.setHandlers(new Handler[] { new DefaultHandler() });

	File keystoreFile = new File(/*keystore のロケーション*/);

	Server server = null;
	if(keystoreFile.exists()) {
		// SSL
		server = new Server();
		SslSelectChannelConnector sslConnector = new SslSelectChannelConnector();
		sslConnector.setPort(12345); // 任意のポート番号
		sslConnector.setKeystore(keystoreFile.getPath());
		sslConnector.setPassword(/*キーストアのパスワード*/);
		sslConnector.setKeyPassword(/*パスワード*/);
		server.addConnector(sslConnector);
	} else {
		server = new Server(12345);
	}
	server.setHandler(handlers);
}
上のコード例の場合、keystore ファイルが存在している時は12345 ポートでSSL 接続が可能となり、
keystore ファイルが無い場合は12345 ポートでHTTP 接続が出来るようになります。

SSL 接続と非SSL 接続をハイブリッドしたサーバをJava で書く

先ほど書いた"establishSslServer()"はSSL 接続と非SSL 接続の切り替えが出来ないので、少し不便です。
8888 ポートで接続された場合は普通の非SSL 接続、9999 ポートで接続された場合はSSL 接続を行うように書き換えます。
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;

private void establishWebServer() {
	HandlerList handlers = new HandlerList();
	handlers.setHandlers(new Handler[] { new DefaultHandler() });

	File keystoreFile = new File(/*keystore のロケーション*/);

        this.server = new Server();
        SelectChannelConnector connector = new SelectChannelConnector();
        connector.setPort(8888);
        server.setConnectors(new Connector[]{connector});

        if(keystoreFile.exists()) {
            // SSL
            SslSelectChannelConnector sslConnector = new SslSelectChannelConnector();
            sslConnector.setPort(9999);
            sslConnector.setKeystore(keystoreFile.getPath());
            sslConnector.setPassword(/*キーストアのパスワード*/);
            sslConnector.setKeyPassword(/*パスワード*/);
            this.server.addConnector(sslConnector);
        }
        this.server.setHandler(handlers);
}
これで上記の条件を満たすWeb サーバを立ち上げることが可能です。

結論

Jetty でWeb サーバを立ち上げるのは非常に簡単!

補足

ソースコード中に平文でキーストアのパスワードやらを記述するというロックンロールな手法は、
割と危険だと思うので、暗号化等を行っておいた方が良いと思います!

参考資料

www.massapi.com