第7回 SSIの仕組みと有効化・制限の設定

SSIを使えば複数のページで共通部分を一元化できるなどのメリットがある。ただし、サーバへの負荷やセキュリティといった要素も考えると無制限に使うべきではない。デメリットを排してメリットだけを享受するには適切な設定が必要だ。

Index
ApacheによるWebサーバ構築
動的なコンテンツ生成を実現するSSI
 SSIの動作原理
 SSIの制限
  ApacheでSSIを利用するための設定
 SSIの有効化
 SSIが使えるディレクトリの限定
  ファイル一覧表示機能の設定

動的なコンテンツ生成を実現するSSI

 皆さんはSSI(Server Side Include)をご存じだろうか。SSIは、CGIと同じく動的にコンテンツ(HTML)を生成するための技術だ。

 Webサイトの多くは全ページ共通の部分を少なからず持っている。例えば、ページの上にはコンテンツのナビゲーションタブ、ページの下にはCopyrightなどのメッセージといった具合である。これらの共通部分は、各ファイルに記述するよりも共通のファイルに分離しておく方が効率がよい。なぜならば、共通部分に何らかの修正が発生した場合に、複数のファイルを修正するよりも1つのファイルを修正するだけで済む方が簡単で確実だからだ。同じ修正を複数のファイルに実施するのは、ケアレスミスを誘発する原因になる。

 SSIを利用すれば、共通の部分を別のファイルに分離できるようになる。SSIはその命令の中で、別のファイルの内容を読み取れるからだ。

 こうして説明していてもイメージをつかみにくいだろうから、実際にSSIの命令を含んだHTMLを見ていただこう。リスト1がそれである。

<HTML>
<HEAD><TITLE>SSI Sample</TITLE></HEAD>
<BODY>
<!--#include virtual="/common/header.html" -->
コンテンツの中身を記述
<!--#include virtual="/common/footer.html" -->
</BODY>
</HTML>
リスト1 SSIのサンプル(body.shtml)

 リスト1に含まれる、

<!--#include virtual="/common/header.html" -->

は、「/common/header.html」(仮想パス)で示されるファイルの内容をその位置に読み込んで置き換えることを意味している。従って、body.shtmlが呼び出されると、コンテンツの先頭と最後の内容はそれぞれ別ファイル(header.htmlとfooter.html)の内容に置き換えられることになる。ちなみに、SSIは文字どおりサーバ側(Server Side)で処理されるため、このページにアクセスしたブラウザにはその内容が普通のHTMLにしか見えない

 SSIには、ここで紹介した「include」命令のほかにもさまざまな命令が用意されている(編注)。しかし、それは本稿の趣旨から外れてしまうので詳しくは紹介しない。ここでは、SSIの動作原理とApacheにおける設定についてだけ解説しようと思う。

編注:SSIの機能の一部を紹介する。

<!--#fsize file="filename"--> filenameで指定したファイルのサイズを表示する
<!--#config sizefmt="format"--> #fsizeの表示フォーマット指定。sizefmt="bytes"にするとbytes単位、sizefmt="abbrev"とするとbytes、Kbytes……のように単位を自動的に付加する
<!--#flastmod file="filename"--> filenameで指定したファイルの最終更新日時(Webサーバにアップロードした時刻)を表示する
<!--#config timefmt="format"--> #flastmodなどの日時表示フォーマット指定
<!--#exec cmd="command"--> commandで指定したコマンドを実行し、その結果を表示
<!--#exec cgi="xxx.cgi"--> xxx.cgiで指定したCGIを実行し、その結果を表示

SSIの動作原理

 SSIの動作原理は極めて単純である。ApacheをはじめとするSSIをサポートするWebサーバには、SSIの命令を含むHTMLを解釈するためのエンジンが備えられている。それを、仮に「SSIエンジン」と呼ぶことにしよう。

 SSIエンジンがSSIの命令を含むファイルを読み込むと、そこに記述された命令を実行して命令とその結果を置き換える。先ほど例に挙げた「別ファイルの内容を読み込む」という命令(include)であれば、読み込んだファイルの内容とinclude命令を置き換える。その結果、Webサーバから返される内容は通常のHTMLとなる。

 ちなみに、もしSSIエンジンを経由することなく、SSIの命令を含んだファイルがそのままWebブラウザに返されてしまったとする。その場合でも、SSIの命令はHTMLのコメント形式となっている(<!--と-->で囲まれている)ため、Webブラウザには特に影響を与えない。ただ単に、本来SSIによって埋められるはずであった部分が抜け落ち、中途半端な内容が表示されるだけである。

 話が少し横道にそれてしまったが、どうやってSSIエンジンにファイルを読み込ませるのかを解説しよう。実は、この方法も、極めて簡単なのである。

 1つは、SSIの命令を含んだファイルをある特定のディレクトリに配置する方法である。この方法であれば、そのディレクトリに置かれたファイルはすべてSSIの命令を含んだものとして扱うことで問題を解決できる。もう1つは、拡張子を使う方法である。例えば、shtmlという拡張子のファイルは「SSIの命令を含んだもの」として扱うのである。

 Apacheは両方の方法を組み合わせて対応する。特定のディレクトリ(1つとは限らない)に置かれた、特定の拡張子(これも1つとは限らない)を持つファイルを、SSIの命令を含んだファイルとして判断する。

 では、なぜすべてのファイルに対してSSIエンジンを使わないのだろうか。すべてに対してSSIエンジンを利用すれば、面倒な設定などしなくても済んでしまう。しかし、それは現実的ではない。1つは、パフォーマンスの問題である。SSIエンジンは、さほど重いものではないが、すべてのファイルを解析させるとやはりパフォーマンスに影響を与えてしまう。

 もう1つはセキュリティの問題である。SSIに用意される命令は、使い方によってはサーバ上の制限された情報へのアクセスを実現するものもある。従って、どのディレクトリに置かれたファイルでもSSIを利用できるのでは都合が悪いのだ。SSIは、管理者の管理下に置かれた特定のディレクトリでのみ利用されるべきなのである。

SSIの制限

 SSIを利用するうえで注意しなくてはならない制限が1つだけある。それは、「CGIプログラムやJavaプログラムの出力結果をSSIエンジンに渡すことはできない」という点だ。

 CGIプログラムやJavaプログラムの出力結果にSSIの命令を埋め込み、SSIエンジンに解析させることはできない。なぜなら、SSIは特定のディレクトリの特定の拡張子のファイルを対象に解析を行うからだ。CGIプログラムやJavaプログラムの出力結果に対して解析を行わせる設定は存在しないのである。

 この問題を解決するには、特殊な技術が必要になる。いくつかのアプリケーションサーバ製品ではすでにこの問題を解決しているが、Apacheにはまだできない。「まだ」と表現したのは、Apache 2.0で解決される予定だからだ。

 とはいえ、CGIプログラムやJavaプログラムを使えば、SSIを使う必要はないはずである。SSIにできることはCGIやJavaのプログラムでも実現できるからだ。

ApacheでSSIを利用するための設定

 それでは、実際にApacheでSSIを実現するための設定を紹介する。

SSIの有効化

 まずは、特定の拡張子のファイルに対してSSIを有効にする設定から紹介しよう。この設定は非常に簡単である。

 Apacheの設定ファイル(httpd.conf)の中に、リスト2のような記述がある。

# To use server-parsed HTML files
#
#AddType text/html .shtml
#AddHandler server-parsed .shtml
リスト2 httpd.confの一部

 リスト2では、行の先頭にコメントを意味する「#」が付けられているので、「AddType」と「AddHandler」の行の「#」を削除して有効化する。

# To use server-parsed HTML files
#
AddType text/html .shtml
AddHandler server-parsed .shtml
リスト3 リスト2を修正してAddTypeとAddHandlerを有効化

 ファイルの内容を修正したら、ファイルを保存してApacheを再起動する。これで、修正した内容が実際に有効になる。しかし、まだ設定を変更するから、いますぐ有効にする必要はない。すべての設定変更が終わってからApacheを再起動することにしよう。

 上記の設定は、拡張子「shtml」のファイルをSSIエンジンで解析するためのものである。もし、別の拡張子もSSIエンジンで解析するようにしたければ、2つの行の右端に書かれた拡張子を変更する。

 2つの設定のうち、AddTypeディレクティブはMIME-Typeの設定のために利用する(MIME-Typeについては、この連載の第2回を参考にしていただきたい)。従って、このディレクティブはSSIを有効にするために必須の設定とはいえない。MIME-Typeの設定は、あくまでもクライアントとのやりとりに使われるだけだからである。

 これに対し、AddHandlerディレクティブの方は、SSIを有効にするために欠かせない。このディレクティブを使うことで、その拡張子のファイルは「server-parsed」で実行するという指示を行うからだ。「server-parsed」というのは、Apacheの内部的な表現だから、決まり文句と思ってもらえばいい。

 ちなみに、AddTypeとAddHandlerディレクティブはmod_mimeモジュールを利用している。また、「server-parsed」つまりSSIエンジンはmod_includeモジュールを利用している。どちらもApacheのインストール時に自動的にインストールされるモジュールだから、特に心配しなくても利用できるはずである。

SSIが使えるディレクトリの限定

 次に、特定のディレクトリに置かれたファイルをSSIエンジンに解析させる方法を紹介しよう。繰り返しになるが、Apacheはディレクトリと拡張子の両方を判断して、SSIエンジンにファイルの内容を解析させる。

 この設定は、Directoryディレクティブに囲まれたOptionsディレクティブで行う。Directoryディレクティブは、特定の実ディレクトリに対して、制限などさまざまな設定を行うものである。Webサーバの動作をディレクトリごとに細かく指定したい場合に使う。

 このディレクティブは、リスト4のように、必ず<Directory></Directory>を組み合わせて利用する。こうすることで、その間に複数のディレクティブを記述できる。

<Directory /usr/local/apache/htdocs/ssi>
  Options Includes
</Directory>
リスト4 SSIの設定だけを行った最小限のDirectoryディレクティブ

 リスト4の例では、「/usr/local/apache/htdocs/ssi」というディレクトリだけを対象とした設定になっている。Directoryディレクティブの間に書かれたOptionsディレクティブは、そのディレクトリで利用可能な機能を指定する。Optionsディレクティブに記述できるオプションは下の表のとおりである。

All すべてのオプションを有効にする(デフォルト)
None すべてを無効にする
ExecCGI CGIの実行を許可する
Includes SSIを有効にする
IncludesNOEXEC SSIを有効にするが、EXEC命令(CGIプログラムを実行する命令)は無効にする
Indexes 指定されたファイルが存在しない場合にファイル一覧を表示する
MultiViews 言語サポート機能を有効にする
FollowSymLinks シンボリックリンクで示されたファイルにアクセスすることを可能にする
SymLinksIfOwnerMatch シンボリックリンクで示されたファイルにアクセスすることを可能にするが、リンク先のファイルとリンクのオーナーが一致しなければならない
表 Optionsディレクティブオプション一覧

 のとおり、SSIに関係するのはIncludesIncludesNOEXECの2つだけである。単純にSSIを有効したい場合は、Optionsディレクティブに対して「Includes」あるいは「All」と書けばいい。ただし、「All」の場合はほかのオプションも有効になってしまう。SSIは使いたいが、SSIからCGIを呼び出すのは禁じたいという場合は「IncludesNOEXEC」と書く。SSIからCGIを呼び出さないようにするのは、CGIのセキュリティ上の問題を回避したいからにほかならない。

 以下に、Optionsディレクティブの例をいくつか挙げておく。

<Directory "/home/httpd/cgi-bin">
  Options ExecCGI
</Directory>
cgi-binディレクトリでCGIの実行を許可

<Directory "/home/*/public_html>
  Options ExecCGI Includes
</Directory>
(お勧めはできないが)各ユーザーディレクトリでCGIとSSIの実行を許可

 AddTypeとAddHandlerディレクティブ、それにDirectoryディレクティブ内のOptionsディレクティブを修正したら、Apacheを再起動して修正を有効にする。これで、Directoryディレクティブに指定されたディレクトリでは、AddHandlerディレクティブで指定した拡張子のファイルをSSIエンジンに解析させる。実際にSSIの命令を含んだファイルを作成して実験してみるといいだろう。

ファイル一覧表示機能の設定

 Directoryディレクティブの話が出たついでに、ほかのオプションについて補足しておこう。ここではIndexesオプションについてだけ説明することにする。

 Indexesオプションは、Directoryディレクティブで指定するディレクトリに既定のファイルが存在しなかった場合の動作を決定する。「既定のファイル」とは、ファイル名を省略した場合に補完するファイル名のことを指す。一般に、このファイルは「index.html」であり、ApacheではDirectory_Indexディレクティブで設定されている(編注)。

編注:既定のファイルあるいはデフォルトファイルと呼ばれるファイルは、index.html以外にもindex.htm、default.html、default.htmなどが使われることもある。

 例えば、http://www.atmarkit.co.jp/flinux/にアクセスした場合、Apacheは「flinux」という仮想ディレクトリが示す実ディレクトリにアクセスし、index.html(Directory_Indexディレクティブで指定されたファイル)を探す。このファイルが存在しなかった場合、そのディレクトリでIndexesオプションが有効になっているかどうかが動作に影響を与える。

 Indexesが有効になっていると、ブラウザはディレクトリに格納されたファイルの一覧を表示する。Indexesが無効だった場合は単にエラーが表示されるだけである。

Indexesが有効になっていると、ディレクトリの内容がそのまま表示されてしまう

 この機能は、mod_autoindexモジュールで実現している。一見便利ではあるが、セキュリティの面ではあまり有効にしたくないオプションである。なぜなら、ファイルの一覧が表示されてしまうと、そのディレクトリに置かれたファイルの状態を把握されるばかりか、ディレクトリ構造まで知られてしまう恐れがあるからである。

 Optionsディレクティブに関していえば、できる限り「None」を選択するのがセキュリティ的には安全である。もちろん、必要であればその機能を有効にするしかない。しかし、必要もないのに有効にしておくことは感心できるものではない。

 Apacheでは、特に指定しなければAllを選択したことになってしまうし、あらかじめ記述されたDirectoryディレクティブでは、デフォルトでIndexesとFollowSymLinksを有効にしている。Directoryディレクティブの記述をチェックして、不必要なオプションは削除するよう強く勧める。