将自定义 captcha 服务与 Customer Insights - Journeys 窗体集成

Customer Insights - Journeys 窗体允许您使用自定义的 captcha 机器人防护来验证窗体提交。 本文给出了一个如何集成 Google reCAPTCHA 的示例。 其他 captcha 服务的流都类似。

备注

在当前的应用版本中,只能激活一个 captcha 实现。 如果您使用自己的 captcha 提供程序(如下所述),使用现成 captcha 的现有窗体将停止工作。 自定义 captcha 实现至少需要编写和调试 dataverse 插件的基本知识。

流程由以下步骤组成:

  1. 将 reCAPTCHA 添加到窗体中
  2. 提交窗体后,将 captcha 文本值添加到窗体提交中。
  3. 在 CRM 中创建验证 captcha 的插件

分步示例:集成 Google reCAPTCHA

1. 将 reCAPTCHA 添加到窗体中

  1. 在 Customer Insights - Journeys 窗体编辑器中创建窗体。

  2. data-validate-submission="true" 属性添加到 <form> 元素中,这可以对窗体提交进行自定义验证:

    将属性添加到窗体元素。

  3. 在窗体中添加一个 <div id="g-recaptcha"> 作为 reCAPTCHA 的占位符。 此 div ID 之后将用作引用。 建议将占位符放在最后一个字段和提交按钮之间。

    为 reCAPTCHA 添加占位符。

  4. 发布窗体,并将窗体嵌入到您的网站中。

  5. 编辑嵌入窗体的页面。 将 Google 提供的脚本添加到页面标题中。 此脚本加载带有 onLoad 回调参数的 reCAPTCHA。 captcha 一加载即会调用此回调。

    <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback" async defer></script>
    
  6. 添加 onLoadCallback 函数:

    function onloadCallback() {
        grecaptcha.render('g-recaptcha',
        { 
          sitekey: '{sitekey}',
        });
    }
    

    {sitekey} 占位符替换为 Google 提供的占位符。 此回调函数在您之前创建的占位符 <div id="g-recaptcha"> 中呈现 reCAPTCHA。

  7. 注册窗体加载程序调用的 onloadCallback 函数:

document.addEventListener("d365mkt-afterformload", onloadCallback);

2. 将 captcha 文本值添加到窗体提交中

提交窗体后,g-recaptcha-response 参数将被自动添加到窗体提交中。 在接下来的步骤中,您将构建一个隐藏此值的插件,因为它将被添加到插件代码返回的响应对象中的 ValidationOnlyFields 列表中。

将添加 G-recaptcha-response 参数。

3. 创建插件

3.1 为插件创建 Visual Studio 项目

  1. 打开 Visual Studio,使用 .NET Framework 4.6.2 创建一个新的类库项目。
  2. 在解决方案资源管理器中,选择管理 NuGet 包,安装 Microsoft.CrmSdk.CoreAssemblies

3.2 创建插件类

  1. Class1.cs 重命名为 CustomValidationPlugin.cs

  2. 让 CustomValidationPlugin 类从 IPlugin 接口继承,并添加 Execute 方法。

    public class CustomValidationPlugin : IPlugin
    {
       public void Execute(IServiceProvider serviceProvider)
       {
    
       }
    }
    
  3. 将以下代码添加到 execute 方法中,来检索上下文和跟踪服务。

    public void Execute(IServiceProvider serviceProvider)
    {
       // get tracing service
       ITracingService tracingService =
       (ITracingService)serviceProvider.GetService(typeof(ITracingService));
    
       // get plugin execution context
       IPluginExecutionContext context = (IPluginExecutionContext)
       serviceProvider.GetService(typeof(IPluginExecutionContext));
    }
    
  4. 添加此代码来检索窗体提交参数字符串。 它是一个 JSON 编码的字符串,表示用户在窗体中提交的字段。 此过程会检索此字符串,并使用反序列化的助手方法和之后定义的 FormSubmissionRequest 类对其进行反序列化。 这将检查 Fields 数组是否包含 g-repatcha-response 的密钥。 如果找不到 reCAPTCHA 密钥,它将返回跳过验证,因为所处理的窗体不包含 Google repatcha 元素。

    var requestString = (string)context.InputParameters["msdynmkt_formsubmissionrequest"];
    var requestObject = Deserialize<FormSubmissionRequest>(requestString);
    if (!requestObject.Fields.TryGetValue("g-recaptcha-response", out string recaptchaToken))
    {
       tracingService.Trace("g-recaptcha-response was not present in form submission");
       return;
    }
    
  5. 如果 g-recaptcha-token 值为 null 或为空,添加以下代码用于返回。

    if (String.IsNullOrEmpty(recaptchaToken))
    {
       tracingService.Trace($"g-recaptcha-response value not found");
       return;
    }
    
  6. 添加以下代码以根据 Google API 验证 Google captcha 令牌。

    string url = "https://www.google.com/recaptcha/api/siteverify";
    using (HttpClient client = new HttpClient())
    {
       var content = new FormUrlEncodedContent(new Dictionary<string, string>
       {
          {"secret", "your_secret_key"},
          {"response", recaptchaToken}
       });
    
       try
       {
          var response = client.PostAsync(url, content).Result;
          if (!response.IsSuccessStatusCode)
          {
             tracingService.Trace($"Request Failed: ({response.StatusCode}){response.Content}");
             return;
          }
    
          var responseString = response.Content.ReadAsStringAsync().Result;
    
          gRecaptchaResponse = Deserialize<GRecaptchaResponse>(responseString);
    
          var resp = new ValidateFormSubmissionResponse()
          {
             IsValid = isValid,
             ValidationOnlyFields = new List<string>() { "g-recaptcha-response" }
          };
          context.OutputParameters["msdynmkt_validationresponse"] = Serialize(resp);
        }
        catch (Exception e)
        {
           tracingService.Trace($"{e.Message}");
        }
    }
    

    首先,将定义 URL,然后将创建 HttpClient 实例。 将创建 FormUrlEncodedContent 对象,其中包含之前步骤中检索到的 recaptchaToken 和 Google 提供的密钥。 然后,发送 POST 请求,并检查状态代码,如果不成功,则返回。 如果成功,将使用反序列化助手方法和之后定义的 GRecaptchaResponse 反序列化响应。 然后,将创建一个新的 ValidateFormSubmissionResponse 对象,对其进行序列化,并将其设置为输出参数 msdynmkt_validationresponse 的值,这是它用来接受或拒绝提交的一项 Microsoft 服务。 将 g-recaptcha-response 字符串添加到 ValidationOnlyFields 列表会在 UI 中的窗体提交中隐藏此字段。

  7. 添加以下代码来定义序列化和反序列化助手方法。

    private T Deserialize<T>(string jsonString)
    {
       serializer = new DataContractJsonSerializer(typeof(T));
       T result;
       using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
       {
          result = (T)serializer.ReadObject(stream);
       }
       return result;
    }
    
    private string Serialize<T>(T obj)
    {
        string result;
        serializer = new DataContractJsonSerializer(typeof(T));
        using (MemoryStream memoryStream = new MemoryStream())
        {
           serializer.WriteObject(memoryStream, obj);
           result = Encoding.Default.GetString(memoryStream.ToArray());
        }
        return result;
    }
    
  8. 添加以下代码来定义序列化/反序列化 JSON 字符串对象所需的类。

    public class FormSubmissionRequest
     {
         public Dictionary<string, string> Fields { get; set; }
     }
    
     public class GRecaptchaResponse
     {
         public bool success { get; set; }
     }
    
     public class ValidateFormSubmissionResponse
     {
         public bool IsValid { get; set; }
         public List<string> ValidationOnlyFields { get; set; }
     }
    

3.3 签署和构建插件

  1. 右键单击项目,在解决方案资源管理器中选择属性
  2. 选择签名选项卡,然后选中为程序集签名复选框。
  3. 选择<New...>
  4. 输入密钥文件名称,取消选择使用密码保护我的密钥文件
  5. 生成项目。
  6. 您可以在 \bin\Debug 中找到插件程序集 CustomValidationPlugin.dll

3.4 注册插件

  1. 打开 PluginRegistration.exe
  2. 选择创建新连接
  3. 选择Office 365
  4. 选择登录
  5. 选择注册,然后选择注册新程序集

    选择注册,然后选择注册新程序集。

  6. 在步骤 1 中选择 (...) 按钮,然后选择前面步骤中构建的 dll。
  7. 选择注册所选插件

3.4 注册步骤

  1. 从已注册程序集的列表中选择 CustomValidationPlugin
  2. 选择注册新步骤
  3. 在消息文本字段中输入 msdynmkt_validateformsubmission
  4. 确保将执行模式设置为同步

    确保将执行模式设置为同步。

  5. 确保执行顺序设置为 10
  6. 确保将执行的事件管道阶段设置为后操作
  7. 选择注册新步骤

结束语

当提交具有 data-validate-submission 属性的窗体时,您的自定义插件将运行并使用 Google 服务验证 reCAPTCHA 响应。 自定义插件将在默认的 Microsoft 验证插件之后运行。 如果窗体中没有 Microsoft captcha 字段,Microsoft 插件会设置 IsValid:false,除非您使用 IsValid:true 覆盖它,否则提交将失败。

验证流。