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
相关产品推荐
相关产品推荐

