.htaccessファイルをweb.configに変換する際の注意事項

発行日 : 2009 年 2 月 18 日 (作業者 : stjacobs)

更新日 : 2009 年 2 月 27 日 (作業者 : stjacobs)

.htaccess ファイルを web.config に変換する際の注意事項

多くの PHP アプリケーションは、Apache Web サーバーの構成ファイルと共に配布されます。 これらの構成ファイル (一般に .htaccess と呼ばれます) には、アプリケーションを Web サーバーの機能と統合するためのさまざまな設定が格納されています。 IIS 7 では、web.config というファイルを使用して、アプリケーションと統合するための設定が格納されます。 以降のセクションでは、PHP アプリケーションによる .htaccess ファイルの最も一般的な使用法と共に、IIS の web.config ファイルを使用して、求める結果を達成する手順について説明します。

サンプル アプリケーション

テスト用の Application の .htaccess ファイルを次に示します。 このファイルの各セクションを調べて、IIS で同じ機能を確立する方法を検討しましょう。

要求のフィルタリング

Application では、FilesMatch ディレクティブを使用して、アプリケーションのコンポーネントであるファイルへのブラウザー アクセスを制限します。

<FilesMatch "\.(engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(code-style\.pl|Entries.*|Repository|Root|Tag|Template)$">
  Order allow,deny
</FilesMatch>

IIS では、要求フィルター モジュールを使用して、このようなファイルへのブラウザー アクセスを制限します。 たとえば、Application の場合、セクションは次のようになります。

<security>
            <requestFiltering>
                <denyUrlSequences>
                    <add sequence="engine" />
                    <add sequence="inc" />
                    <add sequence="info" />
                    <add sequence="install" />
                    <add sequence="module" />
                    <add sequence="profile" />
                    <add sequence="po" />
                    <add sequence="sh" />
                    <add sequence="theme" />
                    <add sequence="tpl(\.php" />
                    <add sequence="Root" />
                    <add sequence="Tag" />
                    <add sequence="Template" />
                    <add sequence="Repository" />
                    <add sequence="code-style" />
                </denyUrlSequences>
                <fileExtensions>
                    <add fileExtension=".sql" allowed="false" />
                    <add fileExtension=".pl" allowed="false" />
                </fileExtensions>
            </requestFiltering>
        </security>
        

注 : このフィルターによってインストール スクリプトがブロックされるので、インストールのためにこのセクションをコメントにしておきます。

要求のフィルタリグを使用する代わりに、URL の書き換えモジュール (後述) を使用して、一致するファイルの種類について 403 エラーを返す方法もあります。この方法では正規表現を使用して照合が行われるので、こちらをお勧めします。

<rule name="Protect files and directories from prying eyes" stopProcessing="true"> 
                <match url="\.(engine|inc|info|install|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl|svn-base)$|^(code-style\.pl|Entries.*|Repository|Root|Tag|Template|all-wcprops|entries|format)$" /> 
                <action type="CustomResponse" statusCode="403" subStatusCode="0" 
                    statusReason="Forbidden" 
                    statusDescription="Access is forbidden." /> 
        </rule>
        

既定のドキュメント

DirectoryIndex ディレクティブは、URL にファイル名が含まれていない場合に読み込むファイルを Web サーバーに指示します。

# 既定のハンドラーを設定します。
DirectoryIndex index.php

IIS の場合、モジュール ハンドラーと同じレベルの Web サイト階層で既定のドキュメントを設定する必要があります。 たとえば、PHP では通常、モジュール ハンドラーは Web サーバー レベルで設定されます。 Web サイトのコンテキスト内でローカルに設定するのではなく、既定のドキュメントもそのレベルで設定する必要があります。  アプリケーションで確実にそのように設定するには、web.config ファイル内で次のスニペットを使用します。

  <defaultDocument>
            <files>
                <remove value="index.php" />
                <add value="index.php" />
            </files>
        </defaultDocument> 
                

URL の書き換え

IIS 7 には、"URL の書き換え" という拡張機能があります。 この拡張機能を使用すると、着信した URL 要求を書き換えるルールを IIS に提供することができます。 URL の書き換えは、短くて覚えやすい URL を使用する必要があるアプリケーションに最もよく使われます。 現在、多くの PHP アプリケーションに、.htaccess ファイルの一部として書き換えルールが付属しています。 これらのルールは、着信要求をいつどのように書き換えるかを Apache の mod_rewrite に指示します。 IIS 7 の URL の書き換えモジュールは、これらのルールを読み取り、URL の書き換えルールに変換することができます。 この手順の概要については、次のリンク先のドキュメントを参照してください。

http://learn.iis.net/page.aspx/470/importing-apache-modrewrite-rules/

Application の場合、関連する mod_rewrite ルールは次のとおりです。

RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
  RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
    

IIS の URL の書き換えモジュールは、これらのルールを読み取り、変換することができます。 変換後の URL の書き換えモジュール ルールは次のとおりです。

<rewrite>
  <rules>
    <rule name="Imported Rule 1" stopProcessing="true">
      <match url="^(.*)$" ignoreCase="false" />
      <conditions>
        <add input="{HTTP_HOST}" pattern="^example\.com$" />
      </conditions>
      <action type="Redirect" redirectType="Permanent" url="http://www.example.com/{R:1}" />
    </rule>
    <rule name="Imported Rule 2" stopProcessing="true">
      <match url="^(.*)$" ignoreCase="false" />
      <conditions>
        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
        <add input="{URL}" pattern="^/favicon.ico$" ignoreCase="false" negate="true" />
      </conditions>
      <action type="Rewrite" url="index.php?q={R:1}" appendQueryString="true" />
    </rule>
  </rules>
</rewrite>
    

エラー ページのリダイレクトと処理

Web サーバーから返される "ページが見つかりません " という標準的なエラー メッセージは、一般にはアプリケーションに統合されていないようです。 しかし、Application のように、アプリケーションの範囲内でこのようなエラーを処理するよう選択するアプリケーションもあります。 次の ErrorDocument ディレクティブは、404 エラーまたは "ファイルが見つかりません" というエラーが発生した場合にホーム ページを読み込むよう Web サーバーに指示します。

# Application に 404 エラーの処理を行わせます。
ErrorDocument 404 /index.php

IIS では、この機能に httpErrors ディレクティブを使用します。 ただし、IIS ではアプリケーション レベルでこれを設定する機能が既定で無効になっているので、出荷時にはこのセクションをコメントにする必要があります。

 <!-- HTTP Errors section should only be enabled if the "Error Pages"
        feature has been delegated as "Read/Write" at the Web Server level.
           <httpErrors>
               <remove statusCode="404" subStatusCode="-1" />
               <error statusCode="404" prefixLanguageFilePath="" path="/index.php" responseMode="ExecuteURL" />
           </httpErrors>
        -->
    

ディレクトリの参照

別のアプリケーション セキュリティ/整合性対策として、クライアントからのディレクトリの参照を無効にする機能を実装することがよくあります。 多くの Web サーバーの構成では、ユーザーは、既定のドキュメント ファイルのいずれかを含まないディレクトリ内のファイルの一覧を参照することができます。 Application では、Options ディレクティブを使用してこれを無効にします。

# ディレクトリにマップされる URL についてディレクトリ一覧を表示しません。
Options -Indexes

IIS では、directoryBrowse ディレクティブを使用してこのアクセスを制限します。

<directoryBrowse enabled="false" />

キャッシュ期限

キャッシュ ディレクティブを使用すると、静的コンテンツはしばらくの間キャッシュし、動的コンテンツはまったくキャッシュしないようにすることができます。 Application では、mod_expires モジュールで提供される ExpiresBy ディレクティブを使用します。

# mod_expires を有効にする必要があります。
<IfModule mod_expires.c>
  # 有効期限を有効にします。
 ExpiresActive On
 
  # アクセス (A) 後 2 週間、すべてのファイルをキャッシュします。
 ExpiresDefault A1209600
 
  # 動的に生成されたページはキャッシュしません。
 ExpiresByType text/html A1
</IfModule>

IIS では、出力キャッシュ モジュールと caching ディレクティブを使用してキャッシングを制御します。Application では、最大期限を 14 日間として .html ファイルのキャッシュを有効にします。 .php ファイルについては、キャッシュがまったく行われないようにします。

<caching>
            <profiles>
                <add extension=".php" policy="DisableCache" kernelCachePolicy="DisableCache" />
                <add extension=".html" policy="CacheForTimePeriod" kernelCachePolicy="CacheForTimePeriod" duration="14:00:00:00" />
            </profiles>
        </caching>

サンプル アプリケーション の .htaccess ファイル

# Apache/PHP/Application の設定 :
 
# ファイルおよびディレクトリを好奇の目から保護します。
<FilesMatch ".(engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(.php)?|xtmpl)$|^(code-style.pl|Entries.*|Repository|Root|Tag|Template)$">
  Order allow,deny
</FilesMatch>
 
# ディレクトリにマップされる URL についてディレクトリ一覧を表示しません。
Options -Indexes
 
# このディレクトリ内のシンボリック リンクのリンク先を表示します。
Options +FollowSymLinks
 
# Application に 404 エラーの処理を行わせます。
ErrorDocument 404 /index.php
 
# 存在しない favicon.ico に対する要求に単純なエラー メッセージを適用します。
<Files favicon.ico>
  ErrorDocument 404 "The requested file favicon.ico was not found.
</Files>
 
# 既定のハンドラーを設定します。
DirectoryIndex index.php
 
# PHP の設定を上書きします。さらに、sites/default/settings.php の設定を変更します。
# ただし、実行時に次の設定を変更することはできません。
 
# PHP 4、Apache 1
<IfModule mod_php4.c>
  php_value magic_quotes_gpc                0
  php_value register_globals                0
  php_value session.auto_start              0
  php_value mbstring.http_input             pass
  php_value mbstring.http_output            pass
  php_value mbstring.encoding_translation   0
</IfModule>

# PHP 4、Apache 2
<IfModule sapi_apache2.c>
  php_value magic_quotes_gpc                0
  php_value register_globals                0
  php_value session.auto_start              0
  php_value mbstring.http_input             pass
  php_value mbstring.http_output            pass
  php_value mbstring.encoding_translation   0
</IfModule>
 
# PHP 5、Apache 1 および 2
<IfModule mod_php5.c>
  php_value magic_quotes_gpc                0
  php_value register_globals                0
  php_value session.auto_start              0
  php_value mbstring.http_input             pass
  php_value mbstring.http_output            pass
  php_value mbstring.encoding_translation   0
</IfModule>
 
# mod_expires を有効にする必要があります。
<IfModule mod_expires.c>
  # 有効期限を有効にします。
 ExpiresActive On
 
  # アクセス (A) 後 2 週間、すべてのファイルをキャッシュします。
 ExpiresDefault A1209600
 
  # 動的に生成されたページはキャッシュしません。
 ExpiresByType text/html A1
</IfModule>
 
# さまざまな書き換えルール。
<IfModule mod_rewrite.c>
  RewriteEngine on
 
  # 'www.' プレフィックスを付けても付けなくてもサイトにアクセスできる場合、次の設定のいずれかを
  # 使用し、'www.' プレフィックスを付けて、または 'www.' プレフィックスを付けないで
  # 適切な URL にユーザーをリダイレクトできます。オプションを 1 つだけ選択してください。
  # 'www.' プレフィックスを付けてサイトにアクセスするようにすべてのユーザーを
  # リダイレクトする場合は (http://example.com/... は http://www.example.com/... に
 # リダイレクトされます)、次の行を調整し、コメントを解除します。
 # RewriteCond %{HTTP_HOST} ^example.com$ [NC]
  # RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
  # 'www.' プレフィックスを付けないでサイトにアクセスするようにすべてのユーザーを
  # リダイレクトする場合は (http://www.example.com/... は http://example.com/... に
 # リダイレクトされます)、次の行のコメントを解除し、調整します。
 # RewriteCond %{HTTP_HOST} ^www.example.com$ [NC]
  # RewriteRule ^(.*)$ http://example.com/$1 [L,R=301]
 
  # サブディレクトリまたは VirtualDocumentRoot で Application を使用しており、書き換えルールが
  # 正しく機能していない場合は、RewriteBase を変更します。
 # たとえば、サイトが http://example.com/application にある場合、次の行のコメントを
  # 解除し、変更します。
 # RewriteBase /application
  # http://example.com/ の VirtualDocumentRoot でサイトが実行されている場合、
  # 次の行のコメントを解除します。
 # RewriteBase /
 
  # 'x' という形式の URL を 'index.php?q=x' という形式に書き換えます。
 RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
</IfModule>
 
# $Id:.htaccess,v 1.90.2.1 2008/07/08 09:33:14 goba Exp $

サンプル アプリケーションの web.config

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

    <configSections>
        <sectionGroup name="system.webServer">
            <sectionGroup name="rewrite">
                <section name="rewriteMaps" overrideModeDefault="Allow" />
                <section name="rules" overrideModeDefault="Allow" />
            </sectionGroup>
        </sectionGroup>
    </configSections>

    <system.webServer>
        <security>
            <!--  This section should be uncommented after
            installation to secure the installation. -->
            <!--
            <requestFiltering>
                <denyUrlSequences>
                    <add sequence="engine" />
                    <add sequence="inc" />
                    <add sequence="info" />
                    <add sequence="module" />
                    <add sequence="profile" />
                    <add sequence="po" />
                    <add sequence="sh" />
                    <add sequence="theme" />
                    <add sequence="tpl(\.php" />
                    <add sequence="Root" />
                    <add sequence="Tag" />
                    <add sequence="Template" />
                    <add sequence="Repository" />
                    <add sequence="code-style" />
                </denyUrlSequences>
                <fileExtensions>
                    <add fileExtension=".sql" allowed="false" />
                    <add fileExtension=".pl" allowed="false" />
                </fileExtensions>
            </requestFiltering>
            -->
        </security>
        <directoryBrowse enabled="true" />
        <caching>
            <profiles>
                <add extension=".php" policy="DisableCache" kernelCachePolicy="DisableCache" />
                <add extension=".html" policy="CacheForTimePeriod" kernelCachePolicy="CacheForTimePeriod" duration="14:00:00:00" />
            </profiles>
        </caching>
        <rewrite>
            <rules>
                <rule name="block favicon" stopProcessing="true">
                    <match url="favicon\.ico" />
                    <action type="CustomResponse" statusCode="404" subStatusCode="1" 
                        statusReason="The requested file favicon.ico was not found" 
                        statusDescription="The requested file favicon.ico was not found" />
                </rule>
                <rule name="Imported Rule 1" stopProcessing="true">
                    <match url="^(.*)$" ignoreCase="false" />
                    <conditions>
                        <add input="{HTTP_HOST}" pattern="^example\.com$" />
                    </conditions>
                    
                    <action type="Redirect" redirectType="Permanent" url="http://www.example.com/{R:1}" />
                </rule>
                <rule name="Imported Rule 2" stopProcessing="true">
                    <match url="^(.*)$" ignoreCase="false" />
                    <conditions>
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
                        <add input="{URL}" pattern="^/favicon.ico$" ignoreCase="false" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="index.php?q={R:1}" appendQueryString="true" />
                </rule>
            </rules>
        </rewrite>
        <defaultDocument>
            <files>
                <remove value="index.php" />
                <add value="index.php" />
            </files>
        </defaultDocument>

        <!-- HTTP Errors section should only be enabled if the "Error Pages"
        feature has been delegated as "Read/Write" at the Web Server level.
           <httpErrors>
               <remove statusCode="404" subStatusCode="-1" />
               <error statusCode="404" prefixLanguageFilePath="" path="/index.php" responseMode="ExecuteURL" />
           </httpErrors>
        -->

    </system.webServer>
</configuration>