将自定义 captcha 服务与 Customer Insights - Journeys 窗体集成
Customer Insights - Journeys 窗体允许您使用自定义的 captcha 机器人防护来验证窗体提交。 本文给出了一个如何集成 Google reCAPTCHA 的示例。 其他 captcha 服务的流都类似。
备注
在当前的应用版本中,只能激活一个 captcha 实现。 如果您使用自己的 captcha 提供程序(如下所述),使用现成 captcha 的现有窗体将停止工作。 自定义 captcha 实现至少需要编写和调试 dataverse 插件的基本知识。
流程由以下步骤组成:
- 将 reCAPTCHA 添加到窗体中。
- 提交窗体后,将 captcha 文本值添加到窗体提交中。
- 在 CRM 中创建验证 captcha 的插件。
分步示例:集成 Google reCAPTCHA
1. 将 reCAPTCHA 添加到窗体中
在 Customer Insights - Journeys 窗体编辑器中创建窗体。
将
data-validate-submission="true"
属性添加到<form>
元素中,这可以对窗体提交进行自定义验证:在窗体中添加一个
<div id="g-recaptcha">
作为 reCAPTCHA 的占位符。 此 div ID 之后将用作引用。 建议将占位符放在最后一个字段和提交按钮之间。发布窗体,并将窗体嵌入到您的网站中。
编辑嵌入窗体的页面。 将 Google 提供的脚本添加到页面标题中。 此脚本加载带有
onLoad
回调参数的 reCAPTCHA。 captcha 一加载即会调用此回调。<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback" async defer></script>
添加 onLoadCallback 函数:
function onloadCallback() { grecaptcha.render('g-recaptcha', { sitekey: '{sitekey}', }); }
将
{sitekey}
占位符替换为 Google 提供的占位符。 此回调函数在您之前创建的占位符<div id="g-recaptcha">
中呈现 reCAPTCHA。注册窗体加载程序调用的 onloadCallback 函数:
document.addEventListener("d365mkt-afterformload", onloadCallback);
2. 将 captcha 文本值添加到窗体提交中
提交窗体后,g-recaptcha-response
参数将被自动添加到窗体提交中。 在接下来的步骤中,您将构建一个隐藏此值的插件,因为它将被添加到插件代码返回的响应对象中的 ValidationOnlyFields
列表中。
3. 创建插件
3.1 为插件创建 Visual Studio 项目
- 打开 Visual Studio,使用 .NET Framework 4.6.2 创建一个新的类库项目。
- 在解决方案资源管理器中,选择管理 NuGet 包,安装
Microsoft.CrmSdk.CoreAssemblies
。
3.2 创建插件类
将
Class1.cs
重命名为CustomValidationPlugin.cs
。让 CustomValidationPlugin 类从 IPlugin 接口继承,并添加 Execute 方法。
public class CustomValidationPlugin : IPlugin { public void Execute(IServiceProvider serviceProvider) { } }
将以下代码添加到 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)); }
添加此代码来检索窗体提交参数字符串。 它是一个 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; }
如果
g-recaptcha-token
值为 null 或为空,添加以下代码用于返回。if (String.IsNullOrEmpty(recaptchaToken)) { tracingService.Trace($"g-recaptcha-response value not found"); return; }
添加以下代码以根据 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 中的窗体提交中隐藏此字段。添加以下代码来定义序列化和反序列化助手方法。
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; }
添加以下代码来定义序列化/反序列化 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 签署和构建插件
- 右键单击项目,在解决方案资源管理器中选择属性。
- 选择签名选项卡,然后选中为程序集签名复选框。
- 选择
<New...>
。 - 输入密钥文件名称,取消选择使用密码保护我的密钥文件。
- 生成项目。
- 您可以在
\bin\Debug
中找到插件程序集CustomValidationPlugin.dll
。
3.4 注册插件
- 打开
PluginRegistration.exe
。 - 选择创建新连接。
- 选择Office 365。
- 选择登录。
- 选择注册,然后选择注册新程序集。
- 在步骤 1 中选择 (...) 按钮,然后选择前面步骤中构建的 dll。
- 选择注册所选插件。
3.4 注册步骤
- 从已注册程序集的列表中选择 CustomValidationPlugin。
- 选择注册新步骤。
- 在消息文本字段中输入
msdynmkt_validateformsubmission
。 - 确保将执行模式设置为同步。
- 确保执行顺序设置为
10
。 - 确保将执行的事件管道阶段设置为后操作。
- 选择注册新步骤。
结束语
当提交具有 data-validate-submission
属性的窗体时,您的自定义插件将运行并使用 Google 服务验证 reCAPTCHA 响应。 自定义插件将在默认的 Microsoft 验证插件之后运行。 如果窗体中没有 Microsoft captcha 字段,Microsoft 插件会设置 IsValid:false
,除非您使用 IsValid:true
覆盖它,否则提交将失败。