.htaccess の設定、書き方のサンプル

更新:

.htaccess の設定方法と記述例。
対象 : Apache 2.4/2.2、Linux Fedora, RedHat, CentOS

.htaccess について

.htaccess はサイトへのアクセス制御や各種設定ができる。 Apache の httpd.conf でも設定できるが、httpd.conf に補足する形で使用できる。 ただし、Apache の httpd.conf にて .htaccess の使用が許可されてないと利用できない。 .htaccess は各ディレクトリに設置し、設置したディレクトリ以下でその設定が有効になる。 .htaccess を複数設置した場合、上位のディレクトリに設置したものから順に認識され、設定が反映される。 詳しくはApacheのサイト Apache チュートリアル: .htaccess ファイル に書かれている。

<Directory>、<Location> ディレクティブ

<Directory> はディレクトリ、<Location> はURLを指定できるディレクティブ(セクション)である。

記述例としていろいろなブログ等に書かれているが、これらのディレクティブは基本的に httpd.conf で使用し、.htaccess では使えない。 VPS等root権限が使えるサーバーを除く多くのレンタルサーバーでは .htaccess しか編集できず、そこに <Directory> や <Location> を書いても Internal Server Error になるので注意する。

アクセスの許可と拒否

Require ディレクティブ(Apache 2.4以上)

.htaccess でアクセスを制限する方法として従来は allow や deny が使われたが、Apache 2.4系から仕組みが変わり、 Require を使うことになった。

レンタルサーバーでもApache 2.4系が導入され、Require に書き換えなければいけないと思っている人もいるようだが、そうとも限らない。 Apache モジュール mod_access_compat が有効な場合、allow や deny も使える。 私が使用しているエックスサーバーやコアサーバーはApache 2.4系だが、どちらも使えるようになっている。 ただ、今後使用できなくなる可能性もあるので記述例を書いておく。

サイト運営で最もよくあるのは、一部のIPアドレスやホスト名のアクセスを拒否する方法で、例えば以下のように書く。

<RequireAll>
Require all granted
Require not ip 210.168.
Require not host .kanagawa.ocn.ne.jp
</RequireAll>

とりあえずディレクティブの動作を確認しようと <RequireAll> 内に何も書かないと Internal Server Error になる場合がある。

まず、Require all granted で全てのアクセスを許可する。 その後、Require not の後にアクセスを拒否したいIPアドレスやホスト名を書く。 それらはフルで書いても部分一致で書いても良い。

以下の例は上記の例と同じ効果がある。

<RequireAll>
Require all granted
    <RequireNone>
    Require ip 210.168.
    Require host .kanagawa.ocn.ne.jp
    </RequireNone>
</RequireAll>

<RequireNone> ディレクティブを使う場合は not を書かない。 拒否するIPアドレスやホスト名が多い場合は、この書き方が良いかもしれない。

また、Require の記述例として <Directory> や <Location> ディレクティブ を併用した例もブログ等で見られるが、上述のように .htaccess しか使えないレンタルサーバーでは <Directory> や <Location> は使えず、エラーになるので注意する。 レンタルサーバーで使う場合は、基本的に <RequireAll> や <RequireNone> だけで記述する。

SetEnvIf を使って特定の環境変数のアクセスを拒否する場合は以下のように書く。

SetEnvIf Referer "example\.com" deny_ref

<RequireAll>
Require all granted
Require not env deny_ref
</RequireAll>

私はあまり使うことがないが、特定のIPアドレスやホスト名だけアクセスを許可する場合は以下のように書く。

<RequireAll>
Require all denied
Require ip 210.168.
Require host .kanagawa.ocn.ne.jp
</RequireAll>

Require all denied で全てのアクセスを拒否する。 その後、Require の後にアクセスを許可したいIPアドレスやホスト名を書く。

allow、deny ディレクティブ

.htaccess における allow や deny は、Order allow,deny の書き方や順序について分かりにくいという話をよく聞くが、特定のIPアドレスやホスト名のアクセスを拒否するだけなら deny from だけ書いても動作する。 その記法が正しいのかどうか分からないが、さくら、エックスサーバー、コアサーバーではそれで動作している。

特定のIPアドレスからのアクセスを拒否したい場合は以下のように書く。

deny from 219.111.65.200

以下の場合は、210.108. で始まるIPアドレスがすべて対象となる。

deny from 210.108.

幅広いIPアドレス帯域を設定するには、ネットマスク(CIDR)を利用して一括してIP帯域を指定できる。 この例は 210.108.0.0 ~ 210.108.255.255 までを指定したことになる。

deny from 210.108.0.0/16

すべてのアクセスを拒否する場合は all と書く。

deny from all

ホスト名(サブドメイン)も省略して制限できる。 この例では a.example.com や b.example.com など .example.com に一致するものがすべて対象となる。

deny from .example.com

特定のIPアドレス(例では219.111.65.200)からのアクセスのみ許可したい場合は以下のように書く。

allow from 219.111.65.200

以下のようにドメイン名でも制限できる。

allow from adsl.example.com

allow と deny は優先順位を指定でき、先に書いた方が優先される。 以下の例だと allow が先になる。

Order allow,deny

よく記述例で見かけるように一通り書くと以下のようになる。

Order allow,deny
allow from all
deny from 210.108.

allow from all で全てのアクセスを許可した後、deny from で拒否したいIPアドレスやホスト名を記述する。 この逆は以下のようになる。

Order deny,allow
deny from all
allow from 210.108.

deny from all で全てのアクセスを拒否した後、allow from で許可したいIPアドレスやホスト名を記述する。

<Limit> ディレクティブを使い、GETとPOSTの処理だけに適用することもできる。

<Limit GET POST>
Order deny,allow
deny from all
</Limit>

SetEnvIf - 環境変数

.htaccess は環境変数を用いて制御できる。 環境変数はUser-Agent、Referer、Accept-Language、Remote_Host、Remote_Addr、Server_Addr、Request_Method、Request_Protocol、Request_URIなど。 以下の例は、User-Agent に iPhone や Android が含まれる場合、特定のURLへ飛ばす。

RewriteEngine On
RewriteBase /
SetEnvIf User-Agent "iPhone" UA=sp
SetEnvIf User-Agent "Android" UA=sp
RewriteCond %{REQUEST_URI} !^/sp.*
RewriteCond %{ENV:UA} ^sp$
RewriteRule ^(.*)$ /sp/ [R,L]

また、Referer(参照元の情報)を取得して外部のサイトからのファイル(画像やページ)の参照を禁止することもできる。
詳しくは SetEnvIf Refererの設定 に書いた。

リダイレクトなど

RewriteRule

Redirect や RedirectMatch など .htaccess にてリダイレクトする方法はいろいろあるが、RewriteRule は柔軟に対応でき使いやすい。 RewriteRule はリダイレクトだけでなく、URLを書き換えたりいろいろできる。 話が長くなるので、RewriteRuleについては RewriteRule に書いた。

Redirect

testディレクトリ以下のアクセスをsampleディレクトリにする場合、以下のように書く。

Redirect permanent /test/ http://www.example.com/sample/

testディレクトリ以下のディレクトリ構造を維持できるので、test/a.html、test/b.html があった場合、sample/a.html、sample/b.html にリダイレクトできる。 http://www.example.com/test/ から http://www.example.com/sample/ にリダイレクト(同じサイト内で別のディレクトリにリダイレクト)でも、http://www.example-test.net/test/ から http://www.example.com/sample/ にリダイレクト(別のサイトにリダイレクト)でもOK。

また、以下のようにリダイレクト先のURLに元のディレクトリ名の文字列(ここでは/test/)が含まれると永久ループしてエラーになる。

Redirect permanent /test/ http://www.example.com/sample/test/

以下の場合、testディレクトリ以下のアクセスをsample/test.htmlにリダイレクトできる。

Redirect permanent /test/ http://www.example.com/sample/test.html

以下のようなリダイレクトもできる。

Redirect permanent /test/abc.html http://www.example.com/sample/abc.php

RedirectMatch

正規表現を使ってリダイレクトできる。 以下の場合、URLの最後が.htmlでアクセスされたものを.htmlの部分だけ.phpに置き換えてアクセスさせる。 今までHTMLでページを作っていたものをPHPに変更して、ファイル名はそのまま(拡張子だけ変更)というような場合などに使う。

RedirectMatch (.*)\.html$ http://www.example.com$1.php

以下の場合、windows_という文字を含み、URLの最後が.phpなURLを http://www.example.com/internet/pc/ にリダイレクトする。

RedirectMatch (.*)windows_(.*)\.php$ http://www.example.com/internet/pc/

以下の場合、websiteという文字を含むURLを http://www.example.com/memo/website/ にリダイレクトする。

RedirectMatch (.*)website/(.*)$ http://www.example.com/memo/website/$2

例えば「http://www.example.com/internet/website/任意のファイル名」を「http://www.example.com/memo/website/任意のファイル名」にリダイレクトしたい場合、このRedirectMatchを http://www.example.com/internet/ 以下に置く。 ディレクトリを変更した場合などに利用できる。

CGIで使いそうなもの

CGI関連のディレクティブは、昨今レンタルサーバーにてデフォルトで設定されているものが多く、あまり使わなくなったが、一応記述例を書いておく。

Options

以下の例はCGIの実行を許可し、Indexファイル(index.htmlなど)がない場合にディレクトリ構造を表示しないようになる。 CGIが使えるレンタルサーバーでは最初からこの設定が行われているので基本的に記述する必要はない。

Options +ExecCGI -Indexes

Options は + でその設定を追加、- で削除になる。 + や - が付いたものと付けないものを混在させるのはApacheのドキュメントによると正しくないらしい。 Options には以下の種類がある。

  • ExecCGI・・・CGIの実行許可
  • Includes・・・SSIの実行許可
  • IncludesNOEXEC・・・SSIの#execと、#include以外許可
  • Indexes・・・Indexファイルがない場合に、ディレクトリ構造を表示
  • All・・・MultiViews以外のすべてのオプション有効
  • None・・・すべてのオプション無効
  • FollowSymLinks・・・シンボリックリンク有効
  • MultiViews・・・MultiViewsを許可
  • SymLinksIfOwnerMatch・・・ファイル所有者のみシンボリックリンクを許可

詳しくはApacheのサイト Options ディレクティブ に書かれている。

AddType

初期設定にないMIMEタイプ(Content-Type、ファイルの種類)を追加する場合は AddType を使う。

AddType text/html .cgi
#AddType application/x-httpd-cgi .cgi
AddType application/x-httpd-php .php
AddType application/xml .rdf

ファイルの種類によってはMIMEタイプを設定しないと正常にダウンロードできなかったり、ブラウザで認識されない場合がある。 CGIプログラムの場合、ヘッダで Content-Type を指定して出力すれば基本的に記述する必要はない。

CGI、SSIを利用する

CGIが最初から利用できるサーバーでは特に設定は必要ないが、.htaccessで指定しないと動作しない場合は以下のように記述する。

Options +ExecCGI
AddHandler cgi-script .cgi .pl

上の例では拡張子が .cgi と .pl のファイルがCGIアプリケーションとして動作するようになる。 拡張子はスペースで区切って複数指定できる。 以下はSSIの場合(拡張子shtmlというファイルでSSIを利用する場合)。

Options +Includes
AddType text/html .shtml
AddHandler server-parsed .shtml
AddOutputFilter INCLUDES .shtml

レンタルサーバーの設定によるが、Perl、Ruby、Pythonで書いたCGIプログラムを動かすには、拡張子を .cgi にして中身をそれぞれの言語で書き、パーミッションを設定すれば良い。 パーミッションは 755 とは限らず、レンタルサーバーによって異なる場合がある。 拡張子が .cgi では面白くないという人は、.pl、.rb、.pyでCGIプログラムが動くように以下のように設定する。

AddHandler cgi-script .pl .rb .py

その他

DirectoryIndex

http://www.example.com/test/ のようにディレクトリ名だけを指定してアクセスすると index.html や index.cgi などが表示される。 もとは httpd.conf に記載されているが、この最初に表示されるページの優先順位を変更するには DirectoryIndex を使う。

DirectoryIndex index.php index.html index.cgi top.html

先頭に書いたものほど優先され、該当のファイルがなければ順次後ろのファイルを探して表示する。 また、DirectoryIndexが指定されていない場合や、DirectoryIndexで指定したファイルがすべてなかった場合、ディレクトリ構造の一覧が見えてしまう場合がある。 それを防ぐには以下のように .ht を記述する。

DirectoryIndex index.php index.html index.htm index.cgi .ht

ErrorDocument - エラーページを表示

ページが見つからなかったり、サーバーエラーが発生した場合など、何らかのエラーが発生した場合に表示するページを指定できる。 以下のようにHTTPステータスコードを指定して記述する。

ErrorDocument 403 /data/html/403.html
ErrorDocument 404 /data/html/404.html
ErrorDocument 500 /data/html/500.html

また、URL(ドメイン)を指定して自サイトまたは他サイトへ飛ばすこともできる。

ErrorDocument 403 http://www.example.com/data/html/403.html

ページにアクセスした際、パスで書いた場合はエラーページに転送されてURLは元のページのまま、URLを書いた場合はエラーページに転送されURLも転送先のものに変わる。

.htpasswd - パスワードによるアクセス制限(Basic認証)

Basic認証はユーザ名とパスワードを入力するウィンドウを表示させて、ページにアクセスできる人を制限できる。 .htaccessと.htpasswdの2つのファイルが必要で、まず.htaccessに以下のように書く。

AuthUserFile /htdocs/sample/.htpasswd

AuthName "Secret Area"
AuthType Basic

require valid-user

<Files ~ "^\.ht">
   deny from all
</Files>

AuthUserFileには.htpasswdを置いたディレクトリのパスを書く。 次に.htpasswdに以下のように書く。

sample:ABwOg1D2JDxIQ

これはユーザ名:sample、パスワード:test の場合の例。 .htpasswdには「ユーザ名:cryptしたパスワード」という書式で書く。 ABwOg1D2JDxIQ は test を AB という種(salt)をもとに crypt した結果の文字列。

メンテナンス中の処理

以下はサイトのメンテナンスを行う場合のサンプル。 ディレクトリをリネームする場合、http://www.example.com/abc/ を http://www.example.com/abc2/ などにしておき、トップの.htaccessでエラーページを指定する。

ErrorDocument 403 /info/maintenance/index.html
ErrorDocument 404 /info/maintenance/index.html
ErrorDocument 500 /info/maintenance/index.html

リダイレクトする(リネームしたくない)場合、http://www.example.com/abc/ の.htaccessに以下のように書く。

Redirect permanent /abc/ http://www.example.com/info/maintenance/

以下のようにパスに同じ文字列(例ではabc)を含むとループになるので注意。

Redirect permanent /abc/ http://www.example.com/info/abc/

Redirectはディレクトリの階層構造がそのまま反映され http://www.example.com/info/maintenance/ 以下全てのアクセスがエラーになるので、http://www.example.com/info/maintenance/ の.htaccessに 以下を書く。

ErrorDocument 403 /info/maintenance/index.html
ErrorDocument 404 /info/maintenance/index.html
ErrorDocument 500 /info/maintenance/index.html
このエントリーをはてなブックマークに追加