你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用 Azure Active Directory B2C 配置传输安全性,以防止欺诈

重要

自 2025 年 5 月 1 日起,Azure AD B2C 将不再可供新客户购买。 在我们的常见问题解答中了解详细信息

本教程介绍如何将 Azure Active Directory B2C (Azure AD B2C) 身份验证与 传输安全性的检测和响应服务(DRS)集成。 Transmit Security 允许您检测数字渠道上客户互动中的风险,并在整个消费者体验中做出知情的身份和信任决策。

此功能仅适用于自定义策略。 对于设置步骤,请在前面的选择器中选择“自定义策略”

方案说明

传输检测和响应集成包括以下组件:

  • Azure AD B2C 租户:对用户进行身份验证,并托管在用户执行目标策略时收集设备信息的脚本。 它根据 Transmit 返回的风险建议,阻止或质询登录/注册尝试。
  • 自定义 UI 模板:自定义 Azure AD B2C 呈现的页面的 HTML 内容。 这些页面包括传输风险检测所需的 JavaScript 代码片段。
  • 传输数据收集服务:动态嵌入的脚本,用于记录设备信息,用于在用户交互期间持续评估风险。
  • 传输 DRS API 终结点:根据收集的数据提供风险建议。 Azure AD B2C 使用 REST API 连接器与此终结点通信。
  • Azure Functions:托管的 API 终结点,用于通过 API 连接器从 Transmit DRS API 终结点获取建议。

以下体系结构关系图说明了本指南中所述的实现:

Transmit 和 Azure AD B2C 体系结构的关系图。

  1. 用户使用 Azure AD B2C 登录。
  2. 自定义页面初始化 Transmit SDK,该 SDK 开始将设备信息流式传输到 Transmit 服务。
  3. Azure AD B2C 报告登录操作事件给 Transmit,以获取操作令牌。
  4. Transmit 会返回作令牌,Azure AD B2C 会继续用户注册或登录。
  5. 用户登录后,Azure AD B2C 会通过 Azure 函数向 Transmit 请求风险建议。
  6. Azure 函数向 Transmit 发送带有动作令牌的建议请求。
  7. Transmit 会根据收集的设备信息返回建议(质询/允许/拒绝)。
  8. Azure 函数将建议结果传递给 Azure AD B2C,以便相应地处理。
  9. 如果需要,Azure AD B2C 会执行更多步骤,例如多重身份验证并完成注册或登录流。

先决条件

步骤 1:创建传输应用

登录到 传输管理门户创建应用程序

  1. “应用程序”中,选择“ 添加应用程序”。

  2. 使用以下属性配置应用程序:

    资产 DESCRIPTION
    应用程序名称 应用程序名称
    客户端名称 客户端名称
    重定向 URI 输入网站 URL。 此属性是必填字段,但不用于此流
  3. 选择 并添加

  4. 注册后,会显示 客户端 ID客户端密码 。 记录值以供以后使用。

步骤 2:创建自定义 UI

首先将 Transmit DRS 集成至 B2C 前端应用程序中。 创建集成 传输 SDK 的自定义登录页,并替换默认的 Azure AD B2C 登录页。

激活后,传输 DRS 将开始收集与应用交互的用户的信息。 Transmit DRS 返回一个 Azure AD B2C 需要用于风险建议的动作令牌。

若要将传输 DRS 集成到 B2C 登录页面,请执行以下步骤:

  1. 根据 示例模板为登录页准备自定义 HTML 文件。 添加以下脚本以加载和初始化 Transmit SDK,并获取操作令牌。 返回的作令牌应存储在隐藏的 HTML 元素中(ts-drs-response 在本示例中)。

    <!-- Function that obtains an action token -->
    <script>
    function fill_token() {
       window.tsPlatform.drs.triggerActionEvent("login").then((actionResponse) => {
          let actionToken = actionResponse.actionToken;
          document.getElementById("ts-drs-response").value = actionToken;
          console.log(actionToken);
       });
    }
    </script>
    
    <!-- Loads DRS SDK -->
    <script src="https://platform-websdk.transmitsecurity.io/platform-websdk/latest/ts-platform-websdk.js" defer> </script>
    
    <!-- Upon page load, initializes DRS SDK and calls the fill_token function -->
    <script defer>
    window.onload = function() {
       if (window.tsPlatform) {
          // Client ID found in the app settings in Transmit Admin portal
          window.tsPlatform.initialize({ clientId: "[clientId]" });
          console.log("Transmit Security platform initialized");
          fill_token();
       } else {/
          console.error("Transmit Security platform failed to load");
       }
    };
    </script>
    
  2. 在 Azure AS B2C 中启用 JavaScript 和页面布局版本

  3. 通过 创建存储帐户添加对 Azure 存储的 CORS 支持,在已启用跨域资源共享(CORS)的 Web 终结点上托管 HTML 页面。

步骤 3:创建 Azure 函数

Azure AD B2C 可以使用 API 连接器从传输中获取风险建议。 通过中间 Web API(例如使用 Azure Functions)传递此请求可提高实现逻辑的灵活性。

按照以下步骤创建一个 Azure 函数,该函数使用前端应用程序提供的操作令牌从 传输 DRS 终结点获取推荐。

  1. 创建 Azure Function 的入口点,一个 HTTP 触发的函数,用于处理传入的 HTTP 请求。

    public static async Task<HttpResponseMessage> Run(HttpRequest req, ILogger log)
    {
        // Function code goes here
    }
    
  2. 从请求中提取动作令牌。 自定义策略定义如何在查询字符串参数或正文中传递请求。

    // Checks for the action token in the query string
    string actionToken = req.Query["actiontoken"];
    
    // Checks for the action token in the request body
    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    actionToken = actionToken ?? data?.actiontoken;
    
  3. 通过验证提供的值不为空且不是 null 来确认操作令牌:

    // Returns an error response if the action token is missing
    if (string.IsNullOrEmpty(actionToken))
       {
           var respContent = new { version = "1.0.0", status = (int)HttpStatusCode.BadRequest, userMessage = "Invalid or missing action token" };
           var json = JsonConvert.SerializeObject(respContent);
           log.LogInformation(json);
           return new HttpResponseMessage(HttpStatusCode.BadRequest)
           {
               Content = new StringContent(json, Encoding.UTF8, "application/json")
           };
       }
    
  4. 调用 Transmit DRS API。 在步骤 1 中获取的传输客户端 ID 和客户端密码应用于生成用于 API 授权的持有者令牌。 请确保在文件中添加必要的环境变量(如 ClientId 和 ClientSecret local.settings.json )。

    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transmitSecurityApiKey}");
    
    // Add code here that sends this GET request:
    // https://api.transmitsecurity.io/risk/v1/recommendation?action_token=[YOUR_ACTION_TOKEN]
    
    HttpResponseMessage response = await client.GetAsync(urlWithActionToken);
    
  5. 处理 API 响应。 如果成功,以下代码将转发 API 响应;否则,处理任何错误。

     if (response.IsSuccessStatusCode)
       {
           log.LogInformation(responseContent);
           return new HttpResponseMessage(HttpStatusCode.OK)
           {
               Content = new StringContent(responseContent, Encoding.UTF8, "application/json")
           };
       }
       else
       {
           var errorContent = new { version = "1.0.0", status = (int)response.StatusCode, userMessage = "Error calling Transmit Security API" };
           var json = JsonConvert.SerializeObject(errorContent);
           log.LogError(json);
           return new HttpResponseMessage(response.StatusCode)
           {
               Content = new StringContent(json, Encoding.UTF8, "application/json")
           };
       }
    

步骤 4:配置自定义策略

通过扩展自定义策略,将 Transmit DRS 集成到 Azure B2C 应用程序中。

  1. 下载 自定义策略初学者包 以开始使用(请参阅 Azure AD B2C 中的自定义策略

  2. 创建继承自 TrustFrameworkExtensions 的新文件,该文件使用特定于租户的自定义来扩展传输 DRS 的基本策略。

    <BasePolicy>
       <TenantId>YOUR AZURE TENANT</TenantId>
       <PolicyId>B2C_1A_TrustFrameworkExtensions</PolicyId>
    </BasePolicy>
    
  3. BuildingBlocks部分,定义actiontokents-drs-responsets-drs-recommendation为声明:

    <BuildingBlocks>
       <ClaimsSchema>
       <ClaimType Id="ts-drs-response">
          <DisplayName>ts-drs-response</DisplayName>
          <DataType>string</DataType>
          <UserHelpText>Parameter provided to the DRS service for the response</UserHelpText>
          <UserInputType>TextBox</UserInputType>
       </ClaimType>
       <ClaimType Id="actiontoken">
          <DisplayName>actiontoken</DisplayName>
          <DataType>string</DataType>
          <UserHelpText />
          <UserInputType>TextBox</UserInputType>
       </ClaimType>
       <ClaimType Id="ts-drs-recommendation">
          <DisplayName>recommendation</DisplayName>
          <DataType>string</DataType>
          <UserHelpText />
          <UserInputType>TextBox</UserInputType>
       </ClaimType>
       </ClaimsSchema>
    <BuildingBlocks>
    
  4. 在本 BuildingBlocks 部分中,添加对自定义 UI 的引用:

    <BuildingBlocks>
       <ClaimsSchema>
       <!-- your claim schemas-->
       </ClaimsSchema>
    
       <ContentDefinitions>
       <ContentDefinition Id="api.selfasserted">
       <!-- URL of your hosted custom HTML file-->
          <LoadUri>YOUR_SIGNIN_PAGE_URL</LoadUri>
       </ContentDefinition>
       </ContentDefinitions>
    </BuildingBlocks>
    
  5. ClaimsProviders 部分中,配置一个声明提供程序,其中包含以下技术配置文件:一个(SelfAsserted-LocalAccountSignin-Email)用于输出操作令牌,另一个(在本示例中为 login-DRSCheck 的 Azure 函数)用于接收操作令牌作为输入并输出风险建议。

    <ClaimsProviders>
       <ClaimsProvider>
       <DisplayName>Sign in using DRS</DisplayName>
       <TechnicalProfiles>
          <TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email">
             <DisplayName>Local Account Sign-in</DisplayName>
             <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
             <Metadata>
             <Item Key="SignUpTarget">SignUpWithLogonEmailExchange</Item>
             <Item Key="setting.operatingMode">Email</Item>
             <Item Key="setting.showSignupLink">true</Item>
             <Item Key="setting.showCancelButton">false</Item>
             <Item Key="ContentDefinitionReferenceId">api.selfasserted</Item>
             <Item Key="language.button_continue">Sign In</Item>
             </Metadata>
             <IncludeInSso>false</IncludeInSso>
             <InputClaims>
             <InputClaim ClaimTypeReferenceId="signInName" />
             </InputClaims>
             <OutputClaims>
             <OutputClaim ClaimTypeReferenceId="signInName" Required="true" />
             <OutputClaim ClaimTypeReferenceId="password" Required="true" />
             <OutputClaim ClaimTypeReferenceId="objectId" />
             <OutputClaim ClaimTypeReferenceId="authenticationSource" />
             <!-- Outputs the action token value provided by the frontend-->
             <OutputClaim ClaimTypeReferenceId="ts-drs-response" />
             </OutputClaims>
             <ValidationTechnicalProfiles>
             <ValidationTechnicalProfile ReferenceId="login-DRSCheck" />
             <ValidationTechnicalProfile ReferenceId="login-NonInteractive" />
             </ValidationTechnicalProfiles>
          </TechnicalProfile>
          <TechnicalProfile Id="login-DRSCheck">
             <DisplayName>DRS check to validate the interaction and device </DisplayName>
             <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
             <Metadata>
             <!-- Azure Function App -->
             <Item Key="ServiceUrl">YOUR_FUNCTION_URL</Item>
             <Item Key="AuthenticationType">None</Item>
             <Item Key="SendClaimsIn">Body</Item>
             <!-- JSON, Form, Header, and Query String formats supported -->
             <Item Key="ClaimsFormat">Body</Item>
             <!-- Defines format to expect claims returning to B2C -->
             <!-- REMOVE the following line in production environments -->
             <Item Key="AllowInsecureAuthInProduction">true</Item>
             </Metadata>
             <InputClaims>
             <!-- Receives the action token value as input -->
             <InputClaim ClaimTypeReferenceId="ts-drs-response" PartnerClaimType="actiontoken" DefaultValue="0" />
             </InputClaims>
             <OutputClaims>
             <!-- Outputs the risk recommendation value returned by Transmit (via the Azure function) -->
             <OutputClaim ClaimTypeReferenceId="ts-drs-recommendation" PartnerClaimType="recommendation.type" />
             </OutputClaims>
          </TechnicalProfile>
       </TechnicalProfiles>
       </ClaimsProvider>
    </ClaimsProviders>
    
  6. 在本 UserJourneys 部分中,创建一个新的用户旅程(SignInDRS 在我们的示例中),该旅程标识用户并根据传输风险建议执行相应的标识保护步骤。 例如,如果传输返回 允许信任,则旅程可以正常进行,如果“拒绝”,则终止并通知用户问题;如果 质询,则触发分步身份验证过程。

  <UserJourneys>
    <UserJourney Id="SignInDRS">
      <OrchestrationSteps>
        <!-- Step that identifies the user by email and stores the action token -->
        <OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.selfasserted">
          <ClaimsProviderSelections>
            <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
          </ClaimsProviderSelections>
          <ClaimsExchanges>
            <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
          </ClaimsExchanges>
        </OrchestrationStep>

        <!-- Step to perform DRS check -->
        <OrchestrationStep Order="2" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="DRSCheckExchange" TechnicalProfileReferenceId="login-DRSCheck" />
          </ClaimsExchanges>
        </OrchestrationStep>

        <!-- Conditional step for ACCEPT or TRUST -->
        <OrchestrationStep Order="3" Type="ClaimsExchange">
          <Preconditions>
            <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
              <Value>ts-drs-recommendation</Value>
              <Value>ACCEPT</Value>
              <Value>TRUST</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <!-- Define the ClaimsExchange or other actions for ACCEPT or TRUST -->
        </OrchestrationStep>

        <!-- Conditional step for CHALLENGE -->
        <OrchestrationStep Order="4" Type="ClaimsExchange">
          <Preconditions>
            <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
              <Value>ts-drs-recommendation</Value>
              <Value>CHALLENGE</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <!-- Define the ClaimsExchange or other actions for CHALLENGE -->
        </OrchestrationStep>

        <!-- Conditional step for DENY -->
        <OrchestrationStep Order="5" Type="ClaimsExchange">
          <Preconditions>
            <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
              <Value>ts-drs-recommendation</Value>
              <Value>DENY</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <!-- Define the ClaimsExchange or other actions for DENY -->
        </OrchestrationStep>
    </UserJourney>
  </UserJourneys>
  1. 将策略文件另存为 DRSTrustFrameworkExtensions.xml

  2. 创建一个从保存的文件继承的新文件。 它扩展了登录策略,该策略用作使用 Transmit DRS 注册和登录用户旅程的入口点。

    <BasePolicy>
       <TenantId>YOUR AZURE TENANT</TenantId>
       <PolicyId>B2C_1A_DRSTrustFrameworkExtensions</PolicyId>
    </BasePolicy>
    
  3. RelyingParty 部分中,配置 DRS 增强型用户旅程(在本示例中的 SignInDRS)。

    <RelyingParty>
       <DefaultUserJourney ReferenceId="SignInDRS" />
       <UserJourneyBehaviors>
       <ScriptExecution>Allow</ScriptExecution>
       </UserJourneyBehaviors>
       <TechnicalProfile Id="PolicyProfile">
       <DisplayName>PolicyProfile</DisplayName>
       <Protocol Name="OpenIdConnect" />
       <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="displayName" />
          <OutputClaim ClaimTypeReferenceId="givenName" />
          <OutputClaim ClaimTypeReferenceId="surname" />
          <OutputClaim ClaimTypeReferenceId="email" />
          <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" />
       </OutputClaims>
       <SubjectNamingInfo ClaimType="sub" />
       </TechnicalProfile>
    </RelyingParty>
    
  4. 将策略文件另存为 DRSSignIn.xml

步骤 5:上传自定义策略

使用与 Azure AD B2C 租户关联的目录,上传自定义策略:

  1. 登录到 Azure 门户
  2. 在门户工具栏中,选择 “目录 + 订阅”。
  3. 门户设置 |“目录 + 订阅 ”页,在 “目录名称 ”列表中,找到 Azure AD B2C 目录,然后选择“ 切换”。
  4. 在“策略”下,选择“Identity Experience Framework”
  5. 选择“ 上传自定义策略”,然后上传更新的自定义策略文件。

步骤 6:测试自定义策略

将目录与 Azure AD B2C 租户配合使用,测试自定义策略:

  1. 在 Azure AD B2C 租户中,在“策略”下,选择“标识体验框架”。
  2. “自定义策略”下,选择“登录策略”。
  3. 对于 应用程序,请选择已注册的 Web 应用程序。
  4. 选择“立即运行”。
  5. 完成用户流。

后续步骤