ブログ

  • 【PHP】header関数とErrorDocument 404

    WEBサイトの制作において、エラーページの表示は重要です。

    基本的には、404エラー等は、.htaccess に記述する、ErrorDocument により制御できます。

    たとえば、次のように .htaccessに記述します。

    ErrorDocument 404 /error/404.html

    基本中の基本ですね。ちなみに、遷移先のパスは相対パスにしないと404ステータスにならない場合があります。つまり、絶対パス(URL)ではなく、相対パスにするということです。

    他方で、PHPのスクリプトによっても、404ステータスを発行することが可能です。

    PHPの場合には、header関数により、次のように記述します。

    header("HTTP/1.0 404 Not Found");

    http://jp1.php.net/manual/ja/function.header.php

    上記の記述により、ブラウザに404ステータスを送出できます。

    しかし、ここで大きな問題に直面します。

    どういう問題かというと、PHPのheader関数により、404ステータスを送出した場合には、自動的には、/error/404.html には遷移しないのです。

    これは、少々、面倒なことになります。

    というのも、header(“HTTP/1.0 404 Not Found”); の後に、header(“Location: http://~”); とロケーションを付け足してやるとエラーページに遷移はするものの、ヘッダーステータスが302に変更され、404ではなくなってしまうからです。

    この対応策ですが、/error/404.htmlをfile_get_contents ()関数などで、読み込んで、出力するのも一つの方法となります。

    header("HTTP/1.0 404 Not Found");
    
    $error_page = file_get_contents('../error/404.html')
    
    echo $error_page;
    
    exit;

    こうすることで、一応、ErrorDocumentの場合とPHPの場合で同一の404ファイルを出力することができます。
    また、file_get_contentsの代わりに、require_once等でエラーファイルを読み込む方法も考えられます。

    なお、取得するファイルのパスは、サイトの構造により修正が必要です。

    もっとも、404ファイルを動的に作成している場合には、上手くいかない場合もあるので注意が必要です。

    この件で、他に良い方法があれば、コメントください。

    以上です。

  • 【書評】CakePHP2 実践入門 (WEB+DB PRESS plus)

    ■ 書評対象:CakePHP2 実践入門 (WEB+DB PRESS plus)

    ■ 良い点

    ・ わかりやすく丁寧な説明
    ・ サンプルアプリ(タスク管理システム)を作りながら学べる
    ・ インストール等環境構築に詳しい
    ・ セキュリティ対策の解説有り
    ・ チートシート(プロパティ・メソッド集)が巻末に有り

    ■ 悪い点

    ・ 本文とコード等(図表)のページ位置関係が悪い
    ・ 白黒の本のため重要箇所がわかりづらい
    ・ レイアウト(ヘッダー・フッター)の扱いは無し

    ■ 総評

    全体的に良書です。大きく分けて、前半の基礎部分と、後半の応用部分に分かれます。

    前半部分は、安藤氏が一貫して解説しており、とても分かりやすくなっています。

    コントローラー・モデル・ビューのそれぞれについて、サンプルコードを交え構文を解説し、各章のまとめで、タスク管理アプリを段階的に構築していきます。

    当該サンプルアプリは、簡易的なものですが、DBのテーブルのアソーシエイション(JOIN)などまで含めての解説です。実用にも応用可能なレベルです。

    後半部分は、CakePHPの応用となっており、各章ごとに執筆者が異なっています。

    もっとも、各章ごとに、きちんとトピックが決まっており、前半同様、内容の濃い解説となっています。

    セキュリティの対策についても、CakePHPの観点から、XSSなど代表的なリスク対策について検討がなされています。

    また、公開準備にあわせたデプロイ等にも触れられていて、なかなかの参考になりました。

    さらに、PHPUnitをつかったテストの自動化などにも触れられています。ここら辺は、自分のレベルではついていけなかったですが、マスターできれば、より効率的な開発ができそうです。

    巻末には、CakePHPの重要なプロパティ・メソッド集としてチートシートが収録されていて、開発時の参考に随所で活躍しそうです。

    全体的にレベルは高いですが、前半部分は初心者にも易しい解説になっているのでCakePHPの入門としてオススメです。 前半部分だけでも読むとCakePHPについてだいぶ自信が持てるようになると思います。

  • 【http】404ページへアクセスがある原因【error】

    WEBサイトにおいて、存在しないページにアクセスがあると、404ステータスコードを返すのが一般的な仕様となっています。

    そして、404ステータスの場合に、WEBサイト側で用意した、404ページへリダイレクトさせることもできます。

     ErrorDocument 404 http://example.com/error/404.html

    このような設定を、.htaccess に記述すると、リンク切れなどでページが存在しない場合、404.html に遷移します。

    つまり、通常、リンク切れなどがなければ、404.htmlへのアクセスは無いはずなのですが、頻繁にアクセスが有るケースがあります。

    それは、検索エンジンのロボット(クローラー)が、robots.txt にアクセスする場合です。

    robots.txt とは、検索エンジンのロボットに対して、クロールの可否を知らせるものです。

    ロボットがrobots.txtにアクセスしてきた時、このrobots.txt  を設置していないと、サーバーは、存在しないページにアクセスしてきたものとして、ロボットに対し404ページへ移動するよう処理します。

    つまり、リンク切れがない場合でも、robots.txt  を設置しておらず、かつ、404ページへの遷移の設定をしていると、robots.txt のため、404ページへのアクセスがログに記録されてしまうわけです。

    この対策としては、robots.txt を設置すればよいのですが、サイトへのアクセスを左右するものだけに、慎重に行うべきだと考えます。

    なお、robots.txt は、サイトに必須のものではないので、「設置しない」というのも一つの選択肢です。

  • 【JavaScript】メールフォームのスパム対策【PHP】

    WEBサイトを運営していてメールフォームを設置すると、遅かれ早かれスパム投稿に悩まされるようになります。

    メールフォームのスパム対策には、画像認証を付けるなど、いくつかの方法があるのですが、より簡単に実装できるのが、JavaScriptによるフォーム値の上書き方法です。

    どういう方法かというと、フォームにhiddenタグを埋め込みトークンを値にセットします。このトークン値をPOSTされる際に、JavaScriptにより書き換えてしまうというものです。

    以下、具体例です。

    (略)
    <input id="token" type="hidden" name="token" value="some_token">
    
    <input onclick="change_token();" type="submit" value="送信">
    
    </form>

    上記コードには、hiddenタグに、トークンとして、some_tokenがセットされています。

    この状態で送信すると、原則的には、スパムは、token=some_token を送信してきます。

    この原則を、JavaScriptの関数により変更します。つまり、送信ボタンが押されたときに、トークンの値を書き換えて、その書き換え後の値でなければ、スクリプト側でスパムとして送信を弾くようにします。

    JavaScriptは次のようになります。(外部ファイルにする場合)

    function change_token(){
        var token = 10 * 10;
        document.getElementById('token').value = token;
    }

    ここでは、例として、トークンの値を10 * 10 の100 としています。送信されたスクリプト側(PHPなど)で、入力チェックをするのですが、このtokenの値が100でなければスパムによる送信と判断するわけです。

    スパムは、JavaScriptを実行しないことを利用したものですが、何も対策をしないよりは効果があると思います。

    以上です。

  • PHPを使いサーバー監視をする方法

    WEBサイトを運営する場合、気になるのがサーバーの死活状況です。

    サーバーがダウンしてユーザーに迷惑をかけてしまっては一大事です。
    ただ、そうかといって、ずっとサーバーの負荷状況を目視で確認するのも非現実的な話です。

    そこで、PHPスクリプトを組み、サーバーを監視します。

    ■ 監視方法の概要は次のようになります。

    ・ 甲サーバーを監視するため、外部乙サーバーからPHPスクリプトにより死活状況監視
    ・ 乙サーバーのPHPスクリプトは、CRONの仕組みにより定期的に実行
    ・ 甲サーバーにおいてエラーが生じていたらメールにて通知

    それでは、実際のPHPスクリプトです。

    <?php
    
    /**** サーバー設定 ****/
    
    mb_language('ja');
    mb_internal_encoding('UTF-8');
    
    /**** サーバー情報初期化 ****/
    
    $server_ip   = '20*.*72.*4.5*';
    $server_name = 'example.com';
    $page_url    = 'http://example.com/sample_page.html';
    $mail_to     = 'your-mail';
    $mail_from   = 'your-mail';
    
    /**** チェック開始 ****/
    
    $result = '';
    
    //■ 1.pingチェック
    $ping_command = 'ping -c 3 -w 5 '. $server_ip;
    
    if (strstr(`$ping_command`, '100% packet loss')) {
    
        $result .= '1.pingが停止しています。'."\n";
    }
    
    //■ 2.socketチェック
    $socket = @fsockopen($server_name, '80', $errno, $errstr, 5);
    
    if ($socket === FALSE) {
    
        $result .= '2.socketを接続できません。'.$errno.$errstr."\n";
    }
    
    //■ 3.webアクセスチェック
    if (!$res = @file_get_contents($page_url)) {
    
        $result .= '3.pageを取得できません。'."\n";
    }
    
    /**** メール送信 ****/
    
    //停止していればをメール送信
    if ($result != '') {
    
        $subject = 'エラー!停止しています。('. $server_name .')';
        mb_send_mail($mail_to, $subject, $result, 'From: '. $mail_from);
    
    } else {
    
        $subject = '正常に稼動してます。('. $server_name .')';
        mb_send_mail($mail_to, $subject, '正常稼動中', 'From: '. $mail_from);
    }

    それでは、少し補足です。

    ■ 1では、pingを送信し正常かを確認しています。もし、送信したパケットが100%失われていれば、エラーとします。

    通常だとpingは次のようなメッセージを生成します。

    PING 20*.*72.*6.*0 (20*.*72.*6.*0) 56(84) bytes of data. 
    64 bytes from 20*.*72.*6.*0: icmp_seq=1 ttl=64 time=2.71 ms 
    64 bytes from 20*.*72.*6.*0: icmp_seq=2 ttl=64 time=0.146 ms 
    64 bytes from 20*.*72.*6.*0: icmp_seq=3 ttl=64 time=0.143 ms
     --- 20*.*72.*6.*0 ping statistics --- 
    3 packets transmitted, 3 received, 0% packet loss, 
    time 2002ms rtt min/avg/max/mdev = 0.143/1.000/2.713/1.211 ms

    つまり、‘ping -c 3 -w 5 ‘ のコマンドを実行すると、-cオプションの回数だけ、-wオプションの秒数を限度にパケットを送信するのですが、そのパケットのロスの割合を出力します。このロスの割合が、100%ならば、エラーと判断するわけです。

    なお、pingのコマンドは、バッククオート`コマンド`で実行しています。(@マークのキーで出る記号です。)

    ■ 2では、サーバーにソケット接続して、正常に接続できるかを判断しています。

    @fsockopen($server_name, ’80’, $errno, $errstr, 5);の部分ですが、これは、指定したサーバーの80ポート(httpポート)にソケット接続するための関数を実行しています。

    引数に、$errno, $errstr などといきなり変数が出てきていますが、この変数に結果が参照で入るのでこのように指定しておきます。なお、5とあるのは、5秒を限度に接続を試みるというものです。

    ちなみに、先頭の@マークは、スクリプトエラーが生じた場合に、エラーメッセージを表示させないための記号です。

    ■ 3では、@file_get_contents($page_url)を実行しています。@マークは上と同様です。

    file_get_contentsで正常にファイルを取得できると、その結果を返しますが、失敗するとFALSEを返します。ここで、データベースを使用しているページを指定すると、データベースがきちんと動いているかも推定できます。

    最後は、エラー結果に基づき、場合分けしてメールを送信しています。エラーの処理だけ欲しい場合には、else以降は不要となります。

    以上です。

    (参考)
    http://blog.asial.co.jp/486
    http://www.seeds-std.co.jp/seedsblog/315.html
    http://www.okushin.co.jp/kodanuki_note/2012/09/php-2.html

    感謝です。