Php ReCaptcha在iPhone上无法正常工作
我有一个网站与一个简单的联系方式。验证有点小,因为它不进入数据库;只是一封电子邮件。表格的工作原理如下: 共有5个字段,其中4个是必填字段。在4个字段有效之前,将禁用提交,然后您可以提交它。然后在服务器上再次验证所有内容,包括recaptcha(未经me客户端验证)。整个过程都是用ajax完成的,必须在服务器端通过多个测试,或者返回4**头,并调用失败回调处理程序 在桌面上,一切都像Chrome上的gangbusters(我没有尝试过其他浏览器,但我无法想象它们为什么会有所不同),但在iPhone上,即使我没有选中测试框,reCaptcha也会进行验证 换句话说:我仍然必须正确填写这四个值才能提交,但是如果我没有选中reCaptcha复选框,请求仍然成功 如果有人认为这会有帮助,我可以发布一些代码,但问题似乎出在设备上,而不是代码上。有人对此有什么见解吗Php ReCaptcha在iPhone上无法正常工作,php,iphone,recaptcha,Php,Iphone,Recaptcha,我有一个网站与一个简单的联系方式。验证有点小,因为它不进入数据库;只是一封电子邮件。表格的工作原理如下: 共有5个字段,其中4个是必填字段。在4个字段有效之前,将禁用提交,然后您可以提交它。然后在服务器上再次验证所有内容,包括recaptcha(未经me客户端验证)。整个过程都是用ajax完成的,必须在服务器端通过多个测试,或者返回4**头,并调用失败回调处理程序 在桌面上,一切都像Chrome上的gangbusters(我没有尝试过其他浏览器,但我无法想象它们为什么会有所不同),但在iPhon
注意:如果有帮助的话,服务器端是PHP/Apache
更新日期:2015年5月28日 我仍在调试,但似乎Mobile Safari忽略了我iPhone上的响应标题。当我将响应输出到页面时,我在桌面上得到的
(数据、状态、xhr)
是:
数据
:此时我的回答是错误或成功->错误
状态
:错误
xhr
:{'error',400,'error'}
数据
:错误
状态
:成功
xhr
:{'error',200,'success'}
{“headers”:{“cache control”:“no cache”}
,但没有效果
更新日期:2015年6月3日 根据请求,这里是代码。这几乎肯定超出了您的需要。它也变得更迟钝,因为我已经作出了改变,试图修复它。还要注意的是,虽然看起来有些变量尚未定义,但它们(应该)已经在其他文件中定义
客户端
服务器:
在客户端是否正确设置了“remoteIP”变量
即使Ajax请求发送空值或假值,php脚本中的isset()函数也会返回true,从而错误地填充$remoteIp
试着做:
$remoteIp = $_SERVER['REMOTE_ADDR'];
Ajax只是让浏览器执行请求,因此PHP可以完美地抓取用户的ip
我敢肯定,如果您传递了错误的值,ReCaptcha将以某种方式陷入困境
决不信任Ajax上的任何Javascript变量也更安全,因为这些变量也应被视为用户输入。验证码旨在防止恶意客户端(机器人),因此理论上如果客户端绕过验证码,这是服务器端的问题。(但是,如果客户端未能完成验证码,则可能是服务器端问题或客户端问题。)
因此,问题一定出在服务器上。即使出于安全考虑,您也应该使用
$\u服务器['REMOTE\u ADDR']
,而不是$\u POST['remoteIp']
,因为$\u POST['remoteIp']
可能(被恶意客户端)伪造。事实上,$\u服务器['REMOTE\u ADDR']
比客户端的$\u POST['remoteIp']
可靠得多我在两三个月前编写了一个脚本,它仍然可以正常工作,请尝试以下方法:
<?php
$siteKey = ''; // Public Key
$secret = ''; // Private Key
/**
* This is a PHP library that handles calling reCAPTCHA.
* - Documentation and latest version
* https://developers.google.com/recaptcha/docs/php
* - Get a reCAPTCHA API Key
* https://www.google.com/recaptcha/admin/create
* - Discussion group
* http://groups.google.com/group/recaptcha
*
* @copyright Copyright (c) 2014, Google Inc.
* @link http://www.google.com/recaptcha
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* A ReCaptchaResponse is returned from checkAnswer().
*/
class ReCaptchaResponse
{
public $success;
public $errorCodes;
}
class ReCaptcha
{
private static $_signupUrl = "https://www.google.com/recaptcha/admin";
private static $_siteVerifyUrl =
"https://www.google.com/recaptcha/api/siteverify?";
private $_secret;
private static $_version = "php_1.0";
/**
* Constructor.
*
* @param string $secret shared secret between site and ReCAPTCHA server.
*/
function ReCaptcha($secret)
{
if ($secret == null || $secret == "") {
die("To use reCAPTCHA you must get an API key from <a href='"
. self::$_signupUrl . "'>" . self::$_signupUrl . "</a>");
}
$this->_secret=$secret;
}
/**
* Encodes the given data into a query string format.
*
* @param array $data array of string elements to be encoded.
*
* @return string - encoded request.
*/
private function _encodeQS($data)
{
$req = "";
foreach ($data as $key => $value) {
$req .= $key . '=' . urlencode(stripslashes($value)) . '&';
}
// Cut the last '&'
$req=substr($req, 0, strlen($req)-1);
return $req;
}
/**
* Submits an HTTP GET to a reCAPTCHA server.
*
* @param string $path url path to recaptcha server.
* @param array $data array of parameters to be sent.
*
* @return array response
*/
private function _submitHTTPGet($path, $data)
{
$req = $this->_encodeQS($data);
$response = file_get_contents($path . $req);
return $response;
}
/**
* Calls the reCAPTCHA siteverify API to verify whether the user passes
* CAPTCHA test.
*
* @param string $remoteIp IP address of end user.
* @param string $response response string from recaptcha verification.
*
* @return ReCaptchaResponse
*/
public function verifyResponse($remoteIp, $response)
{
// Discard empty solution submissions
if ($response == null || strlen($response) == 0) {
$recaptchaResponse = new ReCaptchaResponse();
$recaptchaResponse->success = false;
$recaptchaResponse->errorCodes = 'missing-input';
return $recaptchaResponse;
}
$getResponse = $this->_submitHttpGet(
self::$_siteVerifyUrl,
array (
'secret' => $this->_secret,
'remoteip' => $remoteIp,
'v' => self::$_version,
'response' => $response
)
);
$answers = json_decode($getResponse, true);
$recaptchaResponse = new ReCaptchaResponse();
if (trim($answers ['success']) == true) {
$recaptchaResponse->success = true;
} else {
$recaptchaResponse->success = false;
$recaptchaResponse->errorCodes = $answers [error-codes];
}
return $recaptchaResponse;
}
}
$reCaptcha = new ReCaptcha($secret);
if(isset($_POST["g-recaptcha-response"])) {
$resp = $reCaptcha->verifyResponse(
$_SERVER["REMOTE_ADDR"],
$_POST["g-recaptcha-response"]
);
if ($resp != null && $resp->success) {echo "OK";}
else {echo "CAPTCHA incorrect";}
}
?>
<html>
<head>
<title>Google reCAPTCHA</title>
<script src="https://www.google.com/recaptcha/api.js"></script>
</head>
<body>
<form action="reCAPTCHA.php" method="POST">
<input type="submit" value="Submit">
<div class="g-recaptcha" data-sitekey="<?php echo $siteKey; ?>"></div>
</form>
</body>
</html>
谷歌雷帕查
像这个问题一样,最简单的解决方法是忽略自然头验证,在回调成功时,使用一些标志进行验证
我见过一些这样的情况,但从来都不好闻。需要用于提交AJAX请求的Javascript来帮助您进行调试。您是否正在发布(请说“是”)而没有获得?如果您正在发布,但无法发布,请确保在请求中添加缓存破坏(不要只依赖于标题,因为有很多东西可以忽略标题)。但是发布JS,我们可以从中提供帮助。@user1167442是的,请提供一些代码:)这里会很有帮助。是的-添加了POST方法。代码。谢谢。暗中猜测-可能你的iPhone日期设置不正确。请提供一些服务器端代码(如你提到的PHP)?我100%确定存在服务器端问题。如果您试图仅从客户端修复此问题,恶意黑客仍然可以忽略验证码。根据我的代码,您无法看到它,但服务器上设置了remoteIP
var。但是,在这两种情况下,为什么根据客户端浏览器会有所不同?如果是calc在客户端,另一个浏览器很可能会计算出不同的结果,将错误的IP发送回google。我认为javascript甚至无法访问remoteIP。不管怎样,这都是没有意义的。在这种情况下,它是在加载页面之前在服务器上计算的,并传递给javascript变量。看起来你说了两件事e、 你是说IOS上的Safari不支持captcha吗?另外,我不太明白第二部分如何适用于我的情况。@user1167442不。问题是Safari绕过了captcha。理论上,如果绕过了captcha,那一定是服务器端的问题。第二部分提出了一个可能的解决方案。谢谢你的通知接着,我改写了我的答案。
$remoteIp = $_SERVER['REMOTE_ADDR'];
<?php
$siteKey = ''; // Public Key
$secret = ''; // Private Key
/**
* This is a PHP library that handles calling reCAPTCHA.
* - Documentation and latest version
* https://developers.google.com/recaptcha/docs/php
* - Get a reCAPTCHA API Key
* https://www.google.com/recaptcha/admin/create
* - Discussion group
* http://groups.google.com/group/recaptcha
*
* @copyright Copyright (c) 2014, Google Inc.
* @link http://www.google.com/recaptcha
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* A ReCaptchaResponse is returned from checkAnswer().
*/
class ReCaptchaResponse
{
public $success;
public $errorCodes;
}
class ReCaptcha
{
private static $_signupUrl = "https://www.google.com/recaptcha/admin";
private static $_siteVerifyUrl =
"https://www.google.com/recaptcha/api/siteverify?";
private $_secret;
private static $_version = "php_1.0";
/**
* Constructor.
*
* @param string $secret shared secret between site and ReCAPTCHA server.
*/
function ReCaptcha($secret)
{
if ($secret == null || $secret == "") {
die("To use reCAPTCHA you must get an API key from <a href='"
. self::$_signupUrl . "'>" . self::$_signupUrl . "</a>");
}
$this->_secret=$secret;
}
/**
* Encodes the given data into a query string format.
*
* @param array $data array of string elements to be encoded.
*
* @return string - encoded request.
*/
private function _encodeQS($data)
{
$req = "";
foreach ($data as $key => $value) {
$req .= $key . '=' . urlencode(stripslashes($value)) . '&';
}
// Cut the last '&'
$req=substr($req, 0, strlen($req)-1);
return $req;
}
/**
* Submits an HTTP GET to a reCAPTCHA server.
*
* @param string $path url path to recaptcha server.
* @param array $data array of parameters to be sent.
*
* @return array response
*/
private function _submitHTTPGet($path, $data)
{
$req = $this->_encodeQS($data);
$response = file_get_contents($path . $req);
return $response;
}
/**
* Calls the reCAPTCHA siteverify API to verify whether the user passes
* CAPTCHA test.
*
* @param string $remoteIp IP address of end user.
* @param string $response response string from recaptcha verification.
*
* @return ReCaptchaResponse
*/
public function verifyResponse($remoteIp, $response)
{
// Discard empty solution submissions
if ($response == null || strlen($response) == 0) {
$recaptchaResponse = new ReCaptchaResponse();
$recaptchaResponse->success = false;
$recaptchaResponse->errorCodes = 'missing-input';
return $recaptchaResponse;
}
$getResponse = $this->_submitHttpGet(
self::$_siteVerifyUrl,
array (
'secret' => $this->_secret,
'remoteip' => $remoteIp,
'v' => self::$_version,
'response' => $response
)
);
$answers = json_decode($getResponse, true);
$recaptchaResponse = new ReCaptchaResponse();
if (trim($answers ['success']) == true) {
$recaptchaResponse->success = true;
} else {
$recaptchaResponse->success = false;
$recaptchaResponse->errorCodes = $answers [error-codes];
}
return $recaptchaResponse;
}
}
$reCaptcha = new ReCaptcha($secret);
if(isset($_POST["g-recaptcha-response"])) {
$resp = $reCaptcha->verifyResponse(
$_SERVER["REMOTE_ADDR"],
$_POST["g-recaptcha-response"]
);
if ($resp != null && $resp->success) {echo "OK";}
else {echo "CAPTCHA incorrect";}
}
?>
<html>
<head>
<title>Google reCAPTCHA</title>
<script src="https://www.google.com/recaptcha/api.js"></script>
</head>
<body>
<form action="reCAPTCHA.php" method="POST">
<input type="submit" value="Submit">
<div class="g-recaptcha" data-sitekey="<?php echo $siteKey; ?>"></div>
</form>
</body>
</html>