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

如何修改Azure AD B2C用户名登录自定义策略以支持邮箱登录

问题根因

该现象由登录标识存储位置和匹配逻辑不匹配导致:

  • 你引用的用户名注册登录示例策略,默认仅将用户名以signInNames.userName类型存入用户身份集合,注册时用于验证的邮箱不会写入可用于登录的身份条目
  • Azure AD B2C默认邮箱登录逻辑仅匹配signInNames.emailAddress类型的身份记录,无法识别仅绑定了用户名登录标识的账号
  • 原示例的登录校验逻辑仅检索用户名类型的登录标识,不会匹配邮箱条目,因此不支持邮箱输入登录
配置修改方案

仅需两处核心修改即可实现用户名+注册邮箱双登录模式:

  1. 注册流程持久化用户数据时,将验证通过的邮箱额外写入signInNames.emailAddress身份条目,为账号绑定两个可登录标识
  2. 登录流程的校验逻辑调整为自动识别用户输入内容类型,同时匹配用户名、邮箱两类登录标识

1. 注册流程持久化配置修改

打开策略扩展文件TrustFrameworkExtensions.xml,找到ID为AAD-UserWriteUsingLogonName的技术配置文件,在<PersistedClaims>节点下新增邮箱标识写入规则:

<TechnicalProfile Id="AAD-UserWriteUsingLogonName">
  <Metadata>
    <Item Key="Operation">Write</Item>
    <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item>
  </Metadata>
  <IncludeInSso>false</IncludeInSso>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.userName" Required="true"/>
  </InputClaims>
  <PersistedClaims>
    <PersistedClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.userName" Required="true"/>
    <!-- 新增以下规则:将注册验证通过的邮箱写入可登录身份集合 -->
    <PersistedClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" Required="true"/>
    <!-- 原有其他持久化声明(displayName、password、givenName、surname等)保持不变,不要删除 -->
  </PersistedClaims>
  <OutputClaims>
    <!-- 原有输出声明保持不变 -->
  </OutputClaims>
  <IncludeTechnicalProfile ReferenceId="AAD-Common"/>
</TechnicalProfile>

2. 登录流程校验逻辑修改

在同个TrustFrameworkExtensions.xml文件中,先新增邮箱格式判断的声明转换,再调整登录页的校验逻辑:

<!-- 新增:判断用户输入是否为邮箱格式的声明转换 -->
<ClaimsTransformation Id="DetectSigninIdentifierType" TransformationMethod="IsEmail">
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="signInName" TransformationClaimType="inputClaim"/>
  </InputClaims>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="isEmailInput" TransformationClaimType="outputClaim"/>
  </OutputClaims>
</ClaimsTransformation>

<!-- 修改原有用户名登录自断言配置 -->
<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Username">
  <DisplayName>Local Account Signin</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  <Metadata>
    <Item Key="setting.operatingMode">Username</Item>
    <Item Key="ContentDefinitionReferenceId">api.localaccountsignin</Item>
    <Item Key="setting.forgotPasswordLinkLocation">footer</Item>
    <!-- 修改登录提示文案,告知用户支持用户名/邮箱两种输入 -->
    <Item Key="UserMessageIfClaimsPrincipalDoesNotExist">输入的用户名或邮箱不存在,请检查后重试</Item>
    <Item Key="UserMessageIfInvalidPassword">密码错误,请重试</Item>
  </Metadata>
  <InputClaimsTransformations>
    <!-- 登录校验前先判断输入类型 -->
    <InputClaimsTransformation ReferenceId="DetectSigninIdentifierType"/>
  </InputClaimsTransformations>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="signInName" Required="true"/>
    <OutputClaim ClaimTypeReferenceId="password" Required="true"/>
    <OutputClaim ClaimTypeReferenceId="rememberMe" DefaultValue="false" AlwaysUseDefaultValue="true"/>
    <OutputClaim ClaimTypeReferenceId="isEmailInput" />
  </OutputClaims>
  <ValidationTechnicalProfiles>
    <ValidationTechnicalProfile ReferenceId="AAD-UserReadBySigninIdentifier"/>
    <ValidationTechnicalProfile ReferenceId="login-NonInteractive"/>
  </ValidationTechnicalProfiles>
  <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD"/>
</TechnicalProfile>

<!-- 新增:自动匹配用户名/邮箱的用户读取配置 -->
<TechnicalProfile Id="AAD-UserReadBySigninIdentifier">
  <Metadata>
    <Item Key="Operation">Read</Item>
    <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
  </Metadata>
  <InputClaims>
    <!-- 输入为邮箱时匹配email标识,否则匹配用户名标识 -->
    <InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.emailAddress" Required="true" PreconditionType="ClaimEquals" PreconditionClaim="isEmailInput=True"/>
    <InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.userName" Required="true" PreconditionType="ClaimEquals" PreconditionClaim="isEmailInput=False"/>
  </InputClaims>
  <OutputClaims>
    <!-- 原有输出声明保持不变,比如objectId、displayName、signInName、email等 -->
  </OutputClaims>
  <IncludeTechnicalProfile ReferenceId="AAD-Common"/>
</TechnicalProfile>

注意事项
  • 代码中所有占位的客户端ID、租户ID等配置,请替换为你环境中实际的部署值,敏感信息自行替换即可
  • 新注册用户会自动绑定用户名、邮箱双登录标识,直接支持两种方式登录
  • 策略上线前创建的存量账号,需要通过Graph API补写signInNames.emailAddress属性后,才能使用邮箱登录
  • 配置上传后先使用测试账号验证:分别用用户名+密码、邮箱+密码尝试登录,确认两类方式都可正常鉴权

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:16:01