1

我正在尝试通过 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:&#x2F;&#x2F;7231513.collect.igodigital.com&#x2F;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 并将其传递给有效负载,现在我得到了成功响应。

但是我不确定这种方式是否存在任何安全问题。

4

1 回答 1

2

首先,您需要使用 Content Builder 选项创建您的云页面。这将删除script您回复中的标签。

其次,您正在以内容类型发送数据text/html,请尝试使用application/x-www-form-urlencoded

我相信,您的表单处理程序不会捕获,因为在您发送内容类型g-recaptcha-response时无法使用 Request.GetFormField 检索它。text/html

请看这篇文章:https ://ampscript.xyz/how-tos/perform-an-http-request/

否则,将 Axios 用于您的客户端请求:https ://github.com/axios/axios

于 2020-07-29T10:36:27.233 回答