Tagbangers Blog

Basic認証をJavaで導入する2

こんにちは、藤岡です。

四苦八苦して、やっとJavaで作ったWebサーバアプリにBasic認証を導入することができました。

このプログラムの概要については、前回の記事で説明してあります。

完成したものは、GitHubにあげておきました → https://github.com/hiroki0976/Server2


このプログラムを作る中で、Socketの使い方と、Threadの性質、Input(Output)Streamクラスの性質がよく理解できました。

特にInput(Output)Streamクラスについては、流れの概念を表すクラスで、一度使用すると消えてしまう特徴があったので理解しにくかったですが、実際に使ってみることで理解が深まりました。

取得したものを何度も使用するには、メモリに保存する必要があったので、ByteArrayInput(Output)Stream型の配列に保存すれば良さそうでしたが、結局、クラス設計を工夫したら、そのようなことをする必要がなくなりました。

最終的には、以下のようにfor文で無限ループを2回使うことで解決しました。

public static void main(String[] args) throws Exception{
        try (ServerSocket server = new ServerSocket(8080)) {
            for(;;) {
                Socket socket = server.accept();
                Authorized author = new Authorized(socket, encodeAuthorization);

                if (author.isAuthorized()) {
                    for (;;) {
                        socket = server.accept();
                        ServerThread serverThread = new ServerThread(socket);
                        Thread thread = new Thread(serverThread);
                        thread.start();
                    }
                } else {
                    socket = server.accept();
                    ServerThread2 serverThread2 = new ServerThread2(socket);
                    Thread thread2 = new Thread(serverThread2);
                    thread2.start();
                }
            }
    }
}

1つ目のfor文は、認証が通らなかった時に何度も認証ダイアログを表示させるためのものです。それに対し2つ目のfor文は、認証が通った場合に、1つのクライアントだけでなく、様々なクライアントにレスポンスを返すためのものです。

最初はより複雑に考えてしまい、冗長なコードになっていましたが、認証する機能を他のクラスに任せた途端簡単になりました。クラス設計をする時に、意味で考えてクラス分けすることが必要なのだと感じました。

Socketの扱いに関しては、マルチスレッドの処理を実行させたかったので、Threadに渡して処理を実行し、それを切断する、ということを繰り返すことで実現できました。

Socketは理解が難しい概念ですが、ServerSocketクラスはポート番号が指定された港で、Socketクラスはその港に繋がっている船だという小川さんの考え方が分かりやすく、よく理解できました。

ServerSocketは港なので切断されることはないけど、Socketはそこにやってくる一つの船なので、切断してまた繋げつこともできると考えればいいのです。


今回でネットワークプログラミングの課題は最後でしたが、Javaに関しては多くの練習プログラムを作ってきたため、だいぶ理解が進んできたと思います。

しかし、まだまだ学ぶべきことはたくさんあるので、手を抜かずに頑張りたいです。