javascript - 如何在服务器端验证 google reCaptcha?
问题描述
我实施了 reCaptcha。单击“我不是机器人”复选框后,将从谷歌生成一个令牌。
客户端(js)
function checkCaptchaAndSubscribe(thisContext)
{
var captchaResponse = grecaptcha.getResponse();
if (captchaResponse == "") {
$captchaRequired.css('display', 'block');
return false;
}
grecaptcha.reset();
$captchaRequired.css('display', 'none');
jQuery.ajax({
url: "/black_newsletter2go/index/verify",
method: "POST",
async: "true",
data: {
recaptchaResponse: captchaResponse
},
success: function(response) {
$statusContainer.show();
if (response != "success") {
$status.html("<h2 class='nl2go_h2'>Die Captcha Validierung ist fehlgeschlagen!</h2>");
return false;
}
subscribe(thisContext);
}
});
}
我使用 ajax 将令牌发送到我的服务器并在那里验证它,如下所示:
服务器端(php):
public function verifyAction()
{
$captchaResponse = $this->getRequest()->getParam('recaptchaResponse');
if (!isset($captchaResponse) || empty($captchaResponse)) {
return "captcha response is empty";
}
$secretKey = Mage::Helper("recaptcha")->getSecretKey();
$url = 'https://www.google.com/recaptcha/api/siteverify';
$data = array(
'secret' => $secretKey,
'response' => $captchaResponse,
);
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$result = json_decode($result);
//var_dump($result);
//exit();
if ($result->success
&& (strpos(Mage::getBaseUrl(), $result->hostname) !== false)) {
echo "success";
} else {
echo "fail";
}
}
这是对象 $result 的输出
success
如果检查成功则返回,否则返回fail
。
但这足够了吗?如果攻击者使用 burpsuite 之类的 HTTP 代理将响应更改为success
? 那么他就可以绕过我的检查并且总是通过吗?还是我错了?
解决方案
它使用密钥对来加密/解密信息。所以它正在发送加密的信息。这就是它不能被篡改的原因,但是当然,这意味着你必须确保私钥不会被盗。
服务器知道状态并将其保存在其存储中,因此如果客户端在“失败”时尝试将其用作“成功”,则无论如何服务器都会知道。所以对于黑客来说,为客户端改变值的可能性不大,当然这取决于你的代码。如果您使用该 reCAPTCHA 来登录用户,那么如果 reCAPTCHA 返回“失败”,那么显然该登录尝试将在服务器端失败。因此,无论客户端是否被告知“成功”,它仍然不会登录。客户端永远不应该成为这种状态的保持者,因为它不能被信任(它总是可能有被污染的数据。)
它的工作方式类似于您在浏览器和使用 HTTPS 的服务器之间所做的工作。
您的客户端和服务器之间的通信也应该在 HTTPS 上,以避免一些更容易的中间人 (MITM) 问题。但是,总是有可能有人成为代理,这是大多数 MITM 的工作方式,在这种情况下,MITM 可以更改您所做的任何事情。
然而,MITM 不能做的一件事是为最终目的地创建有效证书。从这个意义上说,有一种保护,但许多人不会在每次连接到网站时验证证书。但是,一种技术是 MITM 不给你 HTTPS,只有他和你的服务器会使用 HTTPS,而客户端会保持在 HTTP 上。尽管您的代码可以检测到这种情况,但显然 MITM 也可以更改该代码。同样,设置 cookie可以增强安全性Http-Only
,Secure
但也可以被 MITM 拦截。
由于 MITM 可以完全更改您的脚本,因此您在客户端几乎无法做任何事情来帮助检测此类问题,而在服务器端,您将收到类似于客户端发送给您的命中。再说一次,没有真正的方法来检测 MITM。
有一篇帖子提出了这个问题:我可以从服务器端检测到 MITM 吗?这并非不可能,但相当棘手。通过对普通 HTTP 解决方案的新实现/扩展来实施一些解决方案,但这些解决方案需要一个连接到不同系统的附加应用程序,而且一旦有足够多的人使用这些解决方案,没有理由不能由 MITM 代理解决方案。
推荐阅读
- sql - sql oracle - 使用 case when 过滤查询 sql
- reactjs - 背景图像在 Safari v14 Catalina 上不起作用
- python - MS Learn Python - 代码未在 Visual Studio 中运行(新手)
- python - Tkinter:将文本条目作为按下按钮时调用的函数的参数传递
- laravel - Laravel 禁用调试模式
- json - 是什么导致此 JSON 出现意外的 EOF?
- c# - Xaml 属性的具有多个静态类的常量
- php - 如何添加逗号id=price2 中的值
- reactjs - Reactjs问题路由与URL中的参数
- azure-cosmosdb - Azure Purview 扫描 cosmos 数据库以发现数据资产有时会失败