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

在Moodle定时任务中实现跨服务器向WordPress安全传输数据

实现Moodle定时向WordPress安全传输数据的PHP脚本方案

Hey, I’ve tackled similar cross-server sync tasks before, so here’s a robust, secure solution tailored for your setup—perfect for unlimited data volumes, and built to slot right into your existing Moodle cron framework:

1. First: Lock Down Cross-Site Authentication

Since your Moodle and WordPress are on separate servers, we need to make sure only legitimate requests from Moodle get processed by WordPress. API key + HMAC signature is way more secure than a plain API key, so we’ll go with that.

Step 1: Set Up the WordPress Receive Endpoint

Add this to your WordPress theme’s functions.php or a custom plugin (custom plugins are better for maintainability):

add_action('rest_api_init', function () {
    register_rest_route('moodle-sync/v1', '/receive-data', array(
        'methods' => 'POST',
        'callback' => 'moodle_sync_receive_data',
        'permission_callback' => function ($request) {
            // Pull your pre-configured API key (store this in WP admin settings, not hardcoded!)
            $api_key = get_option('moodle_sync_api_key');
            $signature = $request->get_header('X-Signature');
            $timestamp = $request->get_header('X-Timestamp');
            
            // Block replay attacks: only accept requests from the last 5 minutes
            if (abs(time() - $timestamp) > 300) {
                return new WP_Error('invalid_timestamp', 'Request timed out', array('status' => 403));
            }
            
            // Generate expected signature using HMAC-SHA256
            $request_body = $request->get_body();
            $expected_signature = hash_hmac('sha256', $timestamp . $request_body, $api_key);
            
            if ($signature !== $expected_signature) {
                return new WP_Error('invalid_signature', 'Signature verification failed', array('status' => 403));
            }
            return true;
        }
    ));
});

function moodle_sync_receive_data($request) {
    $data = $request->get_json_params();
    // Replace this with your actual data handling logic (e.g., create posts, update user data)
    $post_args = array(
        'post_title' => sanitize_text_field($data['title']),
        'post_content' => wp_kses_post($data['content']),
        'post_status' => 'publish',
        'post_type' => 'post'
    );
    $post_id = wp_insert_post($post_args);
    
    return $post_id ? 
        array('status' => 'success', 'post_id' => $post_id) :
        new WP_Error('save_failed', 'Failed to save data', array('status' => 500));
}

Don’t forget to add an admin setting in WordPress to store your API key (use add_settings_field() and friends) instead of hardcoding it.

Step 2: Moodle Side Signature & Request Setup

In your Moodle cron task’s PHP code, start with generating the secure signature and preparing your data:

// Configuration - store these in Moodle's config.php as constants for security
define('WP_SYNC_API_KEY', 'your-strong-unique-api-key-here');
define('WP_RESYNC_ENDPOINT', 'https://your-wp-site.com/wp-json/moodle-sync/v1/receive-data');

// Fetch data from Moodle (customize this to pull whatever you need to sync)
function get_moodle_sync_data() {
    global $DB;
    // Example: pull unsynced course updates
    return $DB->get_records('course', array('timemodified' => time() - 86400), '', 'id, fullname, summary');
}

$moodle_data = get_moodle_sync_data();
$timestamp = time();

2. Handle Unlimited Data Volumes

Since data can be huge, we can’t send everything in one request. Split it into batches, or use streaming for files.

Batch Processing for Structured Data

$batch_size = 100; // Adjust based on your server capacity
$total_batches = ceil(count($moodle_data) / $batch_size);

for ($batch_num = 0; $batch_num < $total_batches; $batch_num++) {
    $batch = array_slice($moodle_data, $batch_num * $batch_size, $batch_size);
    $json_payload = json_encode($batch);
    
    // Regenerate signature for each unique payload
    $signature = hash_hmac('sha256', $timestamp . $json_payload, WP_SYNC_API_KEY);
    
    // Send request
    $response = send_sync_request($json_payload, $timestamp, $signature);
    
    // Log results (Moodle's mtrace works great for cron logs)
    if ($response['status'] === 'success') {
        mtrace("Batch $batch_num synced successfully");
        // Mark these records as synced in Moodle
        foreach ($batch as $record) {
            $DB->set_field('course', 'synced', 1, array('id' => $record->id));
        }
    } else {
        mtrace("Batch $batch_num failed: " . $response['message']);
        // Optional: add retry logic here for failed batches
    }
}

// Reusable request function with SSL hardening
function send_sync_request($payload, $timestamp, $signature) {
    $ch = curl_init(WP_RESYNC_ENDPOINT);
    curl_setopt_array($ch, array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $payload,
        CURLOPT_HTTPHEADER => array(
            'Content-Type: application/json',
            "X-Timestamp: $timestamp",
            "X-Signature: $signature"
        ),
        // Enforce SSL security (never disable these in production!)
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2
    ));
    
    $response_body = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($http_code === 200) {
        return json_decode($response_body, true);
    } else {
        return array(
            'status' => 'error',
            'message' => "HTTP $http_code: " . substr($response_body, 0, 200) // Truncate long errors
        );
    }
}

Streaming Large Files (e.g., Moodle Attachments)

If you need to sync files, use multipart/form-data and include a file hash for integrity checks:

// Example: Sync a Moodle file to WordPress media library
$file_path = '/path/to/moodle/user/file.pdf';
$file_hash = hash_file('sha256', $file_path);
$timestamp = time();
$signature = hash_hmac('sha256', $timestamp . $file_hash, WP_SYNC_API_KEY);

$ch = curl_init(WP_RESYNC_ENDPOINT);
curl_setopt_array($ch, array(
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => array(
        'file' => new CURLFile($file_path),
        'file_hash' => $file_hash,
        'metadata' => json_encode(array('source' => 'Moodle'))
    ),
    CURLOPT_HTTPHEADER => array(
        "X-Timestamp: $timestamp",
        "X-Signature: $signature"
    ),
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_SSL_VERIFYHOST => 2
));

$response = curl_exec($ch);
// Update WordPress endpoint to handle file uploads and verify $file_hash

3. Integrate with Moodle Cron Task

Since you already have the cron framework set up, just drop the above logic into your task’s execute() method:

class local_sync_to_wp_task extends core\task\scheduled_task {
    public function get_name() {
        return get_string('synctowp', 'local_syncplugin');
    }
    
    public function execute() {
        mtrace("Starting Moodle to WordPress sync...");
        // Place all the sync logic here (data fetching, batch processing, requests)
        mtrace("Sync completed");
    }
}

4. Critical Security & Reliability Tips

  • Rotate API Keys: Change your API key every few months to reduce risk of compromise.
  • Idempotency: Add a unique sync_id to each record so WordPress doesn’t create duplicates if a batch is retried.
  • Logging: Keep detailed logs in both Moodle (use mtrace or Moodle’s logging API) and WordPress (use error_log() or a logging plugin).
  • Retry Logic: For failed batches, implement exponential backoff (e.g., wait 1min, then 2min, then 4min) instead of immediate retries.
  • Validate Input: Sanitize all data in both Moodle (before sending) and WordPress (before processing) to prevent XSS/SQL injection.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:17:36