こんにちは、株式会社オンラインの金沢です。
プラグイン開発の練習中に、管理画面の独自のフォームに「nonce」なるものを使用しましたので、その忘備録です。
「nonce」は、POST送信されたデータが本物であるかどうかを認証するために使用します。WordPressのテンプレート関数「wp_nonce_field」で、inputタグをhiddenで生成し、送信されたデータを処理する前に「wp_verify_nonce」か「check_admin_referer」で認証を行います。以下、これらの関数の説明をさせて頂きます。
wp_nonce_field( $action, $name, $referer, $echo )
この関数が生成するinputタグの属性は、引数「$action」と「$name」により決められます。「$action」を暗号化された値がタグの「value」属性に使われ、「$name」が、そのままタグの「name」属性となります。これにより送信される「$_POST[ $name ]」が、「nonce」と言われております。この「$action」と「$name」をユニークなものにしていないと、他の送信データの処理に引っかかりエラーとなったり、セキュリティに脆弱性が生じたりしてしまいます。
「$referer」は、「true」か「false」で指定し、上記のinputタグに加えてもう一つhiddenタイプのinputタグを生成するかどうかを設定します。ここで生成するタグの中身は、フォームを生成するページのURL情報が含まれています。従って、同一のページから送られてきたPOSTデータかどうかをチェックする場合に使えます。初期値は「true」で、「referer」のタグも生成します。
最後の引数「$echo」は、出力か取得かの選択です。初期値は「true」の出力です。
wp_verify_nonce( $nonce, $action )
この関数は、引数に入力した「nonce」が有効かどうかを確認します。引数「$action」は、「wp_nonce_field」に使用した「$action」と同じ文字列を用います。「$nonce」は、「wp_nonce_field」の「$name」から「$POST_[ $name ]」を入力しましょう。戻り値は、認証に失敗すれば「false」、「nonce」が12時間以内のもので認証に成功すれば「1」、「nonce」が12~24時間前に生成されたもので認証OKなら「2」となります。
check_admin_referer( $action, $query_arg )
こちらは「nonce」だけではなく「referer」もチェックしてくれる関数です。「$action」は上述の「$action」と同じです。「$query_arg」は、「$_REQUEST」の中のどのパラメータが「nonce」かを聞かれているもので、「wp_nonce_field」で使用した「$name」をそのまま入れれば大丈夫です。
こちらの関数で認証に失敗すると、そこで処理がストップしてしまいます。PHPの「die」関数により、「本当に実行していいですか ? もう一度お試しください。」という文字が出力され、処理が停止します。
認証成功時は「true」を戻してくれます。
あとがき
私が、「nonce」を使用してエラーとなってしまった例は、「wp_nonce_field」の「name」を初期値の「_wpnonce」のままにしてしまったことが原因でした。作成したフォームは正常に動いたのですが、ブログや固定ページなどの別のフォームが動かなくなってしまいました。保存しようとしても、「本当に実行していいですか ? もう一度お試しください。」と表示されるだけになってしまったときはどうしたものかと思いました。「nonce」は、プラグイン開発に至るまでの試練の一つですね。
よろしければ、ご指摘・ご質問などのコメントをお願いします。
金沢