PythonをApache上でCGIとして動作させる方法

apache

Pythonを使ってWEBアプリケーションを構築する場合、Apacheを使ってCGIとしてPythonを動作させるのが一般的です。
PythonをApache上で動作させるには、PythonとApacheをインストールして、Apacheの設定ファイルを環境にあわせて修正するだけでよいです。


今回は、PythonをApache上で動作させる方法について紹介していきます。


環境情報


  • OS:Windows10
  • Apache:Apache 2.4.41
  • Python:Phton3.9

Pythonスクリプトの格納


まず、使用するPythonスクリプトファイルをApacheの所定の場所に格納します。
ApacheのCGIとしてPythonを動かすので、Apacheのルートディレクトリに存在する「cgi-bin」に格納します。


PythonをCGIとして動作させる場所

今回は、以下の”Hello,World!”を表示するだけのスクリプトで動作確認をおこないます。


#! C:\Python34\python

print('Content-Type: text/html')
print('')
print('Hello,World!')

1行目は、pythonのインストールパスを記載する必要があります。
筆者のマシンでは、「C:\Python34\python」にPythonをインストールしています。


Apacheのインストールについては省略しましたが、以前書いた記事があるので、そちらを参照してください。


Apache設定ファイルの修正


次に、PythonをApacheのCGIとして動かすためにApacheの設定ファイルを修正します。
修正するのは、Apacheの設定ファイルである「httpd.conf」になります。


筆者のマシンのApacheは「C:\Apache24」にインストールしているのですが、「httpd.conf」の格納先は以下になります。


・C:\Apache24\conf\httpd.conf

「httpd.conf」の修正箇所は大きくわけて2カ所になります。 まず、Scriptエイリアスの設定で、「cg-bin」フォルダをcgi実行スクリプトフォルダとして有効にします。


<IfModule alias_module>
    #
    # Redirect: Allows you to tell clients about documents 
    # exist in your server's namespace, but do not anymore.  
    # will make a new request for the document at its location.
    # Example:
    # Redirect permanent /foo http://www.example.com/bar

    #
    # Alias: Maps web paths into filesystem paths and is used to
    # access content that does not live under the DocumentRoot.
    # Example:
    # Alias /webpath /full/filesystem/path/
    #
    # If you include a trailing / on /webpath then the server will
    # require it to be present in the URL.  You will also likely
    # need to provide a <Directory> section to allow access to
    # the filesystem path.

    #
    # ScriptAlias: This controls which directoriesscripts. 
    # ScriptAliases are essentially the same as
    # documents in the target directory are treated 
    # run by the server when requested rather than as 
    # client.  The same rules about trailing "/" apply
    # directives as to Alias.
    #
    ScriptAlias /cgi-bin/ "${SRVROOT}/cgi-bin/"
</IfModule>

通常、上記の設定はデフォルトで有効になっているので、特に設定変更する必要はないかもしれません。


もう1か所の変更箇所が、「cgi-bin」フォルダのディレクトリ設定です。
拡張子「.py」をスクリプトファイルとして認識します。

以下の例では、「.py」ファイルだけではなく「.cgi」「.pl」もスクリプトファイルとして設定しています。


<Directory "${SRVROOT}/cgi-bin">
   AllowOverride none
   AddHandler cgi-script .cgi .pl .py
   Options +ExecCGI
   Require all granted
</Directory>

上記の設定をおこなった後にApacheを再起動し、ブラウザでアクセスして格納したPythonスクリプトが動作するかを確認します。


以下の画面が表示されれば設定成功です。



PythonスクリプトとHTMLを共存させる場合


「cgi-bin」下にはスクリプトファイル(上記例では「.cgi」「.pl」「.py」)だけではなく、通常のHTMLファイルも格納したいことはあると思います。
その場合は、「cgi-bin」のディレクトリ設定で「AddHandler text/html」の設定をおこない、.htmlも有効にする必要があります。


以下の例では、「cgi-bin」下に「.html」「.htm」「.txt」「.css」「.js」の配置を許可しています。


<Directory "${SRVROOT}/cgi-bin">
   AllowOverride none
   AddHandler cgi-script .cgi .pl .py
   AddHandler text/html .html .htm .txt .css .js
   Options +ExecCGI
   Require all granted
</Directory>

この設定をいれることで、「cgi-bin」下にスクリプトファイル以外の静的HTMLについても格納可能になります。




Apache2.4で、ポート毎にドキュメントルールをわける方法

apache

自分のパソコンを開発環境として開発をおこなう際、実態としては複数のPJの開発環境を共存させる必要があります。
その際、ポート毎にドキュメントルートをわけて、ドキュメントルートそれぞれに対して開発環境を準備する方法がやり易いと思います。


今回は、Apache2.4を使って、ポート毎にドキュメントルールをわけるためのApacheの設定方法について紹介します。


環境情報


Windowsマシンに、Apacheを既にインストールしてる状態を想定して説明していきます。


  • OS:Windows10
  • HTTPサーバ:Apache2.4

Apacheのインストールと環境構築方法は過去に記事を使っているので、そちらを参照してください。



筆者のパソコンには既にApache2.4がインストールされていて稼働しているのですが、ちょっと訳あって「80、81」ポートを使用することができないので、今回は「82、83」ポートそれぞれにドキュメントルールを設定して動作させるようにしてみます。


VirtualHostの設定


まずはVirtualHostの設定をおこないます。
82ポートと83ポートを使用できるようにし、それぞれのポート対してドキュメントルートを設定します。



# 1.Listenポートを設定
Listen 82
Listen 83

# 2.82ポートに対するドキュメントルートを設定
<VirtualHost *:82>
    DocumentRoot c:/PORT82/htdocs
    ServerName sakusaku-techs.com:82
    ErrorLog logs/PORT82/error_log
    CustomLog logs/PORT82/access_log common
</VirtualHost>

# 3.83ポートに対するドキュメントルートを設定
<VirtualHost *:83>
    DocumentRoot c:/PORT83/htdocs
    ServerName sakusaku-techs.com:83
    ErrorLog logs/PORT83/error_log
    CustomLog logs/PORT83/access_log common
</VirtualHost>

「1.Listenポートを設定」で、解放するポートを設定します。
今回は、82と83の2ポートを解放します。


” #2.82ポートに対するドキュメントルートを設定 “で、各ポートでアクセスするドキュメントルートを設定します。
ドキュメントルートの設定もおこなっていますが、ログの設定(アクセスログとエラーログ)もおこなっています。
これだけで、ポートとドキュメントの紐付けは完了です


” #3.83ポートに対するドキュメントルートを設定 “は、82ポートと同様の設定です。


ここまでの設定をおこなえばドキュメントルートの設定は完了ですが、このままではアクセスはできません。
次に説明する、アクセス制限の設定をおこなう必要があります。


アクセス制限の設定


VirtualHostの設定をおこなっただけではアクセス権限が設定されておらず、対象URLにブラウザでアクセスしても権限エラーで画面は表示することはできません。


VirtualHostの設定に、以下のようにアクセス制御の設定をおこないます。


<VirtualHost *:82>
    DocumentRoot c:/PORT82/htdocs
    ServerName sakusaku-techs.com:82
    ErrorLog logs/PORT82/error_log
    CustomLog logs/PORT82/access_log common

    <Directory c:/PORT82/htdocs>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:83>
    DocumentRoot c:/PORT83/htdocs
    ServerName sakusaku-techs.com:83
    ErrorLog logs/PORT83/error_log
    CustomLog logs/PORT83/access_log common

    <Directory c:/PORT83/htdocs>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

各バーチャルホストの設定に、以下の権限設定を入れています。


<Directory xxx>
    AllowOverride All
    Require all granted
</Directory>

Apache2.4では上記の設定が正解となります。
「Require all granted」がポイントです。
この設定を入れなかった場合、Apacheはデフォルトで「Require all denied」の設定となります。


そのため、「Require all granted」の権限設定をおこない、アクセスを有効にする必要があります。


ここまでの設定をおこなえば、82ポートと83ポートそれぞれでドキュメントルートをわけることができています。

確認として、82ポートに設定したドキュメントルートである「c:/PORT82/htdocs」と、83ポートに設定したドキュメントルートである「c:/PORT83/htdocs」下にindex.htmlを格納してみます。

その状態で、ブラウザを使って「http://localhost:82/index.html」「http://localhost:83/index.html」にアクセスすると、それぞれのドキュメントルートに配置したhtmlが表示されます。



ApacheAntを使ってWEBアプリケーションをビルドする環境を作成

apache

実業務でWEBアプリケーションを開発する際、製造と単体試験は各メンバのパソコンで実施するかと思います。
しかし、本番リリースするアプリケーションをビルドする際は、それなりのビルドマシンを準備してビルドする方がよいです。
正式なアプリケーションを個人のパソコンでビルドするのはリスクが高いですからね。


ビルド用のマシンを準備してビルド環境を構築する際、ApacheAnt(アパッチアント)を使ってビルド環境を構築するのがシンプルで使い勝手もよいとおもいます。


ApacheAntとはいわゆるビルドツールでして、ビルド内容を定義するxmlファイルにAntタスクと呼ばれる定義を記載していくことで、ビルド環境を構築することができます。


今回はApacheAntを使ってWEBアプリケーションのビルド環境を構築する方法を紹介していきます。


環境情報


  • OS:Windows10
  • ビルドツール:ApacheAnt 1.8.2
  • Java:Java1.8.60

ApacheAntの公式サイトは以下になります。



ビルド環境の構成


Windows環境であることを前提に説明していきますが、Linux系の環境であっても同様かと思います。

Linux環境の人は、パス等を読み替えて試してみてください。


ビルド環境としては以下になります。


C:---apache-ant-1.8.2       // ApacheAntはCドライブ直下に格納。
  |                         //
  |                         //
  |---buildEnv              // ビルドするプロジェクトが全て
    |                       // 格納されているフォルダ。
    |---buildPJ.bat         // ビルドを実行するBATファイル
    |                       //
    |---targetPJ            // ビルド対象プロジェクト。
        |                   //
        |                   //
        |---build           // ビルド対象プロジェクトのフォルダ。
            |               //
            |               //
            |---build.xml   // ビルド対象プロジェクトの定義ファイル。

buildEnvの下に、ビルド対象プロジェクトを格納しています。
今回は、ビルド対象プロジェクトが一つ(targetPJのみ)の例なのですが、ビルド対象プロジェクトが複数存在する場合は、この「buildEnv」下に格納する方法がよいです。


BATファイル・XMLファイルについて、以降に説明していきます。


BATファイル(バッチファイル)


ビルドする際、格納したバッチファイルである「buildPj.bat」を実行したビルドするようにします。
「buildPj.bat」にビルドを開始する定義をおこなっておきます。


@echo off

echo ビルド環境の準備
set ANT_HOME=C:\apache-ant-1.8.2
set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_60
set CLASSPATH=.
set PATH=%ANT_HOME%\bin;%PATH%
set STDWEBAP_SETENV="OK"

echo targetPJのビルドをおこないます。
cd C:\buildEnv\targetPJ\build >> C:\buildEnv\buildTargetPJ.txt
call ant clean >> C:\buildEnvbuildTargetPJ.txt
call ant war >> C:\buildEnv\buildTargetPJ.txt
cd C:\buildEnv >> C:\buildEnv\buildTargetPJ.txt

ビルド結果をログで確認できるように、「C:\buildEnv\buildTargetPJ.txt」に実行結果を出力しています。


XMLファイル


XMLファイルの基本構成を説明する前に、ビルド対象プロジェクトを説明していきます。


今回のビルド対象プロジェクトはWEBアプリケーションを想定します。
WEBアプリケーションの場合、Javaのようなソースコード以外に、JavaScriptファイル、CSSファイル、画像ファイル、といったメタファイル(静的ファイル)も扱わなければいけません。
かつ、今回はWAR形式に圧縮する形でビルドをおこないます。
そのため、XMLファイルは複雑になりがちなので、きちんとAntタスクを使いこなす形で定義する必要があります。

ビルド対象プロジェクトのフォルダ構成は以下になります。


targetPJ--build--build.xml           // ビルド定義。
         |                           //
         |                           //
         |--src                      //
             |                       //
             |--main                 //
                 |                   //
                 |--java             // ソースコード
                 |                   //
                 |--webapp           //
                     |               //
                     |--css          // CSS
                     |               // JavaScript
                     |--js           //
                     |               //
                     |--WEB-INF      //
                        |            //
                        |--properties// プロパティ
                        |            //
                        |--lib       // ライブラリ
                        |            //
                        |--view      // JSPなど

XMLの基本構成


XMLの基本構成は以下になります。


<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<project basedir="." default="war" name="targetPJ">

    <property environment="env" />

    <!-- ----------------------------------------------- --->
    <!-- 1.アプリ名、コンテンツ格納元・先、といった     -->
    <!--     プロパティを定義                             -->
    <!-- ----------------------------------------------- --->
    <property name="app.name" value="targetWeb" />
    <property name="dest.dir" value="dest" />
    <property name="src.dir" value="../src" />
    <property name="src.script.dir" 
        value="../src/main/webapp/js" />
    <property name="dest.script.dir" 
        value="${dest.dir}/release/resource/js" />
         ・
         ・
         ・

    <!-- ------------------------------------------------ -->
    <!-- 2.クラスパス定義を追加                         -->
    <!-- ----------------------------------------------- --->
    <path id="classpath">
        <fileset dir="${lib.dir}">
            <include name="*.jar" />
        </fileset>
    </path>

    <!-- ------------------------------------------------ -->
    <!-- 3.初期化とクリーン                             -->
    <!-- ------------------------------------------------ -->
    <target name="init" depends="clean">
        <mkdir dir="${dest.dir}" />
    </target>
    <target name="clean">
        <delete dir="${dest.dir}" />
    </target>

    <!-- ------------------------------------------------ -->
    <!-- 4.warファイル作成                              -->
    <!-- ------------------------------------------------ -->
    <target name="war" depends="init,compile">
        <echo message="warファイルを作成します。" />
        <jar destfile="${dest.dir}/${app.name}.war" 
           basedir="${dest.webcontents.dir}">
            <manifest>
                <attribute name="version" value="1.0.0" />
            </manifest>
        </jar>
    </target>

    <!-- ------------------------------------------------ -->
    <!-- 5.コンパイル                                   -->
    <!-- ------------------------------------------------ -->
    <target name="compile">
        <echo message="ビルドを行います。" />
        <mkdir dir="${dest.class.dir}" />
        <javac debug="true" destdir="${dest.class.dir}" 
            includeantruntime="false" source="${source}" 
            target="${target}" encoding="UTF-8">
            <src path="${src.dir}" />
            <classpath refid="classpath" />
        </javac>
    </target>

    <!-- ------------------------------------------------ -->
    <!-- 6.静的ファイルのコピー                         -->
    <!-- ------------------------------------------------ -->
    <target name="contents">

        <copy preservelastmodified="true" 
            todir="${dest.css.dir}" flatten="no">
            <fileset dir="${css.dir}" includes="**/*.css" />
            <fileset dir="${css.dir}" includes="**/*.htc" />
            <fileset dir="${css.dir}" includes="**/*.png" />
            <fileset dir="${css.dir}" includes="**/*.gif" />
            <fileset dir="${css.dir}" includes="**/*.svg" />
        </copy>
    </target>
</project>

Antタスク(アントタスク)


「XMLの基本構成」で使用しているAntタスクについて、特に重要なタスクについて説明してきます。


  • <property>タスク

主に、「1.アプリ名、コンテンツ格納元・先、といったプロパティを定義」で使用しているAntタスクです。


<property>タスクは、XMLファイル内で使用する変数に値を格納するタスク定義です。
以下の例では、「src.script.dir」という定数名に”../src/main/webapp/js”という値を格納しています。


<property name="src.script.dir" value="../src/main/webapp/js" />

大きなプロジェクトになるほど、XMLファイルは複雑になります。
<property>タスクを使って、定数定義をおこなっておいた方が見やすい定義になります。


  • <path>タスク

「2.クラスパス定義を追加」で使用しているAntタスクです。


<path>タスクは、idで指定したパスに新たなパスを追加することができるAntタスクになります。
「2.クラスパス定義を追加」では、<fileset>タスク・<include>タスクを使用して、jarファイルのパスをクラスパスに設定して、ビルドがおこなえるようにしています。


  • <target>タスク

「3.初期化とクリーン」でも使用していますが、他の箇所でも多く使用しているAntタスクです。


<target>タスクは、初期化やコンパイルといった大きなタスクを括りを定義できるタスクです。
「■BATファイル」の中で以下の2行を定義しています。


call ant clean >> C:\buildEnvbuildTargetPJ.txt
call ant war >> C:\buildEnv\buildTargetPJ.txt

「clean」「war」という2つのタスクを、<target>タスクに定義することでBATファイルからの定義を可能としています。


<target>タスクで囲ったタグの間に、定義した名称で実行するタスクを定義します。


<target name="clean">
    <delete dir="${dest.dir}" />
</target>

上記例では、「clean」という名称で実行するタスクを定義しています。


かつ、「3.初期化とクリーン」では、<mkdir>タスク・<delete>タスクを使用して、ビルド環境を初期化しています。
<mkdir>タスクはフォルダ作成のタスクになります。
<delete>タスクは削除のタスクになります。


  • <javac>タスク

「5.コンパイル」で使用しているAntタスクです。


構文は難しくないですが、ポイントとしては「includeantruntime」です。
「includeantruntime」とは、”ビルドにAntのライブラリを使用するか?”という属性になります。
この属性をfalseしておかないと、ビルドにAntのライブラリを参照してしまい、ビルドに失敗してしまう場合があります。


  • <copy>タスク

「6.静的ファイルのコピー」で使用しているAntタスクです。


JavaScriptファイル、CSSファイル、画像ファイル、といった静的ファイルのコピーをおこなっています。
「preservelastmodified」をtrueにすいることで、ファイルのタイムスタンプも保持したままコピーすることができます。


<fileset>タグを使い、コピーする対象ファイルを、拡張子指定のワイルドカードで指定をおこなっています。


まとめ


ApacheAntを使えば、ビルドルールをあらかじめ定義することができ、安定したビルド環境を構築することができます。


きちんと開発をおこなっていても、ビルドで失敗して不具合が発生したら悔しいですからね。


紹介してきれていないAntタスクを沢山ありますので、皆さんで調べていろいろ試してみてください。



Apacheでクライアント認証をおこない、Javaプログラムで証明書情報を取得して解析

apache

Apacheを使ったWEBアプリケーションでSSL通信をおこなうためには、Apacheが認識するサーバのフォルダ上に証明書を格納し、Apacheの設定ファイルに証明書の情報を定義する必要があります。

かつ、より安全なSSL通信をおこなう方法は、クライアント認証をおこなう方法になります。

許可した端末のブラウザにクライアント証明書をインストールし、そのクライアント証明書がインストールされている端末についてのみSSL通信を許可します。


今回は、クライアント証明書を使ってSSL通信をおこなうための設定方法と、クライアント証明書から情報を抜き出すJavaプログラムについて説明します。


環境情報


  • HTTPサーバ:Apahce2.2.15
  • 言語:Java1.7.79

SSL認証の概要


クライアント証明書を用いたSSL通信は、通常のSSL通信と少し異なります。

SSL通信をおこなう端末のブラウザにクライアント証明書をインストールしておき、通信においてブラウザのクライアント証明書と、サーバ側のルート証明書とで証明書のマッチング認証をおこない、同証明書であればSSL通信を許可します。



上記のクライアント証明書を用いたSSL通信をおこなうためには、ブラウザへのクライアント証明書のインストールと、Apacheへの証明書設定の2つが必要になります。


Apacheへの証明書設定(サーバ側)


サーバ側の証明書設定は、通常、証明書発行局が作成した証明書をサーバ上に指定フォルダに格納し、Apacheの設定ファイルに証明書のパスを設定します。
OpenSSLを使って独自で証明書を作成した場合でも設定方法は同様です。


設定するファイルは「ssl.conf」になります。
設定箇所は以下の4つです。


SSLCertificateFile

サーバ証明書の格納パス

SSLCertificateKeyFile

秘密鍵の格納パス

SSLCertificateChainFile

サーバー証明書の中間証明書格納パス

SSLCACertificateFile

クライアント証明書のルート証明書格納パス


# サーバー証明書
SSLCertificateFile /etc/httpd/cert/server.crt

# 秘密鍵
SSLCertificateKeyFile /etc/httpd/cert/secret.key

# サーバー証明書における中間証明書
SSLCertificateChainFile /etc/httpd/cert/publicKey.cer

# クライアント証明書におけるルート証明書
SSLCACertificateFile /etc/httpd/cert/root.pem

設定する証明書によっては、証明書の形式も意識する必要があります。
例えば、クライアント証明書におけるルート証明書(SSLCACertificateFile)は、テキスト形式でなくてはなりません。

Apacheのバージョンによるかもしれないのですが、少なくとも「Apahce2.2.15」ではバイナリ形式のルート証明書は認識できません。


Apacheのエラーログに、以下のログが出力されてApacheの起動に失敗します。


[Thu Mon DD HH:MI:SS YYYY] [info] SSL Library Error: 336105671error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not  return a certificate No CAs known to server for verification? 

証明書発行局からテキスト形式の証明書を発行してもらうことが一番よいのですが、OpenSSLコマンドを用いてバイナリからテキスト形式への変更も可能です。


openssl x509 -inform der -in root.cer -outform pem -out root.pem 

ブラウザへの証明書インストール(クライアント側)


ブラウザにインストールするクライアント証明書も、サーバ証明書と同様に証明書発行局が作成した証明書をインストールします。

こちらも基本的には、ウィザードに沿ってブラウザに証明書をインストールしていきます。


証明書ファイル(.der、など)をクリックすると、以下のようなインストールウィザードがひらきます。

表示内容を確認し、OKボタンを押下します。



保管場所を選択します。

通常であれば「現在のユーザ」でよいです。

選択したら次へボタンを押下します。



証明書ストアを設定します。

何かしらの理由がなければ、自動ストアを選択して、次へボタンを押下します。


以下のウィンドウが表示されれば、無事にクライアント証明書のインストール完了です。



インストールが完了したら、ブラウザの設定ウィンドウをひらいてインストール結果を確認します。

Edge(Chromium版)での確認方法は、設定ウィンドウをひらき、「プライバシーとサービス」→「証明書の管理」で証明書情報を確認できます。



「個人」タブにインストールした証明書が表示されていれば、正常にクライアント証明書が認識されているという事になります。


証明書から情報を取得


クライアント証明書を使ったSSL通信において、WEBアプリケーション側でクライアント証明書を情報を取得する事も可能です。
具体的には、JavaプログラムでHTTPリクエストから抽出します。


以下のプログラムでは、java.security.cert.X509Certificateを使って、HttpServletRequestから識別情報を取得しています。


private void getCert(HttpServletRequest request) {

    // -- クライアント証明書情報の取得 --//
    java.security.cert.X509Certificate[] certs = 
        (java.security.cert.X509Certificate[]) request.getAttribute(
        "javax.servlet.request.X509Certificate");

    // クライアント証明書からクライアント証明書識別子を取得
    Principal principal = certs[0].getSubjectX500Principal();

    // クライアント証明書識別子を取得
    X509Name name = new X509Name(principal.getName());
    Vector<?> cert = 
        name.getValues(X509ObjectIdentifiers.commonName);
    if (cert.size() == 1) {
        String code = cert.get(0);
    }

上記のプログラムで、クライアント証明書に格納されている「commonName」を取得することができます。


上記プログラムの用途としては、インストールされているクライアント証明書に格納されている情報(commonName)毎にアプリケーションの制御を変える場合です。
クライアント証明書Aをインストールしているブラウザからログインしたユーザと、クライアント証明書Bをインストールしているブラウザからログインしたユーザとで、上記で取得した情報をもとに制御の切替が可能となります。



EclipseでTomcat起動タイムアウトし、起動しない原因と対処方法

Tomcat起動タイムアウトエラー

EclipseでTomcatを使ったWEBアプリケーションの開発をおこなう際、いきなりTomcatが起動しなくなった場合の対処方を紹介します。
今回紹介するのは、Tomcat起動でタイムアウトが発生した場合の対処方法です。


Tomcat起動でタイムアウトした場合は、設定を変更することで事象が解消されることがほとんどです。


EclipseでのTomcat起動時に起動タイムアウトが発生すると、以下のようなメッセージが表示されます。


一概には言えませんが、紹介する2つの方法のどちらかで対処可能なことが多いです。


環境情報


  • Eclipse:Luna Service Release2(4.4.2)
  • WEBサーバ:Tomcat8.5

タイムアウト値を変更する


まずは、単純にタイムアウト値を変更する方法です。
WEBサーバに配置するアプリケーション自体が大きくなってくれるとTomcatへの展開に時間が掛かってしまい、タイムアウトが発生することがあります。


タイムアウト値の変更方法は以下になります。


まず、Eclipse上のコンソールビューでサーバタブを選択し、「ローカルホストのTomcat v8.0のサーバ」をダブルクリックし、Tomcatの設定ウィンドウをひらきます。



Tomcatの設定ウィンドウにおいて、タイムアウトに関する設定が存在するので、このタイムアウト値を変更することで、Tomcat起動時のタイムアウト値を変更することができます。



割当メモリを変更する


タイムアウト値を長めに変更してもTomcat起動時にタイムアウトの問題が発生する場合は、Tomcatに割り当てられているメモリが少ない事が原因で起動に失敗している可能性があります。
その場合は、メモリの設定を見直してみましょう。


メモリの設定方法は以下になります。
タイムアウト値の変更で使用したTomcatの設定ウィンドウで、一般情報の「起動構成を開く」を選択します。



起動構成プロパティーの編集において、引数タブを押下し、VM引数の設定ウィンドウをひらきます。



VM引数の設定ウィンドウにおいて、末尾に以下の文字列を追加します。

起動時メモリの設定になります。


-Xmx1024M -Xms521M -Djava.awt.headless=true

 

-Xmx

ヒープ全体の最大値

-Xms

ヒープ全体の最小値

-Djava.awt.headles

headlessモードの設定


一番最後の「-Djava.awt.headless」は、メモリの設定とはちょっと違いますが、trueにしておいた方が無難です。
特にGUI環境が無いLinuxサーバでTomcatを動かす場合、この設定がないとエラーになることがあるようです。
なので、常にtrueを設定しておいた方がいいです。


まとめ


EclipseでのTomcat起動タイムアウトは現認が解り辛いです。
しかし、紹介した2つの方法のいずれかで解決することが多いです。


Tomccat起動タイムアウトになった際の見直しポイント
  • タイムアウト値を単純に伸ばそう
  • メモリの設定を見直そう


ApacheのログにPOSTで送信された内容をログ出力する方法

apache


Apacheのアクセスログには、デフォルトでGET形式で送信されたきたデータはログ出力されます。
しかし、POST形式で送信されたきたデータはログ出力されません。


実際には、Apacheが受信した時点でのHTTPリクエストにおけるPOSTデータを確認した場合があるかと思います。


というわけで今回は、POST形式のHTTPで送信されたきたデータをApacheのログに出力する方法を紹介します。


Apacheの設定を追加するだけで、ApacheのログにPOST形式で送信されたきたデータをログ出力できるようになります。


環境情報


  • OS:Windows10
  • Apache:Apache 2.4.41

mod_dumpioモジュールの有効化


POST形式で送信されたきたデータをログ出力するためには、「mod_dumpio」というApacheモジュールを有効にする必要があります。
「<Apacheインストールフォルダ>\conf」下の「httpd.conf」について、「mod_dumpio」を検索し、コメントアウトをはずして有効化します。


LoadModule dumpio_module modules/mod_dumpio.so

このモジュールを有効化することにより、HTTPリクエストの内容がログ出力されるようになります。


ログ出力設定の有効化


POST形式で送信されたきたデータをログ出力するためには、mod_dumpioモジュールの有効化以外に、httpd.confに3つの設定をおこなう必要があります。


  • 「DumpIOInput」ディレクティブの追記
  • 「DumpIOOutput」ディレクティブの追記
  • ログレベルを「dumpio:trace7」にする

「DumpIOInput」ディレクティブを追記します。
これを追記することで、HTTPリクエストの内容がログ出力されるようになります。

DumpIOInput On

「DumpIOOutput」ディレクティブを追記します。
これを追記することで、HTTPレスポンスの内容がログ出力されるようになります。

DumpIOOutput On

ログレベルを「dumpio:trace7」にします。

LogLevel dumpio:trace7

最後にApacheを再起動して、ログ出力の準備完了です。


POSTデータのログ出力


POST形式のリクエストがログ出力されるようになったのですが、具体的には「error.log」にログ出力されます。
以下のような感じです。

mod_dumpio:  dumpio_in (data-HEAP): Referer: http://localhost:81/test/post.html?query=1\r\n
mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
mod_dumpio:  dumpio_in (data-HEAP): 36 bytes
mod_dumpio:  dumpio_in (data-HEAP): Accept-Encoding: gzip, deflate, br\r\n
mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
mod_dumpio:  dumpio_in (data-HEAP): 42 bytes
mod_dumpio:  dumpio_in (data-HEAP): Accept-Language: ja,en-US;q=0.9,en;q=0.8\r\n
mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
mod_dumpio:  dumpio_in (data-HEAP): 2 bytes
mod_dumpio:  dumpio_in (data-HEAP): \r\n
mod_dumpio: dumpio_in [readbytes-blocking] 25 readbytes
mod_dumpio:  dumpio_in (data-HEAP): 25 bytes
mod_dumpio:  dumpio_in (data-HEAP): address=address&name=name



Apache+Tomcatのインストールと連携設定

apache

こんにちは。

さくさくTECHブロガーの「さく」です。


今回は、ApacheとTomcatをインストールし、連携をおこなうまでの方法を紹介します。


ApacheはHTTPサーバで、TomcatはWEBサーバになります。
どちらも単独で動かすことができますが、ちょっとしたWEBアプリケーションでは、連携して環境を構築するパターンが多いです。

その場合、フロント側にApache、バック側にTomcatを設置します。
WEBアプリケーションはTomcat上に乗せた場合、Apacheで受けたHTTPリクエストをTomcatに連携する必要があります。


環境情報


  • OS:Windows10
  • Apache:Apache 2.4.41
  • Tomcat:Tomcat 8.5.51

Apacheのダウンロードとインストール


今回は、Windows(64Bit)の「Apache 2.4.41」をダウンロードします。

Apacheのダウンロードは、以下のサイトから可能です。



Apacheのダウンロード

ZIPファイルを解凍すると、「httpd-2.4.41-win64-VC14」というフォルダが解凍されます。
「httpd-2.4.41-win64-VC14」フォルダ配下の「Apache24」を、Cドライブ直下に格納します。


次のDOSプロンプトを起動し、インストールの準備をおこないます。
DOSプロンプトを管理者権限で起動します。

管理者として実行

ユーザアカウント制御の確認ダイアログが表示されますが、「はい」を押下して先に進みます。

管理者としての実行

DOSプロンプトが開いたら、先ほどダウンロードした「Apache24」配下に存在する「\bin」フォルダに移動します。

コマンドプロンプト

以下コマンドを実行し、インストールを開始します。

httpd.exe -k install

インストールコマンドを実行していますが、実態はサービス化とサービスの起動をおこなっているようです。
なので、サービスの起動に失敗した場合は以下ようなメッセージが表示されます。

c:\Apache24\bin>httpd.exe -k install
Installing the 'Apache2.4' service
The 'Apache2.4' service is successfully installed.
Testing httpd.conf....
Errors reported here must be corrected before the service can be started.
(OS 10013)アクセス許可で禁じられた方法でソケットにアクセスしようとしました。  : AH00072: make_sock: could not bind to address [::]:80
(OS 10013)アクセス許可で禁じられた方法でソケットにアクセスしようとしました。  : AH00072: make_sock: could not bind to address 0.0.0.0:80
AH00451: no listening sockets available, shutting down
AH00015: Unable to open logs

「Errors reported・・・」以降がエラーの内容です。
筆者の場合は上記のようなエラーになりましたが、インストールしようとするマシンによってエラーの内容は異なるかと思います。


今回は、上記エラーの原因を探ります。
エラーメッセージの内容から、Apacheが使用する80ポートが既に使用されているようです。
「netstat -oab」コマンドを実行し、80ポートを使用しているアプリケーションを探します。

c:\Apache24\bin>netstat -oab
アクティブな接続
  プロトコル  ローカル アドレス      外部アドレス           状態            PID
  TCP         0.0.0.0:80             DESKTOP-U7JE3FQ:0      LISTENING       4

PID=4のアプリケーションが80ポートを使用しているようです。
PID=4のアプリケーションを特定します。


「tasklist」コマンドを実行して確認してみます。

c:\Apache24\bin>tasklist
イメージ名                     PID セッション名     セッション# メモリ使用量
========================= ======== ================ =========== ============
System Idle Process              0 Services                   0          8 K
System                           4 Services                   0      1,492 K

「System」ってあるけど。。。なに?って感じです。


いろいろググりましたが、特定するのが面倒になってきたので、Apacheのデフォルトポートを変更することにします。
Apacheのデフォルトポートは、「C:\Apache24\conf\httpd.conf」に定義されています。
『Listen』で検索すると80と定義されている箇所があるので、アプリケーションが使用していないポートに変更します。
筆者は81に変更してみました。

# Change this to Listen on specific IP addresses as shown below to 
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
#80→81
Listen 81

再度、Apacheを起動してみます。
「コントロールパネル」→「サービス」からApacheを指定し、サービスの開始をおこないます。
状態が「実行中」になったら起動成功になります。

サービスでのApache起動確認

最後にブラウザからアクセスして、Apacheが起動したかを確認します。
「http://localhost:81/」をブラウザのURLバーに入力し、起動確認します。

Apacheの起動確認

WEB画面上に「It works!」が表示されていれば、Apacheがきちんと起動していることになります。


これで、Apacheのインストールと起動確認は完了です。


Tomcatのダウンロードとインストール


今回は、Windows(64Bit)の「Tomcat 8.5.51」をダウンロードします。
バイナリ版をダウンロードします。



Tomcatのダウンロード

ZIPファイルを解凍すると、「apache-tomcat-8.5.51」というフォルダが解凍されます。
そのフォルダをCドライブ直下に格納します。


ここから、Tomcat起動のための準備をおこないます。


最初に「CATALINA_HOME」の設定をおこないます。

「CATALINA_HOME」の設定

次に、tomcatのbin下に「パス」を設定します。

tomcatのパス設定

最後に「JAVA_HOME」です。

「JAVA_HOME」の設定

環境変数の設定は完了したらので、Tomcatを起動してみます。
Apacheのインストール時と同様に、管理者権限でDOSプロンプトをひらきます。
「c:\apache-tomcat-8.5.51\bin」に移動したら、「startup.bat」を実行します。

c:\apache-tomcat-8.5.51\bin>startup.bat

別ウィンドウでログが表示されれば起動成功です。
以下のようなログがウィンドウに表示されます。
以下のログは、Tomcatのログフォルダにも出力されます。

15-Feb-2020 16:59:55.242 情報 [main] org.apache.catalina.core.StandardService.startInternal サービス [Catalina] を起動します
15-Feb-2020 16:59:55.242 情報 [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.51
15-Feb-2020 16:59:55.253 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Webアプリケーションディレクトリ [C:\apache-tomcat-8.5.51\webapps\docs] を配備します
15-Feb-2020 16:59:55.583 警告 [localhost-startStop-1] org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom セッション ID を生成するための SecureRandom インスタンスの作成に [147] ミリ秒かかりました。アルゴリズムは [147] です。
15-Feb-2020 16:59:55.599 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory ディレクトリ [C:\apache-tomcat-8.5.51\webapps\docs] の Web アプリケーションの配置は [346] ms で完了しました。
15-Feb-2020 16:59:55.599 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Webアプリケーションディレクトリ [C:\apache-tomcat-8.5.51\webapps\examples] を配備します
15-Feb-2020 16:59:55.898 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory ディレクトリ [C:\apache-tomcat-8.5.51\webapps\examples] の Web アプリケーションの配置は [299] ms で完了しました。
15-Feb-2020 16:59:55.898 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Webアプリケーションディレクトリ [C:\apache-tomcat-8.5.51\webapps\host-manager] を配備します
15-Feb-2020 16:59:55.944 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory ディレクトリ [C:\apache-tomcat-8.5.51\webapps\host-manager] の Web アプリケーションの配置は [46] ms で完了しました。
15-Feb-2020 16:59:55.945 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Webアプリケーションディレクトリ [C:\apache-tomcat-8.5.51\webapps\manager] を配備します
15-Feb-2020 16:59:55.972 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory ディレクトリ [C:\apache-tomcat-8.5.51\webapps\manager] の Web アプリケーションの配置は [27] ms で完了しました。
15-Feb-2020 16:59:55.972 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Webアプリケーションディレクトリ [C:\apache-tomcat-8.5.51\webapps\ROOT] を配備します
15-Feb-2020 16:59:55.995 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory ディレクトリ [C:\apache-tomcat-8.5.51\webapps\ROOT] の Web アプリケーションの配置は [23] ms で完了しました。
15-Feb-2020 16:59:56.000 情報 [main] org.apache.coyote.AbstractProtocol.start プロトコルハンドラー ["http-nio-8080"] を開始しました。
15-Feb-2020 16:59:56.011 情報 [main] org.apache.catalina.startup.Catalina.start Server startup in 797 ms

最後にブラウザからアクセスして、Tomcatが起動したかを確認します。
「http://localhost:8080/」をブラウザのURLバーに入力し、起動確認します。

Tomcatの起動確認

上記のTomcat画面が表示されれば、Tomcatの起動成功です。


ちなみに、起動は「startup.bat」ですが、終了は「shutdown.bat」になります。
「shutdown.bat」を実行すると、Tomcatは停止されます。


ApacheとTomcatのバージョン確認


インストールしたApacheとTomcatのバージョンを確認しておきます。

Apacheのバージョンは、DOSプロンプトで以下のコマンドを実行します。

c:\Apache24\bin>httpd -v
Server version: Apache/2.4.41 (Win64)
Apache Lounge VC14 Server built:   Aug 12 2019 10:48:01

インストールしたApacheのバージョンが「2.4.41」であることがわります。


次にTomcatのバージョンを確認します。
Tomcatのバージョンは、インストールされた「version.bat」を実行します。

C:\Program Files\Apache Software Foundation\Tomcat 8.5\bin>version.bat
Using CATALINA_BASE:   "C:\Program Files\Apache Software Foundation\Tomcat 8.5"
Using CATALINA_HOME:   "C:\Program Files\Apache Software Foundation\Tomcat 8.5"
Using CATALINA_TMPDIR: "C:\Program Files\Apache Software Foundation\Tomcat 8.5\temp"
Using JRE_HOME:        "C:\Program Files\Java\jdk1.8.0_60"
Using CLASSPATH:       "C:\Program Files\Apache Software Foundation\Tomcat 8.5\bin\bootstrap.jar;C:\Program Files\Apache Software Foundation\Tomcat 8.5\bin\tomcat-juli.jar"
Server version: Apache Tomcat/8.0.41.0
Server built:   Sep 28 2017 10:30:11 UTC
Server number:  8.0.41.0
OS Name:        Windows 10
OS Version:     10.0
Architecture:   amd64
JVM Version:    1.8.0_60-b27
JVM Vendor:     Oracle Corporation

インストールしたTomcatのバージョンが「8.0.41」であることがわります。



ApacheとTomcatの連携設定


最後に、ApacheとTomcatの連携をおこないます。
Apacheでリクエストを受け付け、受け付けたリクエストをTomcatに転送します。


Tomcatに連携するドキュメントルートを準備


Tomcatに新たなドキュメントルートを設けます。
最終的に、ここで作成するドキュメントルートについて、Apacheと連携します。


今回は、Tomcatのドキュメントルートに「test」というフォルダを作成し、HelloWorldを表示するHTMLを準備します。


Tomcatにアクセスし、配置した「helloWorld.html」がブラウザで表示されることを確認します。
ブラウザで「http://localhost:8080/test/helloWorld.html」を入力して確認します。

ドキュメントルートの設定

この時点では、まだApacheとTomcatの接続はおこなわれていません。
8080ポートでアクセスしているので、現時点ではまだTomcat直接アクセスになっています。


8080ポートを停止し、AJPプロトコルでの接続準備


現時点では8080ポートで直接接続が可能な状態ですが、Apache経由での接続に切り替えるため、8080ポートでの直接接続を出来ないようにします。


Tomcatインストールディレクトリの「\conf\server.xml」をひらき、8080ポートでの接続設定をコメントアウトします。

    <!--					
    <Connector port="8080" protocol="HTTP/1.1"					
               connectionTimeout="20000"					
               redirectPort="8443" />					
    -->					

server.xmlの修正が完了したらTomcatを再起動します。

再起動が完了したら、再度、8080ポートへのアクセスをおこない、アクセスできなかったら設定変更は成功です。

server.xmlの設定変更

次に、「AJP/1.3」を使用してApacheとの接続準備をおこないます。
インストール時点でserver.xmlに設定が入っている場合もあれば、設定が入っているがコメントアウトされている場合もあります。
筆者のTomcatインストール時点ではコメントアウトされていたので、Apacheとの接続設定部分についてコメントアウトをはずしておきます。

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector protocol="AJP/1.3"
               address="::1"
               port="8009"
               redirectPort="8443" />

server.xmlの修正が完了したらTomcatを再起動します。
しかし、上記の設定(デフォルト)では、エラーが出てしまい起動に失敗してしまいました。

15-Feb-2020 17:50:18.727 重大 [main] org.apache.catalina.core.StandardService.startInternal Failed to start connector [Connector[AJP/1.3-8009]]		
	org.apache.catalina.LifecycleException: プロトコルハンドラの起動に失敗しました	
		at org.apache.catalina.connector.Connector.startInternal(Connector.java:1057)
		at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
		at org.apache.catalina.core.StandardService.startInternal(StandardService.java:440)
		at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
		at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:766)
		at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
		at org.apache.catalina.startup.Catalina.start(Catalina.java:688)
		at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
		at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
		at java.lang.reflect.Method.invoke(Method.java:497)
		at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
		at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)
	Caused by: java.lang.IllegalArgumentException: The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.	
		at org.apache.coyote.ajp.AbstractAjpProtocol.start(AbstractAjpProtocol.java:274)
		at org.apache.catalina.connector.Connector.startInternal(Connector.java:1055)
		... 12 more

どうやら「secretRequired」というオプションの設定が必須のようです。
この設定は、AJPコネクタを信頼できないサイトと接続する際に使用するオプションのようです。
Tomcatのマニュアルに「信頼できるサイトと接続する場合にのみfalseを設定すること」とあるので、今回は「false」を設定します。


    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector protocol="AJP/1.3"
               address="::1"
               port="8009"
               secretRequired="false"
               redirectPort="8443" />

server.xmlの修正が完了したらTomcatを再起動し、エラーが発生せずに起動が完了したら変更完了です。


Apacheの設定


最後にApacheの設定をおこないます。
Apache側でproxy_ajpを使用するようにします。


proxy_ajpを使用するためには、Apacheのproxy_ajpモジュールを使用するようにします。
使用するモジュールは以下の2つです。


  • mod_proxy.so
  • mod_proxy_ajp.so

Apacheのhttpd.conf内をモジュール名で検索し、以下のようにコメントアウトをはずします。

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

一応、Apacheを再起動して無事に起動すること(モジュールを使えるようになったこと)を確認します。

Apacheの起動確認

最後に、ApacheにTomcatとの接続設定をおこないます。
以下の設定を追加します。

<Location /test/>					
    ProxyPass ajp://localhost:8009/test/					
</Location>					

この設定を「httpd.conf」に追加すればよいのですが、Apacheの記述ルールに従って記述を追加します。
「httpd-proxy.conf」を作成し、上記の記述を追加し、「httpd.conf」の中に「httpd-proxy.conf」の読み込み設定をおこなえば設定完了です。


Include conf/extra/httpd-proxy.conf

最後にApacheを再起動して無事に起動が完了したら設定完了です。


これで、ApacheとTomcatがAJPを使用して接続されました。
以下のURLをブラウザに入力して、最終確認します。


http://localhost:81/test/helloWorld.html

ApacheとTomcatの接続設定

Apacheのデフォルトポートに設定した「81」を経由して、Tomcat上に格納したHelloWorldを表示するHTMLの表示がおこなわれました。