我正在尝试通过 Marketing Cloud - 云页面实施 reCAPTCHA 验证。
我已经使用本指南来做到这一点:https ://ampscript.xyz/how-tos/how-to-implement-google-recaptcha-on-marketing-cloud-forms/
我想要做的是创建一个发布请求,而不是 使用操作表单属性。
我的克林特脚本:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://www.google.com/recaptcha/api.js"></script>
</head>
<body>
<form id="form" >
<label>Email: </label>
<input type="email" name="EmailAddress">
<div
class="g-recaptcha"
data-sitekey="XXXXXXXXXXXXXXXXXXXXXX"
data-callback="grecaptchaCallback"
data-size="invisible"
></div>
<br>
<button>Send</button>
</form>
<script>
var form = document.getElementById('form');
form.addEventListener('submit', grecaptchaValidate);
function grecaptchaCallback() {
return new Promise(function (resolve, reject) {
if (grecaptcha.getResponse() !== '') {
var x=grecaptcha.getResponse();
console.log(x);
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "https://pub.s7.exacttarget.com/jnmlkgsfquv", true);
xhttp.setRequestHeader("Content-type", 'text/html',['Accept-Encoding'], ['identity'] );
xhttp.send();
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var response=this.responseText;
console.log(response);
response=response.split("<script>");
console.log(response);
console.log(response[0].trim());
}
}
}
grecaptcha.reset();
})
}
function grecaptchaValidate(e) {
e.preventDefault();
grecaptcha.execute();
}
</script>
</body>
</html>
</script>
</body>
</html>
这是我的服务器端脚本:
<script runat="server">
Platform.Load("core", "1.1.1");
try {
var g_recaptcha_response = Request.GetFormField("g-recaptcha-response");
var secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXX";
var payload = "secret=" + secret + "&response=" + g_recaptcha_response;
var contentType = "application/x-www-form-urlencoded";
var endpoint = "https://www.google.com/recaptcha/api/siteverify";
var req = HTTP.Post(endpoint, contentType, payload);
if (req.StatusCode == 200) {
var resp = Platform.Function.ParseJSON(String(req.Response));
if (!resp.success) throw "Wrong reCAPTCHA";
} else {
throw "reCAPTCHA API error";
}
/// DO SOMETHING
Write(Stringify(resp));
} catch (error) {
Write(Stringify({ status: "Error", message: error }));
}
</script>
我发送请求时得到的错误是:
{"status":"Error","message":"Wrong reCAPTCHA"}
<script>(function(a,m,i,g,o,s){o=a.createElement(g);s=a.getElementsByTagName(i)[0];o.src=m.origin+m.pathname+"/_t?eventType=CLOUDPAGESVISIT";o.width=0;o.height=0;o.style.display="none";s.appendChild(o);})(document,window.location,"body","img");</script>
<script src="https://7231513.collect.igodigital.com/collect.js"></script>
<script>
if (_etmc && typeof _etmc.push === 'function') {
_etmc.push(['setOrgId', '7231513']);
_etmc.push(['trackPageView']);
}
</script>
我得出的另一个结论-如果我手动插入从 x 对象( grecaptcha.getResponse() )从客户端收到的值,则响应正确:
{"success":true,"challenge_ts":"2020-07-29T09:30:03Z","hostname":"pub.s7.exacttarget.com"}
我很想知道如何根据我正在启动的帖子创建从客户端到服务器端页面的请求?
有什么我想念的吗?或者也许我工作不正常?
编辑:
问题出在服务器端页面的有效负载上,因为变量 g_recaptcha_response 为空。
我的解决方法是使用查询字符串变量捕获变量:
%%[
set @x = RequestParameter("x")
]%%
<script runat="server">
Platform.Load("core", "1.1.1");
var x = Variable.GetValue("@x");
try {
// var g_recaptcha_response = Request.GetFormField("g-recaptcha-response");
var secret = "XXXXXXXXXXXXXXXXXXXXXXXXX";
var payload = "secret=" + secret + "&response=" + x;
var contentType = "application/x-www-form-urlencoded";
var endpoint = "https://www.google.com/recaptcha/api/siteverify";
var req = HTTP.Post(endpoint, contentType, payload);
if (req.StatusCode == 200) {
var resp = Platform.Function.ParseJSON(String(req.Response));
if (!resp.success) throw "Wrong reCAPTCHA";
} else {
throw "reCAPTCHA API error";
}
/// DO SOMETHING
Write(Stringify(resp));
} catch (error) {
Write(Stringify({ status: "Error", message: error }));
}
</script>
因为无法在 SSJS 上捕获 URL 数据,所以我使用 AMPscript 捕获 x 并将其传递给有效负载,现在我得到了成功响应。
但是我不确定这种方式是否存在任何安全问题。