如何在AAD B2C自定义策略的统一登录页添加reCaptcha
在Azure AD B2C统一登录页(unified.html)添加Google reCaptcha并验证
核心问题说明
统一登录页(ContentDefinition为api.signuporsignin,基于unifiedssp契约)与自断言页面(api.selfasserted)的渲染逻辑不同,无法直接通过声明字段自动渲染reCaptcha控件,需手动在自定义HTML中添加控件并通过JavaScript将验证结果传递给B2C策略。
步骤1:定义reCaptcha响应声明
在策略的<ClaimsSchema>节点下添加以下声明,用于存储reCaptcha的验证响应:
<ClaimType Id="g-recaptcha-response-toms"> <DisplayName>Google reCaptcha响应值</DisplayName> <DataType>string</DataType> <AdminHelpText>存储Google reCaptcha的验证token</AdminHelpText> </ClaimType> <!-- 可选:添加用于验证结果的声明 --> <ClaimType Id="recaptchaSuccess"> <DisplayName>reCaptcha验证结果</DisplayName> <DataType>boolean</DataType> </ClaimType>
步骤2:修改自定义unified.html页面
在你的自定义登录页中,完成以下操作:
- 引入Google reCaptcha脚本:在HTML的
<head>或<body>末尾添加reCaptcha加载脚本:<script src="https://www.google.com/recaptcha/api.js" async defer></script> - 添加reCaptcha控件:在登录表单的密码字段后插入reCaptcha控件(替换
YOUR_RECAPTCHA_SITE_KEY为你的站点密钥):<div class="form-group"> <label class="control-label">验证</label> <div class="g-recaptcha" data-sitekey="YOUR_RECAPTCHA_SITE_KEY"></div> </div> - 添加提交处理脚本:监听表单提交事件,将reCaptcha响应值存入B2C对应的声明字段:
document.addEventListener('DOMContentLoaded', function() { const loginForm = document.querySelector('form'); if (loginForm) { loginForm.addEventListener('submit', function(e) { // 获取reCaptcha响应token const recaptchaToken = grecaptcha.getResponse(); // 查找或创建隐藏输入框,绑定到声明字段 let recaptchaInput = loginForm.querySelector('input[name="g-recaptcha-response-toms"]'); if (!recaptchaInput) { recaptchaInput = document.createElement('input'); recaptchaInput.type = 'hidden'; recaptchaInput.name = 'g-recaptcha-response-toms'; loginForm.appendChild(recaptchaInput); } recaptchaInput.value = recaptchaToken; // 未完成验证则阻止提交 if (!recaptchaToken) { e.preventDefault(); alert('请完成人机验证'); } }); } });
步骤3:调整自断言技术配置文件
确保SelfAsserted-LocalAccountSignin-Username技术配置文件中正确包含reCaptcha声明:
- 在
<OutputClaims>中保留g-recaptcha-response-toms并标记为必填:<OutputClaim ClaimTypeReferenceId="g-recaptcha-response-toms" Required="true" /> - 确保
<ValidationTechnicalProfiles>中login-Recaptcha排在login-NonInteractive之前,先验证reCaptcha再执行登录逻辑。
步骤4:配置reCaptcha验证技术配置文件
确保login-Recaptcha技术配置文件正确调用Google验证API(替换YOUR_RECAPTCHA_SECRET_KEY为你的密钥):
<TechnicalProfile Id="login-Recaptcha"> <DisplayName>Google reCaptcha验证</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="ServiceUrl">https://www.google.com/recaptcha/api/siteverify?secret=YOUR_RECAPTCHA_SECRET_KEY</Item> <Item Key="SendClaimsIn">Form</Item> <Item Key="AllowInsecureAuthInProduction">false</Item> </Metadata> <InputClaims> <InputClaim ClaimTypeReferenceId="g-recaptcha-response-toms" PartnerClaimType="response" /> <InputClaim ClaimTypeReferenceId="clientIpAddress" PartnerClaimType="remoteip" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="recaptchaSuccess" PartnerClaimType="success" /> </OutputClaims> <ValidationClaimsTransformations> <ValidationClaimsTransformation ReferenceId="AssertRecaptchaSuccessIsTrue" /> </ValidationClaimsTransformations> <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" /> </TechnicalProfile> <!-- 添加断言验证转换 --> <ClaimsTransformation Id="AssertRecaptchaSuccessIsTrue" TransformationMethod="AssertBooleanClaimIsEqualToValue"> <InputClaims> <InputClaim ClaimTypeReferenceId="recaptchaSuccess" TransformationClaimType="inputClaim" /> </InputClaims> <InputParameters> <InputParameter Id="valueToCompareTo" DataType="boolean" Value="true" /> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="recaptchaSuccess" /> </OutputClaims> <OutputClaimsTransformations> <OutputClaimsTransformation ReferenceId="CreateRecaptchaFailureError" /> </OutputClaimsTransformations> </ClaimsTransformation> <ClaimsTransformation Id="CreateRecaptchaFailureError" TransformationMethod="CreateStringClaim"> <InputParameters> <InputParameter Id="value" DataType="string" Value="人机验证失败,请重试" /> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="errorMessage" TransformationClaimType="createdClaim" /> </OutputClaims> </ClaimsTransformation>
关键注意事项
- 确保Google reCaptcha控制台已将你的B2C自定义域名添加到授权域名列表。
- 统一登录页不会自动渲染未在B2C预定义字段中的控件,必须手动添加并通过JS绑定声明值。
- 验证失败时,需通过ClaimsTransformation抛出友好错误提示,避免用户看到原始API错误。
内容的提问来源于stack exchange,提问作者Patrice Cote
相关产品推荐
相关产品推荐

