icon
Let's create! WordPressサイト制作とメンテ/エラー対応から、PHP/CSS/javascriptプログラミング、動画・音・イラスト等制作まで扱うコラム

【WordPress】メールに6文字ワンタイムパスワード送信する、2要素認証機能をつくってみた(プラグイン不使用)

更新: 2025/07/14 3274文字

今回は、WordPressのログイン時、『登録したメールアドレスに、6文字ワンタイムパスワード送信し、2要素認証を行う』というのをやってみます。もちろんメールアカウント情報が書いた紙を落としたりしたらダメなので、100%安全になるわけではないですけど、プラグイン不使用でセキュリティ面を少し強化できます。さっそく内容を確認していきましょう。

ワンタイムパスワード2要素認証ってプラグインでできるの?

もちろんWordPressだけあって、ワンタイムパスワード2要素認証もプラグインで対応できます。管理人が以前使ってみた『Two-Factor(WordPress.org作の公式プラグイン)』などでもできました。QRコード認証アプリなどもあります。

さっくり実装したい方はプラグインを使ってもokですが、ワンタイムパスワードだけだとシンプルなコードで実装できた(&処理の流れがわかりやすい)というわけで、次の段落で実際のコードを見てみましょう。

メールに6文字ワンタイムパスワードの2要素認証機能、コード例やポイント

下準備~フォーム表示用固定ページ

別のやり方もありますが、今回はワンタイムパスワード入力用ページに固定ページを用意しました。通常のログインフォームのあと、このページにリダイレクトし、ショートコード[2fa_form]を実行します。このショートコードがフォーム表示用です

今回はとりあえず、みたいな感じですけど、『wp-login.php以外から遷移してきた場合は元のページにリダイレクト』といった処理を入れてもokです。想定していない不正な遷移防止も大切です。

コード例(functions.php) コードのポイントなど

テーマディレクトリに置いて『get_template_part('/auth2form/core');』のように呼び出す形にしました。functions.phpが長くなりすぎるのもイヤなので。

プラグインのときよりはコード量がかなり少なくなり、1ファイルで済んで、コメントや改行込みで137行程度。処理の流れは以下の通りです。

  • ユーザー一覧に『メール認証使う?』列を追加
  • 『メール認証使う?』列に内容表示
  • ユーザーページ『メール認証使う?on/off』追加
  • 『メール認証使う?on/off』の保存処理
  • ログイン処理時、認証コードと期限をuser_metaに保存
  • コードをメール送信
  • ログイン情報破棄してコード入力ページへ
  • ショートコードで固定ページにフォーム表示
  • 6桁コード検証して、okならログイン&user_metaのコードと期限削除
  • 3分過ぎた場合はメッセージ表示して新しいコードを送信
  • コードが違う場合もメッセージ表示

ユーザーページ『メール認証使う?on/off』追加までは管理画面で使います。それより下は実際にログインを行ったときに行う処理です。

自作WordPress2要素認証機能の動作確認してみる 

管理画面内

ではさっそく動作確認してみますか。まずは管理画面。 個別のユーザーページ下部に、on/off表示。『show_user_profileは自分がログインしたとき』『edit_user_profileは、管理者が他ユーザー編集するとき』のような使い分けがあります。

ユーザー一覧にon/off表示。 投稿一覧の時と似ていますが『manage_users_column』『manage_users_custom_column』のフックでこういった機能をつくることができます。

ログイン時の動作確認

次はログイン時。 通常のログインフォーム。ここは今まで通りです。ユーザー名とパス入れて・・・

一時コード入力画面に。この段階ではまだログインせず、コードを入力します。メールボックスを見てみます。

メールにこんな感じで一時コードが届き、これを先ほどの画面で入力します。

一時コードでログインokでした。ここでは『wp_set_auth_cookie($id)』でログイン状態にしています。

コードが違う場合、期限切れの場合の動作

あとはログインできない状況も確認しておきます。 送信されたコードと違うコードを入れてしまった場合。メッセージ出力。

こちらはコード発行して3分以上たってしまった場合。メールボックスを確認します。

新しいコードが発行されていたのでokです。

データベース(user_metaテーブル)の確認

だいたい想定通りに動いていたけど、一応データベース(user_metaテーブル)内の値も確認。 コードが発行されたとき。idの1884,1885がコードと制限時間になっています。制限時間はUNIX時刻で、サーバーが64bitなので、たぶん2038年以降も大丈夫でしょう。

ログイン成功時、idの1884,1885(コードと制限時間)は削除されます。ログアウト時は何もしませんが、後ほどログインを試みたとき、再発行されます。

小ネタ~session_start()からデータベースuser_metaテーブル使用に変更した理由

上記の機能は『セッションにユーザーIDや発行した一時コードと使用期限を保存・入力内容と照らし合わせる』という方法でも可能でした。実施にセッションでも動くことを確認しましたが、とちゅうからデータベースのuser_metaテーブルにコードと使用期限を保存する形に変更しました。

というのも・・ このようにWPのセッションと競合して、サイトヘルスが『session_start() 関数の呼び出しによって PHP セッションが作成されました』のように警告をだすからです。特にsession_start()の位置が『initやwp_loadedといった早い段階でのフック』だと引っかかる模様。

だからといってwp_loadedより読み込み順が後ろのフックを使ってしまうと、こんどは管理画面の処理に間に合わなくなって、セッションが空になる(一時コードや期限がセッションに入らない)という形になり、判定ができなくなります。user_metaテーブルに保存した場合は、セッション関連の警告は出なくなります(restやブロックエディタとかでも使っていて、競合する形になるそうです。使っていない場合は、警告が出たからと言って酷い誤動作はおきませんでしたが)。

あとがき・まとめ

  • WordPressの一時コード2要素認証機能は、プラグイン実装のほか、自作できる
  • 一時コードや期限をuser_metaテーブルに保存し、通常のログインを一度解除してコードの判定を挟むことができる
  • セッションをinitやwp_loadedのフックで使った場合も機能するが、サイトヘルスが警告を出してくる

まとめると、こんなところでしょうか。コードをブラッシュアップする点はまだありますけど(固定ページに特定リファラじゃないと入れないようにするとか)、こういうのも自作できるのがわかったので、今後もいろいろ試してみたいです。


【カテゴリ】- WordPressファンクションetc
【タグ】-

関連記事