你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
重要
自 2025 年 5 月 1 日起,Azure AD B2C 将不再可供新客户购买。 在我们的常见问题解答中了解详细信息。
Azure Active Directory B2C(Azure AD B2C) 基于 Microsoft Entra ID 构建,因此它使用 Microsoft Entra ID 存储来存储用户帐户。 Azure AD B2C 目录用户配置文件附带一组内置属性,例如名字、姓氏、市/县、邮政编码和电话号码,但你可以使用自己的自定义属性扩展用户配置文件,而无需使用外部数据存储。
自定义策略可以使用 Microsoft Entra ID 技术配置文件来存储、更新或删除用户信息,从而连接到 Microsoft Entra ID 存储。 本文介绍如何在返回 JWT 之前配置一组Microsoft Entra ID 技术配置文件来存储和读取用户帐户。
场景概述
在使用 Azure Active Directory B2C 自定义策略调用 REST API 一文中,我们收集了用户的信息、验证了数据、调用了 REST API,最后返回了 JWT,但是没有存储用户帐户。 我们必须存储用户信息,以便在策略完成执行后不会丢失信息。 这一次,收集用户信息并对其进行验证后,我们需要将用户信息存储在 Azure AD B2C 存储中,然后在返回 JWT 之前读取。 下图显示了此完整过程。
先决条件
如果您还没有 Azure AD B2C 租户,请创建一个链接到您的 Azure 订阅的 Azure AD B2C 租户。
必须在计算机上安装 Visual Studio Code (VS Code)。
完成《使用 Azure Active Directory B2C 自定义策略调用 REST API》中的步骤。 本文是《创建和运行自己的自定义策略操作指南系列教程》的一部分。
注释
本文是《在 Azure Active Directory B2C 中创建和运行自己的自定义策略操作指南系列教程》的一部分。 建议从第一篇文章开始本系列教程。
步骤 1 - 发布声明
需要声明另外两个声明:userPrincipalName
和 passwordPolicies
:
在
ContosoCustomPolicy.XML
文件中,找到 ClaimsSchema 元素并使用以下代码声明userPrincipalName
和passwordPolicies
声明:<ClaimType Id="userPrincipalName"> <DisplayName>UserPrincipalName</DisplayName> <DataType>string</DataType> <UserHelpText>Your user name as stored in the Azure Active Directory.</UserHelpText> </ClaimType> <ClaimType Id="passwordPolicies"> <DisplayName>Password Policies</DisplayName> <DataType>string</DataType> <UserHelpText>Password policies used by Azure AD to determine password strength, expiry etc.</UserHelpText> </ClaimType>
步骤 2 - 创建 Microsoft Entra ID 技术配置文件
需要配置两个 Microsoft Entra ID 技术配置文件。 一个技术档案将用户详细信息写入 Microsoft Entra ID 存储,另一个技术档案从 Microsoft Entra ID 存储读取用户帐户。
在
ContosoCustomPolicy.XML
文件中,找到 ClaimsProviders 元素,然后使用以下代码添加新的声明提供程序。 此声明提供程序会保存 Microsoft Entra ID 技术配置文件:<ClaimsProvider> <DisplayName>Azure AD Technical Profiles</DisplayName> <TechnicalProfiles> <!--You'll add you Azure AD Technical Profiles here--> </TechnicalProfiles> </ClaimsProvider>
在刚刚创建的声明提供程序中,使用以下代码添加 Microsoft Entra ID 技术配置文件:
<TechnicalProfile Id="AAD-UserWrite"> <DisplayName>Write user information to AAD</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.AzureActiveDirectoryProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="Operation">Write</Item> <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item> <Item Key="UserMessageIfClaimsPrincipalAlreadyExists">The account already exists. Try to create another account</Item> </Metadata> <InputClaims> <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" Required="true" /> </InputClaims> <PersistedClaims> <PersistedClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" /> <PersistedClaim ClaimTypeReferenceId="displayName" /> <PersistedClaim ClaimTypeReferenceId="givenName" /> <PersistedClaim ClaimTypeReferenceId="surname" /> <PersistedClaim ClaimTypeReferenceId="password"/> <PersistedClaim ClaimTypeReferenceId="passwordPolicies" DefaultValue="DisablePasswordExpiration,DisableStrongPassword" /> </PersistedClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" /> <OutputClaim ClaimTypeReferenceId="userPrincipalName" /> <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" /> </OutputClaims> </TechnicalProfile>
我们添加了新的 Microsoft Entra ID 技术配置文件
AAD-UserWrite
。 您需要注意技术概况的以下几个重要部分:操作:操作指定要执行的操作,在本例中为写入。 详细了解 Microsoft Entra ID 技术提供程序中的其他操作。
持久化声明:PersistedClaims 元素包含应存储在 Microsoft Entra ID 存储中的所有值。
InputClaims:InputClaims 元素包含一个声明,用于在目录中查找帐户,或创建一个新帐户。 所有 Microsoft Entra ID 技术配置文件的输入声明集合中必须有且只有一个输入声明元素。 此技术配置文件使用电子邮件声明作为用户帐户的密钥标识符。 详细了解可用于唯一标识用户帐户的其他密钥标识符。
在
ContosoCustomPolicy.XML
文件中,找到AAD-UserWrite
技术配置文件,然后使用以下代码在其后面添加一个新的技术配置文件:<TechnicalProfile Id="AAD-UserRead"> <DisplayName>Read user from Azure AD storage</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.AzureActiveDirectoryProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="Operation">Read</Item> <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">false</Item> <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">false</Item> </Metadata> <InputClaims> <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" Required="true" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" /> <OutputClaim ClaimTypeReferenceId="userPrincipalName" /> <OutputClaim ClaimTypeReferenceId="givenName"/> <OutputClaim ClaimTypeReferenceId="surname"/> <OutputClaim ClaimTypeReferenceId="displayName"/> </OutputClaims> </TechnicalProfile>
我们添加了新的 Microsoft Entra ID 技术配置文件
AAD-UserRead
。 我们已将此技术配置文件配置为执行读取操作,如果找到了在objectId
部分包含userPrincipalName
的用户帐户,则返回givenName
、surname
、displayName
、email
和InputClaim
声明。
步骤 3 - 使用 Microsoft Entra ID 技术配置文件
使用 UserInformationCollector
自断言技术配置文件收集用户详细信息后,需要使用 AAD-UserWrite
技术配置文件将用户帐户写入 Microsoft Entra ID 存储。 为此,请使用 AAD-UserWrite
技术配置文件作为 UserInformationCollector
自断言技术配置文件中的验证技术配置文件。
在 ContosoCustomPolicy.XML
文件中,找到 UserInformationCollector
技术配置文件,然后将 AAD-UserWrite
技术配置文件添加为 ValidationTechnicalProfiles
集合中的验证技术配置文件。 需要在 CheckCompanyDomain
验证技术配置文件之后添加此文件。
我们将在用户旅程编排步骤中使用 AAD-UserRead
技术配置文件,以在发出 JWT 之前读取用户详细信息。
步骤 4 - 更新 ClaimGenerator 技术配置文件
我们使用 ClaimGenerator
技术配置文件执行三个声明转换:GenerateRandomObjectIdTransformation、CreateDisplayNameTransformation 和 CreateMessageTransformation。
在
ContosoCustomPolicy.XML
文件中,找到ClaimGenerator
技术配置文件并将其替换为以下代码:<TechnicalProfile Id="UserInputMessageClaimGenerator"> <DisplayName>User Message Claim Generator Technical Profile</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <OutputClaims> <OutputClaim ClaimTypeReferenceId="message" /> </OutputClaims> <OutputClaimsTransformations> <OutputClaimsTransformation ReferenceId="CreateMessageTransformation" /> </OutputClaimsTransformations> </TechnicalProfile> <TechnicalProfile Id="UserInputDisplayNameGenerator"> <DisplayName>Display Name Claim Generator Technical Profile</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <OutputClaims> <OutputClaim ClaimTypeReferenceId="displayName" /> </OutputClaims> <OutputClaimsTransformations> <OutputClaimsTransformation ReferenceId="CreateDisplayNameTransformation" /> </OutputClaimsTransformations> </TechnicalProfile>
我们已将该技术配置文件拆分为两个独立的技术配置文件。 UserInputMessageClaimGenerator 技术配置文件生成在 JWT 中作为声明发送的消息。 UserInputDisplayNameGenerator 技术配置文件生成
displayName
声明。 在displayName
技术配置文件将用户记录写入 Microsoft Entra ID 存储之前,AAD-UserWrite
声明值必须可用。 在新代码中,我们将删除 GenerateRandomObjectIdTransformation,因为创建帐户后由 Microsoft Entra ID 创建并返回objectId
,因此无需在策略中自行生成它。在
ContosoCustomPolicy.XML
文件中,找到UserInformationCollector
自断言技术配置文件,然后将UserInputDisplayNameGenerator
技术配置文件添加为验证技术配置文件。 执行此操作后,UserInformationCollector
技术配置文件的ValidationTechnicalProfiles
集合外观应类似于以下代码:<!--<TechnicalProfile Id="UserInformationCollector">--> <ValidationTechnicalProfiles> <ValidationTechnicalProfile ReferenceId="CheckCompanyDomain"> <Preconditions> <Precondition Type="ClaimEquals" ExecuteActionsIf="false"> <Value>accountType</Value> <Value>work</Value> <Action>SkipThisValidationTechnicalProfile</Action> </Precondition> </Preconditions> </ValidationTechnicalProfile> <ValidationTechnicalProfile ReferenceId="UserInputDisplayNameGenerator"/> <ValidationTechnicalProfile ReferenceId="AAD-UserWrite"/> </ValidationTechnicalProfiles> <!--</TechnicalProfile>-->
必须在
AAD-UserWrite
之前添加验证技术配置文件,因为在displayName
技术配置文件将用户记录写入 Microsoft Entra ID 存储之前,AAD-UserWrite
声明值必须可用。
步骤 5 - 更新用户旅程编排步骤
找到你的 HelloWorldJourney
用户旅程,并将所有业务流程步骤替换为以下代码:
<!--<OrchestrationSteps>-->
<OrchestrationStep Order="1" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AccountTypeInputCollectorClaimsExchange" TechnicalProfileReferenceId="AccountTypeInputCollector"/>
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="GetAccessCodeClaimsExchange" TechnicalProfileReferenceId="AccessCodeInputCollector" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="3" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="GetUserInformationClaimsExchange" TechnicalProfileReferenceId="UserInformationCollector"/>
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="4" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AADUserReaderExchange" TechnicalProfileReferenceId="AAD-UserRead"/>
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="5" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="GetMessageClaimsExchange" TechnicalProfileReferenceId="UserInputMessageClaimGenerator"/>
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="6" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer"/>
<!--</OrchestrationSteps>-->
在业务流程步骤 4
中,执行 AAD-UserRead
技术配置文件,从创建的用户帐户读取用户详细信息(要包含在 JWT 中)。
由于我们不存储 message
声明,因此在业务流程步骤 5
中,我们将执行 UserInputMessageClaimGenerator
生成 message
声明以包含在 JWT 上。
步骤 6 - 上传策略
按照上传自定义策略文件中的步骤上传策略文件。 如果您上传的文件与门户中已存在的文件同名,请确保选择“覆盖自定义策略(如果它已存在)”。
步骤 7 - 测试策略
按照测试自定义策略中的步骤测试自定义策略。
在策略完成执行并收到 ID 令牌后,检查是否已创建用户记录:
登录到 Azure 门户。
如果有权访问多个租户,请选择顶部菜单中的“设置”图标,从“目录 + 订阅”菜单切换到你的 Azure AD B2C 租户。
在“Azure 服务”下,选择“Azure AD B2C”。 或者,使用搜索框查找并选择“Azure AD B2C”。
在“管理”下,选择“用户” 。
找到刚刚创建的用户帐户,并将其选中。 帐户配置文件外观类似于下面的屏幕截图:
在我们的 AAD-UserWrite
Microsoft Entra ID 技术配置文件中,我们指定如果用户已存在,则将引发错误消息。
使用相同的电子邮件地址再次测试自定义策略。 你应会看到如以下屏幕截图所示的错误消息,而不是策略执行完成以颁发 ID 令牌。
注释
密码声明值是一条非常重要的信息,因此在自定义策略中处理该信息时务必谨慎操作。 出于类似的原因,Azure AD B2C 将密码声明值视为特殊值。 在自断言技术配置文件中收集密码声明值时,该值仅在同一技术配置文件中,或由同一自断言技术配置文件引用的验证技术配置文件中可用。 执行完该自我断言技术配置文件并转移动到另一个技术配置文件后,该值会丢失。
验证用户电子邮件地址
建议先验证用户的电子邮件,然后再使用它来创建用户帐户。 验证电子邮件地址时,请确保帐户是由真实用户创建的。 你还可以帮助用户确保他们使用正确的电子邮件地址创建帐户。
Azure AD B2C 的自定义策略提供了一种使用验证显示控件来验证电子邮件地址的方法。 向电子邮件发送验证码。 发送代码后,用户将阅读消息、将验证码输入到显示控件提供的控件中,然后选择“验证代码”按钮。
显示控件是一个具有特殊功能的用户界面元素,可以与 Azure Active Directory B2C (Azure AD B2C) 后端服务进行交互。 它允许用户在页面上执行某些操作,这些操作在后端调用验证技术配置文件。 显示控件显示在页面上,由自断言技术配置文件引用。
要使用显示控件添加电子邮件验证,请使用以下步骤:
发布声明
需要声明一个用于保存验证代码的声明。
要发布声明,请在 ContosoCustomPolicy.XML
文件中找到 ClaimsSchema
元素,并使用以下代码声明 verificationCode
声明:
<!--<ClaimsSchema>-->
...
<ClaimType Id="verificationCode">
<DisplayName>Verification Code</DisplayName>
<DataType>string</DataType>
<UserHelpText>Enter your verification code</UserHelpText>
<UserInputType>TextBox</UserInputType>
</ClaimType>
<!--</ClaimsSchema>-->
配置发送和验证代码技术配置文件
Azure AD B2C 使用 Microsoft Entra ID SSPR 技术配置文件来验证电子邮件地址。 根据配置方式,此技术配置文件可以生成代码并将其发送到电子邮件地址或验证代码。
在 ContosoCustomPolicy.XML
文件中,找到 ClaimsProviders
元素,然后使用以下代码添加声明提供程序:
<ClaimsProvider>
<DisplayName>Azure AD self-service password reset (SSPR)</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="AadSspr-SendCode">
<DisplayName>Send Code</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.AadSsprProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="Operation">SendCode</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" PartnerClaimType="emailAddress" />
</InputClaims>
</TechnicalProfile>
<TechnicalProfile Id="AadSspr-VerifyCode">
<DisplayName>Verify Code</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.AadSsprProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="Operation">VerifyCode</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="verificationCode" />
<InputClaim ClaimTypeReferenceId="email" PartnerClaimType="emailAddress" />
</InputClaims>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
我们配置了两个技术配置文件:AadSspr-SendCode
和 AadSspr-VerifyCode
。 AadSspr-SendCode
会生成代码并将其发送到 InputClaims
部分中指定的电子邮件地址,而 AadSspr-VerifyCode
会验证代码。 您在技术概况的元数据中指定要执行的操作。
配置显示控件
需要配置电子邮件验证显示控件才能验证用户电子邮件。 配置的电子邮件验证显示控件将取代用于从用户收集电子邮件的电子邮件显示声明。
要配置显示控件,请使用以下步骤:
在
ContosoCustomPolicy.XML
文件中,找到BuildingBlocks
部分,然后使用以下代码将显示控件添加为子元素:<!--<BuildingBlocks>--> .... <DisplayControls> <DisplayControl Id="emailVerificationControl" UserInterfaceControlType="VerificationControl"> <DisplayClaims> <DisplayClaim ClaimTypeReferenceId="email" Required="true" /> <DisplayClaim ClaimTypeReferenceId="verificationCode" ControlClaimType="VerificationCode" Required="true" /> </DisplayClaims> <OutputClaims></OutputClaims> <Actions> <Action Id="SendCode"> <ValidationClaimsExchange> <ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="AadSspr-SendCode" /> </ValidationClaimsExchange> </Action> <Action Id="VerifyCode"> <ValidationClaimsExchange> <ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="AadSspr-VerifyCode" /> </ValidationClaimsExchange> </Action> </Actions> </DisplayControl> </DisplayControls> <!--</BuildingBlocks>-->
我们已声明显示控件
emailVerificationControl
。 请注意以下重要部分:DisplayClaims - 与自断言技术配置文件类似,此部分指定要在显示控件中从用户收集的声明集合。
操作 - 指定要由显示控件执行的操作顺序。 每个操作将引用负责执行操作的技术配置文件。 例如,SendCode 引用
AadSspr-SendCode
技术配置文件,该配置文件会生成代码并将其发送到电子邮件地址。
在
ContosoCustomPolicy.XML
文件中,找到UserInformationCollector
自断言技术配置文件,并将电子邮件显示声明替换为 显示控件emailVerificationControl
:发件人:
<DisplayClaim ClaimTypeReferenceId="email" Required="true"/>
更改为:
<DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
使用 Microsoft Entra ID 技术配置文件更新用户帐户
可以将 Microsoft Entra ID 技术配置文件配置为更新用户帐户,而不是尝试创建新帐户。 为此,请使用以下代码设置 Microsoft Entra ID 技术配置文件,以便在元数据集合中尚不存在指定用户帐户时引发错误。 此外,请删除 Key="UserMessageIfClaimsPrincipalAlreadyExists
元数据条目。 需要将“操作”设置为“写入”:
<Item Key="Operation">Write</Item>
<Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">false</Item>
使用自定义属性
在本文中,你已了解了如何使用内置用户配置文件属性存储用户详细信息。 但你通常需要创建自己的自定义属性来管理特定方案。 为此,请按照《在 Azure Active Directory B2C 中定义自定义属性》一文中的说明进行操作。