织梦表单如何实现跨服务器提交?

99ANYc3cd6
预计阅读时长 32 分钟
位置: 首页 织梦建站 正文

核心思路

跨服务器提交的核心思想是:在A网站(源服务器)上,不直接处理表单数据,而是将数据打包发送到B网站(目标服务器)的一个专门接口,B网站接收到数据后,再进行正常的入库或其他操作。

由于浏览器的同源策略,直接使用AJAX请求另一个域名的接口可能会被阻止,我们需要一些技术手段来绕过或解决这个问题。


使用服务器端代理(推荐,最安全可靠)

这种方法的原理是:用户在A网站提交表单,请求先发送到A网站自己的一个处理页面(如 post.php),这个页面使用PHP的cURL库,在服务器端向B网站的目标接口发起请求,因为这是服务器与服务器之间的通信,完全不受浏览器同源策略的限制。

优点:

  • 安全性高:目标服务器的接口地址和密钥永远不会暴露在前端代码中。
  • 兼容性好:不依赖浏览器的特定功能,所有浏览器都能正常工作。
  • 稳定可靠:cURL功能强大,可以处理各种复杂的请求。

缺点:

  • 需要在A网站的服务器上开启并配置cURL扩展(99%的虚拟主机或云服务器都默认支持)。

实现步骤:

第1步:在B网站(目标服务器)创建接收接口

  1. 在B网站根目录下创建一个新文件,receive.php
  2. 这个文件将负责接收来自A网站的数据,并进行处理(如入库)。

receive.php (B网站) 代码示例:

<?php
// 设置响应头,告诉A网站服务器这是一个JSON响应
header('Content-Type: application/json; charset=utf-8');
// 1. 安全验证(非常重要!)
// 这里使用一个预定义的Token,A网站提交时需要带上这个Token
$secretToken = 'YOUR_SECRET_TOKEN_HERE'; // 请务必设置一个复杂的、不易猜测的Token
if (empty($_POST['token']) || $_POST['token'] !== $secretToken) {
    http_response_code(403); // 返回禁止访问状态码
    echo json_encode(['status' => 'error', 'message' => 'Invalid token.']);
    exit;
}
// 2. 接收并处理数据
// 从POST请求中获取表单数据
$title = isset($_POST['title']) ? htmlspecialchars(trim($_POST['title'])) : '';
$content = isset($_POST['content']) ? htmlspecialchars(trim($_POST['content'])) : '';
$email = isset($_POST['email']) ? htmlspecialchars(trim($_POST['email'])) : '';
// 这里是你原有的入库逻辑,例如插入到dede_addonarticle表
// 注意:你需要根据B网站的数据库结构和织梦的API进行调整
// require_once(DEDEINC.'/datalistcp.class.php');
// require_once(DEDEINC.'/custom.func.php'); // 可能需要引入一些函数
// 示例:直接入库(请根据实际情况修改)
if (!empty($title) && !empty($content)) {
    // 连接B网站的数据库
    // $dbhost = 'localhost';
    // $dbuser = 'b_db_user';
    // $dbpass = 'b_db_password';
    // $dbname = 'b_database_name';
    // $link = mysqli_connect($dbhost, $dbuser, $dbpass, $dbname);
    // if (!$link) { die('Error connecting to database'); }
    // $sql = "INSERT INTO dede_addonarticle (title, body, typeid, pubdate) VALUES ('$title', '$content', 1, ".time().")";
    // mysqli_query($link, $sql);
    // mysqli_close($link);
    // 为了演示,我们只返回成功信息
    echo json_encode([
        'status' => 'success',
        'message' => 'Data received and saved successfully!',
        'data' => [
            'title' => $title,
            'content' => $content,
            'email' => $email
        ]
    ]);
} else {
    echo json_encode(['status' => 'error', 'message' => 'Title and content are required.']);
}
?>

第2步:在A网站(源服务器)创建代理提交页面

  1. 在A网站根目录下创建一个新文件,proxy.php
  2. 这个文件接收A网站前端发来的数据,并使用cURL转发给B网站的 receive.php

proxy.php (A网站) 代码示例:

<?php
// 设置响应头
header('Content-Type: application/json; charset=utf-8');
// 1. 接收前端传来的数据(可以是POST或GET)
$data = [ => isset($_POST['title']) ? trim($_POST['title']) : '',
    'content' => isset($_POST['content']) ? trim($_POST['content']) : '',
    'email' => isset($_POST['email']) ? trim($_POST['email']) : '',
    'token' => 'YOUR_SECRET_TOKEN_HERE' // 必须和B网站receive.php中的Token一致
];
// 2. 使用cURL向B网站发送请求
$ch = curl_init();
// B网站接收接口的完整URL
$url = 'http://www.b.com/receive.php'; // 请替换为B网站的实际域名
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true); // 使用POST方法
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); // 将数据转换为URL编码的字符串
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 将curl_exec()获取的信息以字符串返回,而不是直接输出
curl_setopt($ch, CURLOPT_TIMEOUT, 15); // 设置超时时间,防止长时间等待
// 在开发环境下,可以忽略SSL证书验证(生产环境请谨慎)
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// 执行请求
$response = curl_exec($ch);
// 检查是否有错误发生
if (curl_errno($ch)) {
    echo json_encode(['status' => 'error', 'message' => 'cURL request failed: ' . curl_error($ch)]);
} else {
    // 将B网站返回的响应直接返回给前端
    echo $response;
}
curl_close($ch);
?>

第3步:修改A网站的织梦表单模板

找到你的织梦表单模板文件(通常是 plus/diyform.htm),修改其中的JavaScript代码,让它提交数据到本地的 proxy.php,而不是默认的 /plus/diy.php

diyform.htm (A网站模板) 示例:

<form name="myform" action="/proxy.php" method="post" enctype="multipart/form-data">
    <input type="hidden" name="diyid" value="{dede:global.diyid/}" />
    <input type="hidden" name="do" value="2" />
    <p>标题:<input type="text" name="title" id="title" class="intxt" style="width:250px" /></p>
    <p>内容:<textarea name="content" id="content" style="width:360px;height:150px"></textarea></p>
    <p>邮箱:<input type="text" name="email" id="email" class="intxt" style="width:250px" /></p>
    <p>
        <input type="submit" name="submit" value="提 交" class="btn" />
    </p>
</form>
<script>
    document.querySelector('form').addEventListener('submit', function(e) {
        // 这里可以添加前端的简单验证
        const title = document.getElementById('title').value;
        if (!title) {
            alert('标题不能为空!');
            e.preventDefault(); // 阻止表单提交
            return;
        }
        // 表单会正常提交到 /proxy.php,无需复杂的AJAX代码
        // proxy.php会处理cURL请求并返回结果
    });
</script>

使用JSONP(仅适用于GET请求,已不推荐)

JSONP(JSON with Padding)是一种早期用于解决跨域请求的技巧,它利用了<script>标签的src属性不受同源策略限制的特性。

重要提示:JSONP只支持GET请求,不安全(容易受到XSS攻击),且在现代Web开发中已基本被CORS取代。仅当你无法修改服务器端代码(B网站无法提供接口)且数据量不大、不敏感时,才考虑此方案。**

实现步骤:

第1步:B网站(目标服务器)支持JSONP

B网站的接收页面 receive_jsonp.php 必须能返回JSONP格式的数据。

receive_jsonp.php (B网站) 代码示例:

<?php
// 接收回调函数名,前端会传过来
$callback = isset($_GET['callback']) ? $_GET['callback'] : 'callback';
// 你的业务逻辑处理
$data = ['status' => 'success', 'message' => 'Data received via JSONP'];
// 返回JSONP格式
echo $callback . '(' . json_encode($data) . ')';
?>

第2步:A网站(源服务器)前端使用JSONP

在A网站的织梦表单模板中,使用JavaScript动态创建<script>标签来发起请求。

diyform.htm (A网站模板) 示例:

<form name="myform" action="#" onsubmit="return false;" method="post">
    <!-- 表单字段同上 -->
    <p>标题:<input type="text" name="title" id="title" class="intxt" style="width:250px" /></p>
    <p>邮箱:<input type="text" name="email" id="email" class="intxt" style="width:250px" /></p>
    <p><input type="button" name="submit" value="提 交" class="btn" onclick="submitForm()" /></p>
</form>
<script>
    function submitForm() {
        const title = document.getElementById('title').value;
        const email = document.getElementById('email').value;
        // 动态创建script标签
        const script = document.createElement('script');
        // B网站接口,并带上回调函数名和参数
        // 注意:参数需要通过URL传递,不适合大量数据
        script.src = 'http://www.b.com/receive_jsonp.php?callback=handleResponse&title=' + encodeURIComponent(title) + '&email=' + encodeURIComponent(email);
        // 将script标签添加到body中,请求会自动发送
        document.body.appendChild(script);
    }
    // 这个函数名必须和B网站请求URL中的callback参数值一致
    function handleResponse(data) {
        console.log(data); // 在控制台打印B网站返回的数据
        if (data.status === 'success') {
            alert('提交成功!');
            // 可以在这里清空表单或做其他操作
        } else {
            alert('提交失败:' + data.message);
        }
        // 请求完成后,移除这个script标签,避免重复加载
        document.body.removeChild(document.querySelector('script[src^="http://www.b.com/receive_jsonp.php"]'));
    }
</script>

总结与建议

特性 服务器端代理 JSONP
安全性 (密钥不暴露) (参数暴露,易受攻击)
请求方式 支持POST和GET 仅支持GET
数据量 无限制(受服务器配置影响) 受URL长度限制
兼容性 好(依赖服务器cURL) 好(依赖浏览器<script>
推荐度 ★★★★★ (强烈推荐) ★☆☆☆☆ (仅作为备选)

对于织梦CMS的表单跨服务器提交,强烈建议你使用方案一(服务器端代理),它更安全、更强大,是处理此类问题的标准做法,方案二可以作为在特定极端情况下的备选方案。

-- 展开阅读全文 --
头像
Myprintf函数如何实现?
« 上一篇 02-25
织梦二级栏目图片如何指定?
下一篇 » 02-25

相关文章

取消
微信二维码
支付宝二维码

目录[+]