Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
2013/09/29
WordBench京都
Cherry Pie Web 川井昌彦
.htaccessによるリダイレクト徹底解説
~無限ループで100倍返しされないために~
2
自己紹介
●川井昌彦(かわいまさひこ)@sakuragi_kei
 東京の制作会社で24年間勤めた後、
 京都府舞鶴市に帰郷してフリーランスで活動中
 実は、DTPのほうが経験が長いです
  (このスライドも InDesign で作っています)
 実は、MovableTypeのほうが経験が長いです
 小桜インコ・シロハラインコ・黒い柴犬のパパ
 Cherry Pie Web http://www.cherrypieweb.com
3
本日の予定
1.	 リダイレクトとは
2.	 基本のリダイレクト
3.	 mod_rewrite によるリダイレクト
4.	 WordPressが書き出すリダイレクトを見てみよう
5.	 まとめ
・・・実際は、こんなふうに
     キレイにはまとまっていません・・・
4
リダイレクトとは
ウェブページへの訪問者を、自動的に他のページへ移動させること
ウェブページなどの移動の通知に使われることが多い
郵便局の自動転送というより、
 ドアに、「引っ越しました」の
  張り紙があるようなイメージ
5
たとえば・・・
1.	 ウェブページのファイル名が変わった
2.	 ウェブページを他のディレクトリに移動した
3.	 ドメイン名が変わった
4.	 一部のページに、ユーザーがアクセスできないようにする
5.	 index.htmlあり/なし、wwwあり/なしなどを統一する
                        ・・・など
6
リダイレクトの指定方法
1.	 htmlの、metaタグ
2.	 JavaScriptの、location.href=、または、location.replace()
3.	 PHPなどで、HTTPヘッダーを出力
 上記3つは、
  アクセスされるすべてのページに指定しておかなければならない
4.	 Webサーバーの設定
	 httpd.conf または、.htaccess に指定する
	 ページへのアクセス自体を制御できる
7
.htaccess の有効範囲
.htaccess が置かれたディレクトリから下位すべてのディレクトリに有効
ただし、下位ディレクトリにも
.htaccess が置かれていた場合、
 競合する設定は、
  下位のものが有効
example.com
.htaccess
index.html
test1.html
sub1
.htaccess
index.html
subtest1.html
sub2
index.html
subtest2.html
8
では、さっそくサンプルを
いくつか
9
ウェブページのファイル名を変えた
Redirect:リダイレクトを示す
Permanent:301リダイレクト(恒久的なリダイレクト)
/test1.html:古いファイル名
 ドキュメントルートからのパスを指定する
http://example.com/test2.html:新しいファイル名
 絶対URLを指定する
Redirect Permanent /test1.html http://example.com/test2.html
10
ドキュメントルートとは?
ブラウザからドメイン名でアクセスしたときのサーバー上の位置
(例)/var/user_name/public_html/ ←ここが、/(ルート)になる
ファイルのドキュメントルートからのパスは、
 URLからドメイン名をとったものと、だいたい同じ
サブドメインやマルチドメインの時は、
 サブディレクトリがルートになることもある
http://example.com/test1.html
11
絶対URLとは?
http://www.example.com/test2.html
 のようにドメイン名を省略しないURL
※相対パスで指定できない!
※同じドメイン内でも省略できない!
12
301リダイレクトとは?
完全に引っ越したとき(元に戻る予定はない)
302リダイレクトとは?
メンテナンスなどで、一時的に移動しているとき
13
301リダイレクトにするメリット
301リダイレクトと指定した場合、検索エンジンは、
元のページから新しいページに移動したことを、
検索結果に反映してくれるようになる。
また、元のページの評価を、
 新しいページに引き継いでくれる。
ただし、
 「はてブ」や「いいね」は
  自動で引き継がれたり
        しません。
PageRankの
引き継ぎでーす
14
ディレクトリを移動した
oldディレクトリ以下へのアクセスはすべて、
 newディレクトリ以下へリダイレクト
Redirect permanent は、Redirect 301 と書いても良い
【注意!】
リダイレクト元とリダイレクト先のドメインが同じで、
         ディレクトリが親子関係だとエラーになる
                         (後述します)
Redirect 301 /old/ http://example.com/new/
15
ドメインを変えた
全てのアクセスを、http://example.com へリダイレクト
【注意!】
リダイレクト元とリダイレクト先のドメインが同じだとエラーになる
                         (後述します)
Redirect 301 / http://example.com/
16
負荷軽減のため画像ファイルだけを
他のサーバーから読み込む
RedirectMatch:パターンマッチを使用したリダイレクト
301:301リダイレクト
(.*¥.(jpg|gif|png))$:元の画像ファイル名
http://another-img.com$1:読み込む画像ファイル名
RedirectMatch 301 (.*.(jpg|gif|png))$ http://another-img.com$1
17
正規表現の例
(.*¥.(jpg|gif|png))$ http://another-img.com$1
. :全ての文字
*:0回以上の繰り返し
( ):ブロックを指定
¥.:ドット
 「. 」は、正規表現ではすべての文字を示す
  ドットそのものを表すときは ¥をつける(エスケープする)
(jpg|gif|png):jpg,gif,pngのいずれか
$:行の終わり
$1:1つめのブロック
18
リダイレクトは、無限ループにならないように注意!
たとえば、こんな設定で
リダイレクト元とリダイレクト先のドメインが同じだったら・・・
つまり・・・
http://amachan.com へのすべてのアクセスを、
http://amachan.com/je/ へリダイレクトしたいとしたら・・・
Redirect 301 / http://amachan.com/je/
19
http://amachan.com/index.php へのアクセスがどうなるか?
WordPressでよくある、
サブディレクトリにWordPressをインストールした場合のリダイレクトは、
この書き方ではできない!
  http://amachan.com/index.php
→ http://amachan.com/je/index.php
→ http://amachan.com/je/je/index.php
→ http://amachan.com/je/je/je/index.php
→ http://amachan.com/je/je/je/je/index.php
→ http://amachan.com/je/je/je/je/je/index.php
                   以下、無限ループ!!!!
20
これまでの書き方の問題点
1.	 同じドメインで階層の違うディレクトリにリダイレクトをしようとすると、
無限ループが起きやすい
2.	 リダイレクト先はドメインを省略できないので、使いまわしができない
例えば、テスト環境から本番環境に持っていく時に、
リダイレクト先のドメイン名をすべて書き直さないといけない
ぐるぐる
回るよー
21
mod_rewrite をつかったリダイレクト
mod_rewriteは、
 Apache Webサーバーのモジュールで、
  サーバー内でURLの書き換えを行う
ブラウザの種類、リファラ、時間などの
あらゆる適用条件が指定できるなど
とても柔軟な指定が可能
22
mod_rewite はインストールしてないと使えない
サーバーに対して権限があるなら、追加でインストールすればよいが、
レンタルサーバーなどでは自分でインストールはできない。
安いレンタルサーバでは、インストールされていないところもある。
レンタルサーバーでは、「よくある質問」のコーナーに、
「mod_rewrite は使えますか?」という質問が掲載されていることが多い。
PHPが使えるなら、phpinfo() で調べる
23
mod_rewrite がインストールされていなくても
エラーが出ないようにする
IfModule で囲んで、mod_rewriteがインストールされていないときは
実行されないようにしておく
IfModule mod_rewrite.c
・・・・
/IfModule
24
     では、さっそくサンプル
(注)以下、IfModule mod_rewrite.c は省略します。
25
ウェブページのファイル名を変えた
/test1.html → /test2.html
RewriteEngine on:リダイレクトの記述の開始
RewriteRule:リダイレクトのルール
RewriteEngine on
RewriteRule ^test1.html$ test2.html
26
RewriteRule
・リダイレクト元の正規表現パターン
^test1¥.html$:
 .htaccess と同じディレクトリにある test1.html に適用される
 .htaccess のあるディレクトリからの相対パス
mod_rewrite を使うときは、リダイレクト元のパスには / は不要
(リクエストされたURLから、.htaccess のあるパスまで削除されて、評価される)
RewriteEngine on
RewriteRule ^test1.html$ test2.html
27
 ^は行頭を表す
  → 同じディレクトリ以外には適用されない ×test/test1.html
 $は行末を表す
  → test1.htm には適用されない
 ¥.は、ドットを表す
  → .(ドット)はすべての文字という意味なので、
   ドット自体を表したいときは、¥をつける(エスケープする)
RewriteEngine on
RewriteRule ^test1.html$ test2.html
28
 と書くと、test/test1.html など、下位のディレクトリにも適用される
 と書くと、test1.htm、test1.html の両方に適用される
^test1.htm$ と書くと、test1.html には適用されない
RewriteEngine on
RewriteRule test1.html$ test2.html
RewriteEngine on
RewriteRule ^test1.htm test2.html
29
・リダイレクト先の文字列
test2.html:
 .htaccess と同じディレクトリにある test2.html にリダイレクト
 .htaccess のあるディレクトリからの相対パス、絶対パス、絶対URL
RewriteEngine on
RewriteRule ^test1.html$ test2.html
30
ディレクトリを移動した
oldディレクトリ以下へのアクセスを、newディレクトリにリダイレクト
^old/(.*)$:old以下へのすべてのアクセス
( ):ブロック
$1:( )ブロックの1つ目
RewriteEngine on
RewriteRule ^old/(.*)$ /new/$1
31
ドメインを変えた
すべてのリクエストを、http://newserver.com/ にリダイレクトする
^(.*)$:アクセスされたすべてのパターンにマッチ
( ):ブロック
$1:( )ブロックの1つ目
【注意!】リダイレクト元とリダイレクト先のドメインが同じだとエラーになる
RewriteEngine on
RewriteRule ^(.*)$ http://newserver.com/$1
32
負荷軽減のため画像ファイルだけを
他のサーバーから読み込む
RewriteEngine on
RewriteRule ^(.*).(jpg|gif|png)$ http://newserver.com/$1.$2
33
トップページのURLを
「/index.html」ではなく「/」に統一
URLの正規化と言われるものの一つで、アクセス解析で重要
ほかにも、wwwあり/なし の統一などもできる
RewriteEngine on
RewriteRule ^index.html$ http://www.example.com/
34
リダイレクトは、あちこちの .htaccess に書かない!
.htaccess を下位のディレクトリにおくことがあるが、
リダイレクトをあちこちに書くと混乱の元!
・	mod_rewrite を使った場合、
リダイレクト元、リダイレクト先のパスは、
.htaccess が置かれたパスが基準となるので、ややこしい
・	下位のルールが適用されると、上位のルールが適用されなくなる
35
(例1).htaccess をルートディレクトリだけにおいたとき
/old/test1.html → /test2.html
リダイレクト先は、.htaccess が置かれているルートディレクトリになる
RewriteEngine on
RewriteRule ^old/test1.html$ test2.html
36
(例2).htaccess をoldディレクトリだけにおいたとき
/old/test1.html → /old/test2.html
リダイレクト先は、.htaccess が置かれているoldディレクトリになる
RewriteEngine on
RewriteRule test1.html$ test2.html
37
(例3).htaccess を複数のディレクトリにおいたときー1
・ルートディレクトリ・・・(1)
・oldディレクトリ・・・(2)
/old/test2.html → /old/test3.html   (2)のルールのみ適用
/old/test1.html → 何も適用されない!  (2)のルールのみ適用
RewriteEngine on
RewriteRule ^old/test1.html$ test2.html
RewriteEngine on
RewriteRule ^test2.html$ test3.html
38
リダイレクト指定が下位のディレクトリにもある場合
1.	 リクエストされたURLの最も下位の階層のリダイレクトを適用
2.	 リダイレクトされた結果のURLで、
改めて最も下位の階層のリダイレクトを適用
 上位の設定を下位の設定で
   上書きや追加をする
      わけではない!
39
先ほどの例を見直すと・・・
・ルートディレクトリ・・・(1)
・oldディレクトリ・・・(2)
/old/test1.html がリクエストされたので、
oldディレクトリにあるリダイレクトの設定(2)が適用される。
ここに test1.html に対する設定がないので、ここで終わり
RewriteEngine on
RewriteRule ^old/test1.html$ test2.html
RewriteEngine on
RewriteRule ^test2.html$ test3.html
40
(例4).htaccess を複数のディレクトリにおいたときー2
・ルートディレクトリ・・・(1)
・oldディレクトリ・・・(2)
/test1.html → /test2.html
/old/test2.html → /test1.html → /test2.html
  (2)のルールでリダイレクトした結果、上位のURLになったので、
改めて上位のルール(1)のリダイレクトが適用される
RewriteEngine on
RewriteRule ^test1.html$ test2.html
RewriteEngine on
RewriteRule ^test2.html$ /test1.html
41
複数のRewriteRule
/test1.html → /test2.html → /new/test2.html
RewriteRuleは、複数書ける
どれかにマッチすればリダイレクトされるので、もちろん、これも有効
/test2.html → /new/test2.html
RewriteEngine on
RewriteRule ^test1.html$ test2.html
RewriteRule ^test2.html$ new/test2.html
42
RewriteBase
RewriteBase:リダイレクト後のパスのベース
 /test1.html → /old/test2.html となる
 /old/test1.html には適用されない
※RewriteBaseは、リダイレクト元には関係ない
RewriteEngine on
RewriteBase /old
RewriteRule ^test1.html$ test2.html
43
/old/test1.html に適用させるには、
リダイレクト元にディレクトリ指定が必要
RewriteEngine on
RewriteBase /old
RewriteRule ^old/test1.html$ test2.html
44
※Rewritebaseは、リダイレクト後の指定が相対パスの時のみ有効
 / をつけると絶対パスになるので RewriteBase は無効になる
/test1.html → /old/test2.html
/test1.html → /test2.html (RewriteBase無視)
RewriteEngine on
RewriteBase /old
RewriteRule ^test1.html$ test2.html
RewriteEngine on
RewriteBase /old
RewriteRule ^test1.html$ /test2.html
45
特定ディレクトリへのアクセス拒否
oldディレクトリ以下へのアクセスを拒否する
[F]:403 Forbidden(アクセス権限がないエラー)を返す
RewriteRule のリダイレクト先を「-」とすると、リダイレクトしない
RewriteEngine on
RewriteRule ^old/.* - [F]
46
ieからアクセスされたときだけ
違うファイルにリダイレクトする
RewriteCond:条件にマッチした時、RewriteRuleを適用する
%{HTTP_USER_AGENT}:環境変数(ユーザーエージェントを得る)
[NC]:大文字小文字を区別しない
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} MSIE [NC]
RewriteRule ^test1.html$ test2.html
47
使える環境変数
HTTP_USER_AGENT / HTTP_REFERER / HTTP_COOKIE / HTTP_FORWARDED
HTTP_HOST / HTTP_PROXY_CONNECTION / HTTP_ACCEPT
REMOTE_ADDR / REMOTE_HOST / REMOTE_USER / REMOTE_IDENT
REQUEST_METHOD / SCRIPT_FILENAME / PATH_INFO / QUERY_STRING
AUTH_TYPE
DOCUMENT_ROOT / SERVER_ADMIN / SERVER_NAME / SERVER_ADDR
SERVER_PORT / SERVER_PROTOCOL / SERVER_SOFTWARE
TIME_YEAR / TIME_MON / TIME_DAY / TIME_HOUR / TIME_MIN
TIME_SEC / TIME_WDAY / TIME
API_VERSION / THE_REQUEST / REQUEST_URI / REQUEST_FILENAME
IS_SUBREQ
48
RewriteCondを使った例
・2013年12月28日~2014年1月3日までの間だけリダイレクトする
RewriteCondを複数書いたときは、AND条件(すべて満たしたとき)
比較に使えるのは、  = ( = みたいなのは使えない)
比較演算子の後にスペースを入れないこと
RewriteEngine on
RewriteCond %{TIME_YEAR}%{TIME_MON}%{TIME_DAY} 20131227
RewriteCond %{TIME_YEAR}%{TIME_MON}%{TIME_DAY} 20140104
RewriteRule ^test1.html$ test2.html
49
・iPhoneまたはiPadからアクセスされたときだけリダイレクトする
次の条件とOR条件(いずれかを満たすとき)にしたいときは、
[OR]フラグをつける
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} iPhone [NC,OR]
RewriteCond %{HTTP_USER_AGENT} iPod [NC]
RewriteRule ^test1.html$ /test2.html
50
・特定のIPアドレスからのアクセスを拒否
IPアドレスが 123.456.789.012 または 012.345.678.901 から
アクセスされたら、403 Forbidden を返す
[F]:403 Forbidden(アクセス権限がないエラー)を返す
RewriteRule のリダイレクト先を「-」とすると、リダイレクトしない
RewriteEngine on
RewriteCond %{REMOTE_ADDR} ^123.456.789.012$ [OR]
RewriteCond %{REMOTE_ADDR} ^012.345.678.901$
RewriteRule ^.*$ - [F]
51
・特定のIPアドレス以外からのアクセスを拒否
IPアドレスが 012.345.678.901 以外から
アクセスされたら、403 Forbidden を返す
!:否定(条件を満たさないときに有効)
RewriteEngine on
RewriteCond %{REMOTE_ADDR} !^012.345.678.901$
RewriteRule ^.*$ - [F]
52
・SSLによる通信を強制する
http;// でアクセスされても、
https:// に強制的に切り替えることで、SSLを有効にする
%{HTTPS} off:httpsでないアクセス
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
53
WordPressでパーマリンク設定した時
に作成されるリダイレクト
IfModule mod_rewrite.c
RewriteEngine On
RewriteBase /wordpress/
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wordpress/index.php [L]
/IfModule
54
RewriteBaseで指定されているのは、
WordPressがインストールされたディレクトリ
RewriteRule のリダイレクト先を「-」とすると、リダイレクトしない
[L]:これ以降のルールを適用しない
ルートディレクトリのindex.phpにアクセスされたら
リダイレクトしないで終了
 → 次のルールによる無限ループが避けられる!
RewriteBase /wordpress/
RewriteRule ^index.php$ - [L]
55
-f:ファイルが実在すると true
-d:ディレクトリが実在すると true
アクセスされたファイルまたはディレクトリが実在する場合
 → そのままそのファイルを表示
アクセスされたファイルもディレクトリも実在しない場合
 → WordPressの index.php にリダイレクト
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wordpress/index.php [L]
56
Rフラグ
[R]:302リダイレクト
 [R=301] とすれば、301リダイレクトになる
※Rフラグをつけないと、サーバー内部でリダイレクトが行われるので、
 アクセスした側はリダイレクトしたことがわからない!
→ ブラウザのアドレスバーはリダイレクト前のURLのまま!
RewriteEngine on
RewriteRule ^test1.html$ test2.html [R]
57
※Rフラグをつけると、
 アクセスした側が新しいパス(URL)にアクセスし直したように見える
→ ブラウザのアドレスバーがリダイレクト先のURLに変わる
SEOを考慮するなら、 [ R=301 ] は必須!
PageRankの
引き継ぎでーす
58
リダイレクトのまとめ
・	301リダイレクトと302リダイレクトを使い分けよう
(メンテナンス等以外は、301リダイレクトを使う)
・	無限ループに注意
・	リダイレクトの記述は、できるだけ1か所にまとめよう
・	正規表現を勉強しよう
59
  ご清聴ありがとうございました。

More Related Content

.htaccessによるリダイレクト徹底解説