You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无二级域名跨域单点登录需求:两个独立WordPress站点实现方案咨询

Alright, let's solve this cross-domain SSO problem for your two independent WordPress sites. Since they're on separate domains, servers, and databases, subdomain-based tricks won't work here—we need a token-driven approach that syncs user data and handles seamless login across both sites. Here's how to implement it while keeping your domain1 registration form mostly untouched:

核心方案概述

We'll use server-side token authentication paired with WordPress hooks to:

  1. Sync new users from domain1 to domain2 automatically when they register
  2. Generate a secure token when users log into domain1, then redirect them to domain2 to validate the token and auto-login
  3. Keep user data (like passwords, profiles) in sync between both sites
Step 1: Set Up Shared Security

First, add a strong, unique shared key to both sites' wp-config.php files—this will validate requests between the two sites to prevent unauthorized access:

// Add this to wp-config.php on BOTH domain1.com and domain2.com
define('SSO_SHARED_KEY', 'your_32+_character_random_secure_key_here');

Make sure this key is long, random, and never shared publicly.

Step 2: Sync Users from domain1 to domain2 on Registration

We'll use WordPress's user_register hook to push new user data to domain2 right after they sign up on domain1—no need to modify your existing registration form.

Add this code to domain1's functions.php:

// Sync new domain1 users to domain2
add_action('user_register', 'sync_new_user_to_domain2', 10, 1);
function sync_new_user_to_domain2($user_id) {
    $user = get_user_by('id', $user_id);
    $sync_payload = array(
        'action' => 'sso_create_user',
        'username' => $user->user_login,
        'email' => $user->user_email,
        'password_hash' => $user->user_pass, // Pass WordPress's native password hash
        'nickname' => $user->nickname,
        'secret_key' => SSO_SHARED_KEY
    );

    // Send request to domain2's AJAX endpoint
    $response = wp_remote_post('https://domain2.com/wp-admin/admin-ajax.php', array(
        'method' => 'POST',
        'body' => $sync_payload,
        'sslverify' => true // Keep this true if domain2 has a valid SSL certificate
    ));

    // Log errors for debugging (optional but recommended)
    if (is_wp_error($response)) {
        error_log("SSO Sync Failed: " . $response->get_error_message());
    }
}

Then add this code to domain2's functions.php to receive and create the synced user:

// Domain2 endpoint to create synced users from domain1
add_action('wp_ajax_sso_create_user', 'sso_receive_synced_user');
add_action('wp_ajax_nopriv_sso_create_user', 'sso_receive_synced_user');
function sso_receive_synced_user() {
    // Validate shared key first
    if (!isset($_POST['secret_key']) || $_POST['secret_key'] !== SSO_SHARED_KEY) {
        wp_send_json_error('Invalid security key');
        exit;
    }

    $username = sanitize_user($_POST['username']);
    $email = sanitize_email($_POST['email']);
    $password_hash = $_POST['password_hash'];

    // Check if user already exists
    if (username_exists($username) || email_exists($email)) {
        wp_send_json_success('User already exists');
        exit;
    }

    // Create user with the same password hash as domain1
    $user_id = wp_create_user($username, $password_hash, $email);
    if (is_wp_error($user_id)) {
        wp_send_json_error('Failed to create user: ' . $user_id->get_error_message());
        exit;
    }

    // Sync additional profile data
    wp_update_user(array(
        'ID' => $user_id,
        'nickname' => sanitize_text_field($_POST['nickname']),
        'display_name' => sanitize_text_field($_POST['nickname'])
    ));

    wp_send_json_success('User synced successfully');
    exit;
}
Step 3: Add SSO Redirection on domain1 Login

When a user logs into domain1, we'll generate an encrypted token with their user data, then redirect them to domain2 to auto-login.

Add this to domain1's functions.php:

// Redirect domain1 users to domain2 after login with SSO token
add_action('wp_login', 'sso_redirect_to_domain2', 10, 2);
function sso_redirect_to_domain2($user_login, $user) {
    // Token expires in 10 minutes (adjust as needed)
    $expiry = time() + 600;
    $token_data = json_encode(array(
        'user_email' => $user->user_email,
        'expiry' => $expiry
    ));

    // Encrypt token with shared key
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
    $encrypted_token = openssl_encrypt($token_data, 'aes-256-cbc', SSO_SHARED_KEY, 0, $iv);
    $encoded_token = base64_encode($encrypted_token . '::' . $iv);

    // Redirect to domain2's SSO verification page
    $redirect_url = 'https://domain2.com/sso-verify/?token=' . urlencode($encoded_token);
    wp_redirect($redirect_url);
    exit;
}
Step 4: Build the SSO Verification Page on domain2

Create a new page on domain2 with the slug sso-verify, then use this custom template to validate the token and auto-login the user:

Create a file named page-sso-verify.php in domain2's theme folder:

<?php
/*
Template Name: SSO Verification Page
*/

// Check for valid token
if (!isset($_GET['token'])) {
    wp_redirect(home_url('/login/?error=no_token'));
    exit;
}

$encoded_token = urldecode($_GET['token']);
list($encrypted_data, $iv) = explode('::', base64_decode($encoded_token), 2);

// Decrypt token
$decrypted_data = openssl_decrypt($encrypted_data, 'aes-256-cbc', SSO_SHARED_KEY, 0, $iv);
$token_data = json_decode($decrypted_data, true);

// Check if token is expired
if (time() > $token_data['expiry']) {
    wp_redirect(home_url('/login/?error=token_expired'));
    exit;
}

// Find user by email
$user = get_user_by('email', $token_data['user_email']);
if (!$user) {
    // Fallback: Fetch user data from domain1 if sync failed earlier
    $fetch_payload = array(
        'action' => 'sso_get_user_data',
        'user_email' => $token_data['user_email'],
        'secret_key' => SSO_SHARED_KEY
    );
    $response = wp_remote_post('https://domain1.com/wp-admin/admin-ajax.php', array(
        'method' => 'POST',
        'body' => $fetch_payload,
        'sslverify' => true
    ));

    if (!is_wp_error($response) && $response['response']['code'] == 200) {
        $user_data = json_decode($response['body'], true);
        $user_id = wp_create_user($user_data['username'], $user_data['password_hash'], $user_data['email']);
        $user = get_user_by('id', $user_id);
    } else {
        wp_redirect(home_url('/login/?error=user_not_found'));
        exit;
    }
}

// Auto-login the user
wp_set_auth_cookie($user->ID, true); // "true" enables "remember me"
wp_set_current_user($user->ID);

// Redirect to domain2's homepage or user dashboard
wp_redirect(home_url());
exit;
?>

Add this fallback endpoint to domain1's functions.php to let domain2 fetch user data if sync failed:

// Domain1 endpoint to fetch user data for SSO fallback
add_action('wp_ajax_sso_get_user_data', 'sso_provide_user_data');
add_action('wp_ajax_nopriv_sso_get_user_data', 'sso_provide_user_data');
function sso_provide_user_data() {
    if (!isset($_POST['secret_key']) || $_POST['secret_key'] !== SSO_SHARED_KEY) {
        wp_send_json_error('Invalid security key');
        exit;
    }

    $user = get_user_by('email', sanitize_email($_POST['user_email']));
    if (!$user) {
        wp_send_json_error('User not found');
        exit;
    }

    wp_send_json_success(array(
        'username' => $user->user_login,
        'email' => $user->user_email,
        'password_hash' => $user->user_pass,
        'nickname' => $user->nickname
    ));
    exit;
}

To keep passwords in sync when users change them on either site, add this hook to domain1's functions.php:

// Sync password changes from domain1 to domain2
add_action('password_reset', 'sync_password_change_to_domain2', 10, 2);
function sync_password_change_to_domain2($user, $new_pass) {
    $sync_payload = array(
        'action' => 'sso_update_password',
        'user_email' => $user->user_email,
        'new_password_hash' => wp_hash_password($new_pass),
        'secret_key' => SSO_SHARED_KEY
    );

    wp_remote_post('https://domain2.com/wp-admin/admin-ajax.php', array(
        'method' => 'POST',
        'body' => $sync_payload,
        'sslverify' => true
    ));
}

And this to domain2's functions.php:

// Domain2 endpoint to update synced user passwords
add_action('wp_ajax_sso_update_password', 'sso_receive_password_update');
add_action('wp_ajax_nopriv_sso_update_password', 'sso_receive_password_update');
function sso_receive_password_update() {
    if (!isset($_POST['secret_key']) || $_POST['secret_key'] !== SSO_SHARED_KEY) {
        wp_send_json_error('Invalid security key');
        exit;
    }

    $user = get_user_by('email', sanitize_email($_POST['user_email']));
    if (!$user) {
        wp_send_json_error('User not found');
        exit;
    }

    wp_update_user(array(
        'ID' => $user->ID,
        'user_pass' => $_POST['new_password_hash']
    ));

    wp_send_json_success('Password updated successfully');
    exit;
}
Key Security & Best Practices
  • Always use HTTPS: Both sites must have valid SSL certificates to prevent token and data interception.
  • Rotate your shared key: Periodically update the SSO_SHARED_KEY in both wp-config.php files.
  • Add logging: Use WordPress's error_log() function or a logging plugin to track sync/SSO failures.
  • Limit token expiry: Keep token expiry short (10-15 minutes) to reduce the risk of token misuse.

内容的提问来源于stack exchange,提问作者murcoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:30:40