WordPressログイン通知を強化するプラグイン:Chatwork・Slack・メールの3系統に通知対応

WordPressではログイン成功・失敗の通知をしっかり管理することで、セキュリティの強化や管理ログの記録が可能になります。

本記事では、Chatwork / Slack / メールの3系統へ同時通知できる**ログイン通知プラグイン(Multi Login Notifier Extended)**の導入方法と全ソースコードを紹介します。


特徴

  • ログイン成功時に通知
  • ログイン失敗時にも通知
  • 通知先:
  • Chatwork(トークン+ルームID)
  • Slack(Webhook URL)
  • メール(任意の宛先)
  • 通知対象:
  • 指定ロールのユーザーのみ通知
  • 除外ユーザー名も指定可能
  • 管理画面で設定可能

ファイル構成

multi-login-notifier-extended/
├── multi-login-notifier-extended.php
└── includes/
    └── settings.php

multi-login-notifier-extended.php

<?php
/**
 * Plugin Name: Multi Login Notifier Extended
 * Description: Chatwork、Slack、メールにログイン成功・失敗通知を送信し、対象ロールや除外ユーザーも指定できるWordPressプラグイン
 * Version: 1.1.0
 * Author: Your Name
 */

defined('ABSPATH') || exit;

require_once plugin_dir_path(__FILE__) . 'includes/settings.php';

add_action('wp_login', 'mln_notify_on_login', 10, 2);
function mln_notify_on_login($user_login, $user) {
    $excluded_users = array_map('trim', explode(',', get_option('mln_excluded_users', '')));
    if (in_array($user_login, $excluded_users, true)) return;

    $allowed_roles = array_map('trim', explode(',', get_option('mln_allowed_roles', '')));
    if (!empty($allowed_roles)) {
        $matched = false;
        foreach ($user->roles as $role) {
            if (in_array($role, $allowed_roles, true)) {
                $matched = true;
                break;
            }
        }
        if (!$matched) return;
    }

    $site_name  = get_bloginfo('name');
    $site_url   = home_url();
    $ip_address = $_SERVER['REMOTE_ADDR'];
    $login_time = current_time('mysql');
    $roles      = implode(', ', $user->roles);

    $plain_message = <<<EOD
以下のユーザーがログインしました。

■ サイト: {$site_name}
■ URL: {$site_url}
■ ユーザー名: {$user_login}
■ 権限: {$roles}
■ ログイン日時: {$login_time}
■ IPアドレス: {$ip_address}
EOD;

    $slack_message = "ユーザーログイン通知\n"
                   . "• サイト: {$site_name} ({$site_url})\n"
                   . "• ユーザー名: `{$user_login}`\n"
                   . "• 権限: `{$roles}`\n"
                   . "• ログイン日時: `{$login_time}`\n"
                   . "• IPアドレス: `{$ip_address}`";

    $chatwork_message = "[info][title]ユーザーログイン通知[/title]"
                      . "■ サイト: {$site_name} ({$site_url})\n"
                      . "■ ユーザー名: {$user_login}\n"
                      . "■ 権限: {$roles}\n"
                      . "■ ログイン日時: {$login_time}\n"
                      . "■ IPアドレス: {$ip_address}"
                      . "[/info]";

    if (get_option('mln_chatwork_enabled') === '1') {
        $token = get_option('mln_chatwork_token');
        $room  = get_option('mln_chatwork_room_id');
        if ($token && $room) {
            wp_remote_post("https://api.chatwork.com/v2/rooms/{$room}/messages", [
                'headers' => ['X-ChatWorkToken' => $token],
                'body'    => ['body' => $chatwork_message],
            ]);
        }
    }

    if (get_option('mln_slack_enabled') === '1') {
        $webhook = get_option('mln_slack_webhook_url');
        if ($webhook) {
            wp_remote_post($webhook, [
                'headers' => ['Content-Type' => 'application/json'],
                'body'    => json_encode(['text' => $slack_message]),
            ]);
        }
    }

    if (get_option('mln_email_enabled') === '1') {
        $email_to = get_option('mln_email_to');
        if ($email_to) {
            $subject = "[{$site_name}] ログイン通知: {$user_login}";
            wp_mail($email_to, $subject, $plain_message);
        }
    }
}

add_action('wp_login_failed', 'mln_notify_failed_login');
function mln_notify_failed_login($username) {
    $site_name = get_bloginfo('name');
    $ip        = $_SERVER['REMOTE_ADDR'];
    $time      = current_time('mysql');
    $site_url  = home_url();

    $plain = <<<EOD
[ログイン失敗通知]

■ サイト: {$site_name}
■ ユーザー名: {$username}
■ 時間: {$time}
■ IPアドレス: {$ip}
EOD;

    $slack = "ログイン失敗通知\n"
           . "• サイト: {$site_name} ({$site_url})\n"
           . "• ユーザー名: `{$username}`\n"
           . "• 時間: `{$time}`\n"
           . "• IPアドレス: `{$ip}`";

    $chatwork = "[info][title]ログイン失敗通知[/title]"
              . "■ サイト: {$site_name} ({$site_url})\n"
              . "■ ユーザー名: {$username}\n"
              . "■ 時間: {$time}\n"
              . "■ IPアドレス: {$ip}"
              . "[/info]";

    if (get_option('mln_chatwork_enabled') === '1') {
        $token = get_option('mln_chatwork_token');
        $room  = get_option('mln_chatwork_room_id');
        if ($token && $room) {
            wp_remote_post("https://api.chatwork.com/v2/rooms/{$room}/messages", [
                'headers' => ['X-ChatWorkToken' => $token],
                'body'    => ['body' => $chatwork],
            ]);
        }
    }

    if (get_option('mln_slack_enabled') === '1') {
        $webhook = get_option('mln_slack_webhook_url');
        if ($webhook) {
            wp_remote_post($webhook, [
                'headers' => ['Content-Type' => 'application/json'],
                'body'    => json_encode(['text' => $slack]),
            ]);
        }
    }

    if (get_option('mln_email_enabled') === '1') {
        $to = get_option('mln_email_to');
        $subject = "[{$site_name}] ログイン失敗: {$username}";
        wp_mail($to, $subject, $plain);
    }
}

includes/settings.php

<?php
add_action('admin_menu', function () {
    add_menu_page(
        'ログイン通知設定',
        'ログイン通知',
        'manage_options',
        'multi-login-notifier',
        'mln_settings_page',
        'dashicons-admin-network',
        83
    );
});

add_action('admin_init', function () {
    $options = [
        'mln_chatwork_enabled', 'mln_chatwork_token', 'mln_chatwork_room_id',
        'mln_slack_enabled', 'mln_slack_webhook_url',
        'mln_email_enabled', 'mln_email_to',
        'mln_allowed_roles', 'mln_excluded_users'
    ];
    foreach ($options as $opt) {
        register_setting('mln_settings_group', $opt);
    }
});

function mln_settings_page() {
    ?>
    <div class="wrap">
        <h1>ログイン通知 設定</h1>
        <form method="post" action="options.php">
            <?php settings_fields('mln_settings_group'); ?>
            <table class="form-table">
                <tr><th colspan="2"><h2>Chatwork 通知</h2></th></tr>
                <tr><th>有効化</th><td><input type="checkbox" name="mln_chatwork_enabled" value="1" <?php checked(get_option('mln_chatwork_enabled'), '1'); ?> /></td></tr>
                <tr><th>APIトークン</th><td><input type="text" name="mln_chatwork_token" value="<?php echo esc_attr(get_option('mln_chatwork_token')); ?>" class="regular-text" /></td></tr>
                <tr><th>ルームID</th><td><input type="text" name="mln_chatwork_room_id" value="<?php echo esc_attr(get_option('mln_chatwork_room_id')); ?>" class="regular-text" /></td></tr>

                <tr><th colspan="2"><h2>Slack 通知</h2></th></tr>
                <tr><th>有効化</th><td><input type="checkbox" name="mln_slack_enabled" value="1" <?php checked(get_option('mln_slack_enabled'), '1'); ?> /></td></tr>
                <tr><th>Webhook URL</th><td><input type="text" name="mln_slack_webhook_url" value="<?php echo esc_attr(get_option('mln_slack_webhook_url')); ?>" class="regular-text" /></td></tr>

                <tr><th colspan="2"><h2>メール通知</h2></th></tr>
                <tr><th>有効化</th><td><input type="checkbox" name="mln_email_enabled" value="1" <?php checked(get_option('mln_email_enabled'), '1'); ?> /></td></tr>
                <tr><th>送信先メールアドレス</th><td><input type="email" name="mln_email_to" value="<?php echo esc_attr(get_option('mln_email_to')); ?>" class="regular-text" /></td></tr>

                <tr><th colspan="2"><h2>通知対象の制御</h2></th></tr>
                <tr><th>対象ロール(カンマ区切り)</th><td><input type="text" name="mln_allowed_roles" value="<?php echo esc_attr(get_option('mln_allowed_roles')); ?>" class="regular-text" /></td></tr>
                <tr><th>除外ユーザー名(カンマ区切り)</th><td><input type="text" name="mln_excluded_users" value="<?php echo esc_attr(get_option('mln_excluded_users')); ?>" class="regular-text" /></td></tr>
            </table>
            <?php submit_button(); ?>
        </form>
    </div>
    <?php
}

おわりに

このプラグインは、サイトのログイン状況を得るのに最適な機能を提供します。
設定もシンプルで、使用現場に合わせて自由にカスタマイズも可能です。

コメント

タイトルとURLをコピーしました