You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AD B2C自定义策略:登录失败时如何递增失败尝试次数?

关于AD B2C自定义策略实现登录失败次数追踪与永久锁定的问题

需求与现状

  • 核心需求:用户登录失败次数达到X次后永久锁定账号;失败次数低于X时,保留AD B2C原生智能锁定功能
  • 已完成配置:创建自定义声明extension_attempt记录登录尝试次数,可在登录成功时递增该值并保存,也能实现用户锁定,但无法在登录失败时触发次数递增逻辑

现有配置片段

编排步骤

<!-- Increment attempt-->
<OrchestrationStep Order="5" Type="ClaimsExchange">
    <ClaimsExchanges>
        <ClaimsExchange Id="OSIncrementAttempt" TechnicalProfileReferenceId="TPIncrementAttempt"/>
    </ClaimsExchanges>
</OrchestrationStep>

<!-- Save attempt-->
<OrchestrationStep Order="6" Type="ClaimsExchange">
    <ClaimsExchanges>
       <ClaimsExchange Id="OSSaveAttempt" TechnicalProfileReferenceId="TPISaveAttempt"/>
    </ClaimsExchanges>
</OrchestrationStep>

技术配置文件

<TechnicalProfile id="TPIncrementAttempt">
    <Metadata>
        <Item Key="Operation">Read</Item>
        <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
    </Metadata>
    <IncludeInSso>false</IncludeInSso>
    <InputClaims>
        <InputClaim ClaimTypeReferenceId="objectId" Required="true"/>
    </InputClaims>
    <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="extension_attempt" DefaultValue="1"/>
    </OutputClaims>
    <OutputClaimsTransformations>
        <OutputClaimsTransformation ReferenceId="IncrementAttempt"/>
    </OutputClaimsTransformations>
    <IncludeTechnicalProfile ReferenceId="AAD-Comon"/>
</TechnicalProfile>

<TechnicalProfile id="TPISaveAttempt">
    <Metadata>
        <Item Key="Operation">Write</Item>
        <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">false</Item>
        <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
    </Metadata>
    <IncludeInSso>false</IncludeInSso>
    <InputClaims>
        <InputClaim ClaimTypeReferenceId="objectId" Required="true"/>
    </InputClaims>
    <PersistedClaims>
        <PersistedClaim ClaimTypeReferenceId="objectId"/>
        <PersistedClaim ClaimTypeReferenceId="extension_attempt"/>
    </PersistedClaims>
    <IncludeTechnicalProfile ReferenceId="AAD-Comon"/>
</TechnicalProfile>

补充配置问题

修改SelfAsserted-LocalAccountSignin-Email时,添加AAD-UserReadUsingEmailAddress后配置失败,尝试同步signInName与email声明仍未解决:

<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email">
  <Metadata>
    <Item Key="setting.forgotPasswordLinkOverride">ForgotPasswordExchange</Item>
  </Metadata>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="signInName" Required="true"  />
    <OutputClaim ClaimTypeReferenceId="password" Required="true" />
    <OutputClaim ClaimTypeReferenceId="objectId" />
    <OutputClaim ClaimTypeReferenceId="authenticationSource" />
  </OutputClaims>
  <ValidationTechnicalProfiles>
    <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress" />
    <ValidationTechnicalProfile ReferenceId="login-NonInteractive" /> 
  </ValidationTechnicalProfiles>
</TechnicalProfile>

解决方案

1. 修复AAD-UserReadUsingEmailAddress配置问题

添加声明转换,将signInName的值复制到email声明(该技术配置文件需要email作为输入):

<ClaimsTransformation Id="CopySignInNameToEmail" TransformationMethod="CopyClaim">
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="signInName" TransformationClaimType="sourceClaim" />
  </InputClaims>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="email" TransformationClaimType="targetClaim" />
  </OutputClaims>
</ClaimsTransformation>

修改登录技术配置文件,在验证环节添加该转换:

<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email">
  <!-- 原有Metadata和OutputClaims保持不变 -->
  <ValidationTechnicalProfiles>
    <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress">
      <OutputClaimsTransformations>
        <OutputClaimsTransformation ReferenceId="CopySignInNameToEmail" />
      </OutputClaimsTransformations>
    </ValidationTechnicalProfile>
    <ValidationTechnicalProfile ReferenceId="login-NonInteractive">
      <!-- 添加错误处理,捕获登录失败事件 -->
      <ErrorTechnicalProfile ReferenceId="TPHandleLoginFailure" />
    </ValidationTechnicalProfile> 
  </ValidationTechnicalProfiles>
</TechnicalProfile>

2. 创建登录失败处理技术配置文件

捕获登录失败错误,执行次数递增与保存逻辑:

<TechnicalProfile Id="TPHandleLoginFailure">
  <Metadata>
    <Item Key="IncludeClaimResolvingInClaimsHandling">true</Item>
  </Metadata>
  <IncludeInSso>false</IncludeInSso>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="email" />
  </InputClaims>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="objectId" />
    <OutputClaim ClaimTypeReferenceId="extension_attempt" DefaultValue="0" />
  </OutputClaims>
  <OutputClaimsTransformations>
    <OutputClaimsTransformation ReferenceId="IncrementAttempt" />
  </OutputClaimsTransformations>
  <ValidationTechnicalProfiles>
    <!-- 读取用户当前尝试次数 -->
    <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress" />
    <!-- 保存递增后的次数 -->
    <ValidationTechnicalProfile ReferenceId="TPISaveAttempt" />
    <!-- 检查是否达到锁定阈值,达到则锁定用户 -->
    <ValidationTechnicalProfile ReferenceId="TPCheckAndLockUser">
      <Preconditions>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
          <Value>lockUser</Value>
          <Value>true</Value>
          <Action>SkipThisValidationTechnicalProfile</Action>
        </Precondition>
      </Preconditions>
    </ValidationTechnicalProfile>
  </ValidationTechnicalProfiles>
  <!-- 不干扰正常会话,重新抛出登录失败错误 -->
  <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>

3. 添加阈值检查与用户锁定逻辑

阈值判断声明转换(X设为5,可自行修改)

<ClaimsTransformation Id="CheckAttemptThreshold" TransformationMethod="CompareIntegerClaim">
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="extension_attempt" TransformationClaimType="inputClaim1" />
  </InputClaims>
  <InputParameters>
    <InputParameter Id="compareTo" DataType="int" Value="5" />
    <InputParameter Id="operator" DataType="string" Value="greater than or equal" />
    <InputParameter Id="outputClaimIfTrue" DataType="string" Value="true" />
  </InputParameters>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="lockUser" TransformationClaimType="outputClaim" />
  </OutputClaims>
</ClaimsTransformation>

用户锁定技术配置文件

<TechnicalProfile Id="TPCheckAndLockUser">
  <Metadata>
    <Item Key="Operation">Write</Item>
    <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
  </Metadata>
  <IncludeInSso>false</IncludeInSso>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="objectId" Required="true" />
  </InputClaims>
  <OutputClaimsTransformations>
    <OutputClaimsTransformation ReferenceId="CheckAttemptThreshold" />
  </OutputClaimsTransformations>
  <PersistedClaims>
    <PersistedClaim ClaimTypeReferenceId="objectId" />
    <PersistedClaim ClaimTypeReferenceId="accountEnabled" DefaultValue="false" />
  </PersistedClaims>
  <IncludeTechnicalProfile ReferenceId="AAD-Common" />
</TechnicalProfile>

4. 调整登录成功时的次数逻辑

登录成功时应重置尝试次数为0,修改TPIncrementAttempt的声明转换:

<ClaimsTransformation Id="ResetAttempt" TransformationMethod="SetClaimValue">
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="extension_attempt" />
  </InputClaims>
  <InputParameters>
    <InputParameter Id="value" DataType="int" Value="0" />
  </InputParameters>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="extension_attempt" />
  </OutputClaims>
</ClaimsTransformation>

同步修改TPIncrementAttempt的输出转换:

<OutputClaimsTransformations>
  <OutputClaimsTransformation ReferenceId="ResetAttempt"/>
</OutputClaimsTransformations>

内容的提问来源于stack exchange,提问作者Uxia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 07:34:52