サポート » 使い方全般 » 存在しない動的URLを指定した時にレスポンスコードの404を返す方法

8件の返信を表示中 - 1 - 8件目 (全8件中)
  • モデレーター jim912

    (@jim912)

    ご質問の正当なパラメータにでたらめな値を指定された時への対応方法として考えられるものを提示します。

    $wp->query_vars には、URLからWordPressが理解可能なパラメータを抜き出した値が入ります。

    array(2) {
      ["p"]=>
      string(12) "ecrdqxqugwzb"
      ["paged"]=>
      string(1) "5"
    }

    これに対し、$wp_query->query_vars には、パラメータとして正当な形式かどうかをチェックした後の値が入ります。

    array(61) {
      ["p"]=>
      int(0)
      ["paged"]=>
      int(5)
      ["error"]=>
      string(0) ""
      ["m"]=>
      string(0) ""
    
    ※ 長いので途中省略
    
    }

    よって、この2値を比較し、$wp->query_vars の各値が、$wp_query->query_vars の値と異なっていた場合に、status_header 関数で 404 を返すようにすれば、不正な形式での指定には対応可能です。

    function check_invalid_query_vars( $wp ) {
    	global $wp_query;
    	if ( ! is_admin() && $wp_query->is_main_query() ) {
    		foreach ( $wp->query_vars as $key => $val ) {
    			$wp_query_var = (string)$wp_query->get( $key );
    			if ( $wp_query_var != $val ) {
    				// $wp_query->set_404();
    				status_header( 404 );
    				break;
    			}
    		}
    	}
    }
    add_action( 'wp', 'check_invalid_query_vars' );

    これでレスポンスコードは404となりますが、ページの表示は行われてしまいます。もし、表示についても変更したい場合は、上記コードの

    // $wp_query->set_404();

    のコメントアウトを外してください。

    トピック投稿者 toshichan

    (@toshichan)

    jim912様、ご回答ありがとうございます。

    以下のように記述したところ、タブに「ページが見つかりませんでした。」と表示されたため、404が返ってきているようですが、404エラーのページに画面が遷移しません。
    「// $wp_query->set_404()」のコメントは外しています。
    どこが間違っているのでしょうか?
    申し訳ありませんが、よろしくお願いします。

    修正箇所
    ・function check_invalid_query_vars( $wp )は修正なし。
    ・function status_header( $code ) の最終行にadd_action( ‘wp’, ‘check_invalid_query_vars’ );を追加した。

    function status_header( $code ) {
            $description = get_status_header_desc( $code );
            if ( empty( $description ) )
                    return;
            $protocol = $_SERVER['SERVER_PROTOCOL'];
            if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
                    $protocol = 'HTTP/1.0';
            $status_header = "$protocol $code $description";
    
            if ( function_exists( 'apply_filters' ) )
                    $status_header = apply_filters( 'status_header', $status_header, $code, $description, $protocol );
            @header( $status_header, true, $code );
            add_action( 'wp', 'check_invalid_query_vars' );
    
    }
    function check_invalid_query_vars( $wp ) {
            global $wp_query;
            if ( ! is_admin() && $wp_query->is_main_query() ) {
                    foreach ( $wp->query_vars as $key => $val ) {
                            $wp_query_var = (string)$wp_query->get( $key );
                            if ( $wp_query_var != $val ){
                                    $wp_query->set_404();
                                    status_header( 404 );
                                    break;
                            }
                    }
            }
    }
    モデレーター jim912

    (@jim912)

    お使いのテーマは、なんでしょう?
    404.phpがなく、index.php と共用していたりすると、不正な指定を無視して、記事を拾ってきてしまうため、表示がなされてしまったりします。

    もしくは、プラグインなどとの競合などの可能姓もあります。

    ちなみに、記述は functions.php に提示したコードをそのまま記述すれば良く、status_header関数を修正する必要はありません。
    ※ WordPressをバージョンアップする際に戻ってしまいますよね?

    トピック投稿者 toshichan

    (@toshichan)

    jim912様、ありがとうございます。

    使っているテーマはglassです。・・・かなり古い。
    このテーマの中身を調べたら404.phpがありませんでした。
    おそらくこれが原因だろうと思います。
    ちなみにfunctions.php に教えて頂いたコードをそのまま貼り付けると画面が真っ白になってしまいました。

    この対策を行うきっかけは、Googleのウェブマスターツールで「タイトルタグ」「重複するメタデータ(descriptions)」に重複を指摘され、その都度.htaccessを使って正しいURLに転送していましたが、いたちごっこになってしまいました。
    ちょうど1週間おきに新しい重複を指摘され、.htacessを修正する感じです。

    http://www.example.com/wordpress/?p=ecrdqxqugwzb&paged=12

            ↓・・.htaccessで転送する。

    http://www.example.com/wordpress/?paged=12

    そこで思い切ってディレクトリ名をwordpressからblogに変更し、個別記事とカテゴリだけ301転送しましたが、転送先のディレクトリでも再度同じようなことになったら嫌だったので、先に手を打っておこうと思い、対策方法を質問しました。

    > ※ WordPressをバージョンアップする際に戻ってしまいますよね?
    なんとなく、そんな気がしていました。

    404エラー画面が表示されなくてもレスポンスコードの404が返れば目的は達成できますが、バージョンアップでfunctions.phpが元に戻ってしまうのは嫌ですね。
    悩みどころです。

    モデレーター jim912

    (@jim912)

    このテーマの中身を調べたら404.phpがありませんでした。
    おそらくこれが原因だろうと思います。

    では、テーマの index.php の

    <?php if (have_posts()) : ?>

    <?php if (have_posts()&&!is_404()) : ?>

    に直してみてください。

    ちなみにfunctions.php に教えて頂いたコードをそのまま貼り付けると画面が真っ白になってしまいました。

    wp-includes/functions.php に記述していませんか?
    テーマファイルの functions.php の
    ?>
    の直前に記述してみてください。

    トピック投稿者 toshichan

    (@toshichan)

    jim912様、ありがとうございました。

    > wp-includes/functions.php に記述していませんか?
    そのとおりでした。
    「status_header」をキーワードにしてgrepをかけたら、wp-includes/functions.phpがヒットしたので、てきっりこれかなと・・・。

    ご指摘いただいたようにテーマ内のindex.phpとfunctions.phpを修正したら動作しました。

    感謝感激です。

    ところで、便乗で質問です。

    この対策により、ほとんどの存在しないURLは404扱いに出来ました。
    しかし、実際にGoogleにインデックスされた存在しないURL(以下のURLの/wordpress/以下は実データです)を使ってテストすると、一部のURLで404に出来ないものがありました。

    例えば、
    ① p → p__
    ② cat → cat9  :本来はcat=9だと推測される。
    ③ m → m201106  :本来はm=201106だと推測される。
    ④ p → p1469  :本来はp=14699だと推測される。

    特に②~④はパラメータのイコール(=)が抜けてしまったようなURLです。

    http://www.example.com/wordpress/?m201106&paged2&paged=16

    http://www.example.com/wordpress/?p__&paged=10

    http://www.example.com/wordpress/?cat9&paged=6

    http://www.example.com/wordpress/?p1469&paged=13

    このようにパラメータ文字自体が存在しない文字列に変わってしまった場合は対策出来るのでしょうか?

    よろしくお願いします。

    モデレーター jim912

    (@jim912)

    これらを404とすることは、何が有効なパラメータで、何を無効とするか、無限の組み合わせを判定させる必要があり、基本的には困難です。
    ※ Facebookからのリンクをクリックした際に付く、fb_action_ids なんかもその1つでもありますよね。

    その代わり、固定ページや、個別投稿ページの head タグで出力されているURL正規化タグを出す方法が考えられます。

    <link rel='canonical' href='http://example.com/?p=1' />

    存在しないパラメータの場合は、そのパラメータが無視された状態でのページを表示するため、URL正規化タグで、本来在るべきURLを出力することで、存在しないパラメータでの表示を重複コンテンツと認識させ、インデックスさせないようにする方法です。

    トピック投稿者 toshichan

    (@toshichan)

    > これらを404とすることは、何が有効なパラメータで、何を無効とするか、無限の組み合わせ
    > を判定させる必要があり、基本的には困難です。
    了解しました。
    このタイプの異常なURLはほんの一部だけなので、このまま放置とします。

    何度も丁寧にご説明いただき、ありがとうございました。

8件の返信を表示中 - 1 - 8件目 (全8件中)
  • トピック「存在しない動的URLを指定した時にレスポンスコードの404を返す方法」には新たに返信することはできません。