サポート » 使い方全般 » 「nonce」の使い方について

  • お世話になります。
    「nonce」の使い方について教えて頂けませんでしょうか。

    現在HTMLにこのようなボタンがあり、クリックするとuser metaの「’allow’」が更新されるPHPがあります。(JSは割愛)

    ▼HTML
    <button type="button" data-target_id="1">このIDを許可</button>

    ▼PHP

    function my_enqueue_scripts_ajax() {
      $handle = 'my_script';  	
      $jsFile = 'path/to/myscript.js';
      wp_register_script($handle, $jsFile, ['jquery']);
      $action= 'my_ajax_action';
      wp_localize_script($handle, 'MY_AJAX', [
        'api'    => admin_url( 'admin-ajax.php' ),
        'action' => $action,
        'nonce'  => wp_create_nonce( $action ),
      ]);
      wp_enqueue_script($handle);	
    }
    add_action( 'wp_enqueue_scripts', 'my_enqueue_scripts_ajax' );	
    
    add_action( 'wp_ajax_my_ajax_action', 'my_ajax_event' );
    add_action( 'wp_ajax_nopriv_my_ajax_action', 'my_ajax_event' );
    function my_ajax_event() {
      $action = 'my_ajax_action';
      if( check_ajax_referer($action, 'nonce', false) ) {	
    		$u_id = get_current_user_id();
    		$target_id = esc_html( $_POST['target_id'] );
    		update_user_meta( $u_id, 'allow', $target_id );
    	}
      die();
    }

    で質問なのですが、ボタンが複数あったときは、どのようにしたらよろしいのでしょうか?

    つまりHTMLがこのようになっているときです。

    ▼HTML

    <button type="button" data-target_id="1">このIDを許可</button>
    <button type="button" data-target_id="2">このIDを許可</button>

    このようなときは、ボタン1つごとに別々のnonceを生成しなければならないのでしょうか?(もしそうであれば、それはどのように?)

    それとも「nonce」は上のPHPだけあれば、ボタンがいくつあっても適切なセキュリティで処理されるのでしょうか?

    「nonce」というのがよくわかっておらず以上のような疑問に至っておりますが、自力で解決できません。

    どなたかお助け頂けますと幸いでございます。
    宜しくお願い申し上げます。

15件の返信を表示中 - 1 - 15件目 (全40件中)
  • こんにちは

    アクション毎に nonce を別々にするのが望ましいです。
    https://wpdocs.osdn.jp/関数リファレンス/wp_create_nonce

    この場合は、同じアクション(my_ajax_action)のようなので、分ける必要はないと思います。

    こんにちは。どうもありがとうございます。お詳しそうな方にそう言って頂けて助かります。これからの方針が少し固まりました。

    ところで「アクション毎」とのことですが、たとえば質問にあるような『user metaの「’allow’」が更新されるもの』だけでなく、『user metaの「’add’」が更新されるもの』というのもがあった場合はいかがでしょうか?

    これを僕は同じアクションとして扱おうとしているんですが、どうですか?

    たとえばボタンのデータ属性を次のように分けまして、

    『user metaの「’allow’」が更新されるもの』
    <button type="button" data-target_id="1" data-action_name="allow">このIDを許可</button>

    『user metaの「’add’」が更新されるもの』
    <button type="button" data-target_id="1" data-action_name="add">このIDを追加</button>

    そしてPHPでは下記のように、同じアクション(my_ajax_action)の中で、JSから受け取ったデータ属性に応じて「’allow’」と「’add’」を分岐させる。という方法です。

    add_action( 'wp_ajax_my_ajax_action', 'my_ajax_event' );
    add_action( 'wp_ajax_nopriv_my_ajax_action', 'my_ajax_event' );
    function my_ajax_event() {
      $action = 'my_ajax_action';
      if( check_ajax_referer($action, 'nonce', false) ) {	
        $u_id = get_current_user_id();
        $target_id = esc_html( $_POST['target_id'] );
        $action_name = esc_html( $_POST['action_name'] );
        if( $action_name == 'allow' ){
          update_user_meta( $u_id, 'allow', $target_id );
        }
        if( $action_name == 'add' ){
          update_user_meta( $u_id, 'add', $target_id );
        }
    
      }
      die();
    }

    いかが思われますか?
    このような場合ではアクションは分けた方がいいでしょうか?

    もしよろしければ引き続き、「どのような場合にアクションを分けるべきか」について踏み込んだご意見を頂けますと嬉しいです。

    ここでいうアクションは my_ajax_action なので同じアクションです。

    Nonce に関しては下記ページをご覧ください。
    https://wpdocs.osdn.jp/WordPress_Nonce

    あ、それはわかるんですが、同じアクションなのは僕が同じアクションとして処理してるだけじゃないですか?

    ボタンのデータ属性(allowとadd)でアクションを分けてもよかったのですが(my_ajax_action_allowとmy_ajax_action_addのように)、それを同じアクション(my_ajax_action)の中で処理してるというだけですよね。

    でもこれらが同じでいいなら、「どういうときに同じじゃダメなのか」がわからないんです。

    だって、全てのAjaxにおいてHTMLにデータ属性をつければ、そのデータ属性を使って先の返信にあるように

    if( $action_name == 'allow' ){}
    if( $action_name == 'add' ){}
    if( $action_name == 'other' ){}

    などと条件分岐して、全て同じmy_ajax_actionの中で処理できるじゃないですか?

    でも実際には同じアクション(my_ajax_action)の中でまとめず、アクションは分ける必要があるんですよね?

    その「どういうときに同じじゃダメなのか」を知りたいということなんです。

    どういうアクションで、どういう処理を行うかは、私が判断することではないと思いますが・・・。
    一つのアクションで問題ないとは思いますけど・・・。

    でも実際には同じアクション(my_ajax_action)の中でまとめず、アクションは分ける必要があるんですよね?

    分ける必要があるというのは、どうしてでしょうか?どちらの情報でしょうか?

    でも、nonceを複数発行しているサイトってあるじゃないですか?

    そしてそのサイトはつまり、複数のアクションを使い分けているということですよね。(なぜなら「アクション毎に nonce を別々にするのが望ましいから」です。)

    ではそれらのサイトはなぜ、複数のアクションに分けているんでしょう?
    同じアクションで条件分岐すればいいだけなのに。
    そう思いませんでしょうか?

    あと、どのテーマでも記事へのコメントのnonceは、コメントごとに別々に発行されているみたいに見られます。これらが別々のアクションになっているのっておかしくないですか?全てコメントするだけのアクションなのに、nonceが別になっているんですよね。

    Ajax の出力で分けているのではないでしょうか?
    具体的なプラグインを上げてもらえますか?

    あーっと…、すみません、ややこしくなるので、この疑問だけでいいです。

    同じアクションの中で条件分岐すればいいだけなのに、nonceを複数作る(アクションを複数作る)ケースがあるのはなぜか?

    これについて、どう思われますでしょうか?

    うーん、アクションをどう分けるかは、分かりません。
    投稿 ID やユーザー、フォーム、コメント、処理内容などで分けるといいかと思います。

    • この返信は5 ヶ月、 1 週前に  ishitaka さんが編集しました。

    なるほど。分けるべき適切な根拠がわかるまで、いろいろな事例で経験を積んでみたいと思います。とりあえずケースバイケースということですよね。笑
    すみません夜分に。どうもありがとうございました!!

    こんにちは

    最初に書かれているソースで気になったので・・・

    wp_create_nonceの引数がリテラルな固定文字列な nonce は意味がないのではないでしょうか。
    リクエストの target_id を改ざんして異なる ID に対して allow にしようとする攻撃を防ぐことができません。

    ishitaka さんが貼ってくれた codex には以下のように書かれていて、WordPress の nonce はそれが目的だと理解しています。

    もし誰かが URL を書き換えて ID=456 の投稿をゴミ箱へ入れようとすると、nonce が無効になるので、その企みは失敗します

    ですので、(私の理解だと)今回の場合はwp_create_noncecheck_ajax_refererの第一引数は$action . $idのように id を含む必要があり、nonce はボタン毎に生成する必要があると思います。

    私は WordPress での ajax の書き方に詳しくないのでどう書いたらいいか分かりませんが、複数の nonce を出力して Post 時に対象の nonce を data に含める、みたいな書き方じゃないでしょうか。

    でも、ID と nonce のペアが分かるような形式でソースに出てしまうと nonce ごと改ざんすることが可能になる気がするのですが、そこまで気にするかどうかは機能の特性にもよる気がします。

    @munyagu さん

    wp_create_nonce は、nonce を現在の時刻、$action 引数、現在のユーザー ID に基づいて生成します。アクション名をできるだけユニークにしたほうがいいと思いますが、button 毎に生成する必要はないと思いますが、どうでしょうか?

    • この返信は5 ヶ月、 1 週前に  ishitaka さんが編集しました。
    • この返信は5 ヶ月、 1 週前に  ishitaka さんが編集しました。

    @munyagu さん

    おっと、失礼しました。
    アクション名に ID が入っていると思っていました。

    アクション名: my_ajax_action+ID+動作(allow,add,other)

    この場合の動作までは必要ないと思った次第です。できるだけユニークするほうがいいので入れたほうがベターだと思います。

    @ishitaka さん

    アクション名に処理対象の ID を入れるとなると、今回はボタンごとに処理対象の ID が異なるので、ボタン毎に nonce が必要なんじゃなかろうか・・・ということです

15件の返信を表示中 - 1 - 15件目 (全40件中)
  • このトピックに返信するにはログインが必要です。