分享方式:


使用 Azure Active Directory B2C 自訂原則驗證使用者輸入

Azure Active Directory B2C (Azure AD B2C) 自訂原則不僅可讓您強制使用者輸入,還能驗證它們。 您可以將使用者輸入標示為 必要 專案,例如 <DisplayClaim ClaimTypeReferenceId="givenName" Required="true"/> ,但這並不意味著您的使用者將輸入有效的資料。 Azure AD B2C 提供各種方法來驗證使用者輸入。 在本文中,您將瞭解如何撰寫自訂原則,以收集使用者輸入,並使用下列方法加以驗證:

  • 提供要挑選的選項清單,以限制使用者輸入的資料。 此方法會使用 列舉值,您可以在宣告宣告時新增這些值

  • 定義使用者輸入必須相符的模式。 此方法使用 正則運算式,您可以在宣告宣告時新增此正則運算式

  • 定義一組規則,並要求使用者輸入遵守一或多個規則。 此方法會使用 詞,您可以在宣告宣告時新增。

  • 使用特殊宣告類型 reenterPassword 來驗證使用者在使用者輸入集合期間正確重新輸入其密碼。

  • 設定 驗證技術設定檔 ,定義無法在宣告宣告層級定義的複雜商務規則。 例如,您會收集使用者輸入,而該輸入必須針對另一個宣告中的值或集合值進行驗證。

必要條件

注意

本文是 Azure Active Directory B2C 操作指南系列 中建立和執行您自己的自訂原則的一部分 。 建議您從第一篇文章開始此系列。

步驟 1 - 藉由限制使用者輸入選項來驗證使用者輸入

如果您知道使用者可以針對指定輸入輸入輸入的所有可能值,您可以提供使用者必須選取的有限值集。 您可以針對此目的使用 DropdownSinglSelect CheckboxMultiSelect RadioSingleSelect UserInputType 。 在本文中,您將使用 RadioSingleSelect 輸入類型:

  1. 在 VS Code 中,開啟 檔案 ContosoCustomPolicy.XML

  2. ClaimsSchema 檔案的 元素中 ContosoCustomPolicy.XML ,宣告下列宣告類型:

        <ClaimType Id="accountType">
            <DisplayName>Account Type</DisplayName>
            <DataType>string</DataType>
            <UserHelpText>The type of account used by the user</UserHelpText>
            <UserInputType>RadioSingleSelect</UserInputType>
            <Restriction>
                <Enumeration Text="Contoso Employee Account" Value="work" SelectByDefault="true"/>
                <Enumeration Text="Personal Account" Value="personal" SelectByDefault="false"/>
            </Restriction>
        </ClaimType>
    

    我們已宣告 accountType 宣告。 從使用者收集宣告的值時,使用者必須針對值 工作選取 Contoso 員工帳戶 ,或 針對個人值 選取 個人帳戶

    Azure AD B2C 也可讓您將原則納入不同的語言,並提供多種語言的帳戶類型限制。 如需詳細資訊,請參閱 新增使用者屬性的 UI 當地語系化一文 。

  3. 使用 找出具有 Id="UserInformationCollector" 的技術設定檔,並使用下列程式碼, 將 accountType 宣告新增為顯示宣告:

        <DisplayClaim ClaimTypeReferenceId="accountType" Required="true"/>
    
  4. 在 具有 的技術設定檔 Id="UserInformationCollector" 中,使用下列程式碼, 將 accountType 宣告新增為輸出宣告:

        <OutputClaim ClaimTypeReferenceId="accountType"/>
    
  5. 若要在存取權杖中包含帳戶類型宣告,請找出 RelyingParty 元素,使用下列程式碼將 accountType 宣告新增 為權杖宣告:

        <OutputClaim ClaimTypeReferenceId="accountType" />
    

步驟 2 - 使用正則運算式驗證使用者輸入

當無法事先知道所有可能的使用者輸入值時,您可以讓使用者自行輸入資料。 在此情況下,您可以使用 正則運算式 (RegEx) 模式 來決定使用者輸入的格式。 例如,電子郵件必須在其文字中具有 位於 (@) 符號和 句號 (..) 的 。

當您宣告宣告宣告時,自訂原則可讓您定義使用者輸入必須相符的 RegEx。 您可以選擇性地提供訊息,如果訊息的輸入不符合運算式,則會向使用者顯示。

  1. ClaimsSchema找出 元素,並使用下列程式碼宣告 電子郵件 宣告:

        <ClaimType Id="email">
            <DisplayName>Email Address</DisplayName>
            <DataType>string</DataType>
            <DefaultPartnerClaimTypes>
                <Protocol Name="OpenIdConnect" PartnerClaimType="email"/>
            </DefaultPartnerClaimTypes>
            <UserHelpText>Your email address. </UserHelpText>
            <UserInputType>TextBox</UserInputType>
            <Restriction>
                <Pattern RegularExpression="^[a-zA-Z0-9.!#$%&amp;&apos;^_`{}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" HelpText="Please enter a valid email address something like maurice@contoso.com"/>
            </Restriction>
        </ClaimType>
    
  2. 使用 找到具有 Id="UserInformationCollector" 的技術設定檔,使用下列程式碼, 將電子郵件 宣告新增為顯示宣告:

        <DisplayClaim ClaimTypeReferenceId="email" Required="true"/>
    
  3. 在 具有 Id="UserInformationCollector" 的技術設定檔中,使用下列程式碼, 將電子郵件 宣告新增為輸出宣告:

        <OutputClaim ClaimTypeReferenceId="email"/>
    
  4. RelyingParty找出 元素,使用下列程式碼將 電子郵件 新增為權杖宣告:

        <OutputClaim ClaimTypeReferenceId="email" />
    

步驟 3 - 使用述詞驗證使用者輸入

您已使用 RegEx 來驗證使用者輸入。 不過,RegEx 有一個弱點,也就是錯誤訊息會顯示,直到您更正輸入,而不會顯示輸入遺漏的特定需求為止。

述詞驗證可讓您藉由定義一組規則(述詞)和每個規則的獨立錯誤訊息,來解決此問題。 在自訂原則中,述詞具有內建方法,其會定義您想要執行的檢查。 例如,您可以使用 IsLengthRange 述詞方法來檢查使用者 密碼 是否在指定之最小和最大參數(值)的範圍內。

當述詞 定義驗證以針對宣告類型進行檢查時, PredicateValidations 會將一組述詞分組,以形成可套用至宣告類型的使用者輸入驗證。 例如,您可以建立驗證述詞群組,以驗證密碼的不同類型的允許字元。 詞和 PredicateValidations 元素都是原則檔案區段的BuildingBlocks子元素。

  1. ClaimsSchema找出 元素,並使用下列程式代碼宣告密碼宣告:

        <ClaimType Id="password">
          <DisplayName>Password</DisplayName>
          <DataType>string</DataType>
          <AdminHelpText>Enter password</AdminHelpText>
          <UserHelpText>Enter password</UserHelpText>
          <UserInputType>Password</UserInputType>
        </ClaimType>
    
  2. Predicates使用下列程序代碼,將專案新增為 區段的BuildingBlocks子系。 您會在 Predicates 元素下方 ClaimsSchema 新增 元素:

        <Predicates>
    
        </Predicates>
    
  3. 在 元素內 Predicates ,使用下列程式代碼定義述詞:

      <Predicate Id="IsLengthBetween8And64" Method="IsLengthRange" HelpText="The password must be between 8 and 64 characters.">
        <Parameters>
          <Parameter Id="Minimum">8</Parameter>
          <Parameter Id="Maximum">64</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Lowercase" Method="IncludesCharacters" HelpText="a lowercase letter">
        <Parameters>
          <Parameter Id="CharacterSet">a-z</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Uppercase" Method="IncludesCharacters" HelpText="an uppercase letter">
        <Parameters>
          <Parameter Id="CharacterSet">A-Z</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Number" Method="IncludesCharacters" HelpText="a digit">
        <Parameters>
          <Parameter Id="CharacterSet">0-9</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Symbol" Method="IncludesCharacters" HelpText="a symbol">
        <Parameters>
          <Parameter Id="CharacterSet">@#$%^&amp;*\-_+=[]{}|\\:',.?/`~"();!</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="PIN" Method="MatchesRegex" HelpText="The password must be numbers only.">
        <Parameters>
          <Parameter Id="RegularExpression">^[0-9]+$</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="AllowedCharacters" Method="MatchesRegex" HelpText="An invalid character was provided.">
        <Parameters>
          <Parameter Id="RegularExpression">(^([0-9A-Za-z\d@#$%^&amp;*\-_+=[\]{}|\\:',?/`~"();! ]|(\.(?!@)))+$)|(^$)</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="DisallowedWhitespace" Method="MatchesRegex" HelpText="The password must not begin or end with a whitespace character.">
        <Parameters>
          <Parameter Id="RegularExpression">(^\S.*\S$)|(^\S+$)|(^$)</Parameter>
        </Parameters>
      </Predicate>
    

    我們已定義數個規則,當將描述可接受的密碼放在一起時。 接下來,您可以將述詞分組,以形成一組可在原則中使用的密碼原則。

  4. PredicateValidations使用下列程序代碼,將專案新增為 區段的BuildingBlocks子系。 您會將 PredicateValidations 元素新增為 區段的 BuildingBlocks 子系,但在 元素下方 Predicates

        <PredicateValidations>
    
        </PredicateValidations>
    
  5. PredicateValidations 元素內,使用下列程式代碼定義 PredicateValidations:

        <PredicateValidation Id="SimplePassword">
            <PredicateGroups>
                <PredicateGroup Id="DisallowedWhitespaceGroup">
                    <PredicateReferences>
                        <PredicateReference Id="DisallowedWhitespace"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="AllowedCharactersGroup">
                    <PredicateReferences>
                        <PredicateReference Id="AllowedCharacters"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="LengthGroup">
                    <PredicateReferences>
                        <PredicateReference Id="IsLengthBetween8And64"/>
                    </PredicateReferences>
                </PredicateGroup>
            </PredicateGroups>
        </PredicateValidation>
        <PredicateValidation Id="StrongPassword">
            <PredicateGroups>
                <PredicateGroup Id="DisallowedWhitespaceGroup">
                    <PredicateReferences>
                        <PredicateReference Id="DisallowedWhitespace"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="AllowedCharactersGroup">
                    <PredicateReferences>
                        <PredicateReference Id="AllowedCharacters"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="LengthGroup">
                    <PredicateReferences>
                        <PredicateReference Id="IsLengthBetween8And64"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="CharacterClasses">
                    <UserHelpText>The password must have at least 3 of the following:</UserHelpText>
                    <PredicateReferences MatchAtLeast="3">
                        <PredicateReference Id="Lowercase"/>
                        <PredicateReference Id="Uppercase"/>
                        <PredicateReference Id="Number"/>
                        <PredicateReference Id="Symbol"/>
                    </PredicateReferences>
                </PredicateGroup>
            </PredicateGroups>
        </PredicateValidation>
        <PredicateValidation Id="CustomPassword">
            <PredicateGroups>
                <PredicateGroup Id="DisallowedWhitespaceGroup">
                    <PredicateReferences>
                        <PredicateReference Id="DisallowedWhitespace"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="AllowedCharactersGroup">
                    <PredicateReferences>
                        <PredicateReference Id="AllowedCharacters"/>
                    </PredicateReferences>
                </PredicateGroup>
            </PredicateGroups>
        </PredicateValidation>
    

    我們有三個定義的述詞驗證、StrongPassword、CustomPasswordSimplePassword 視您希望使用者輸入的密碼特性而定,您可以在述詞驗證上使用任何專案。 在本文中,我們將使用強密碼。

  6. 找出密碼宣告宣告,並使用下列程式代碼在UserInputType元素宣告之後新增 StrongPassword 述詞驗證:

        <PredicateValidationReference Id="StrongPassword" />
    
  7. 使用 找出具有 Id="UserInformationCollector"的技術配置檔,並使用下列程式代碼, 將密碼 宣告新增為顯示宣告:

        <DisplayClaim ClaimTypeReferenceId="password" Required="true"/>
    
  8. 在 具有 Id="UserInformationCollector"的技術設定檔中,使用下列程式代碼, 將密碼 宣告新增為輸出宣告:

        <OutputClaim ClaimTypeReferenceId="password"/>
    

注意

基於安全性考慮,我們不會將用戶的密碼新增為原則所產生令牌中的宣告。 因此,我們不會將密碼宣告新增至信賴憑證者元素。

步驟 4 - 驗證密碼並確認密碼

您可以要求使用者輸入其密碼兩次,以確認使用者記住他們輸入的密碼。 在此情況下,您必須檢查兩個專案的值是否相符。 自定義原則可讓您輕鬆達成此需求。 宣告類型 密碼reenterPassword 會被視為特殊,因此當他們用來收集使用者輸入時,UI 會驗證使用者是否已正確重新輸入其密碼。

使用下列步驟來驗證自定義原則中的密碼重新輸入:

  1. 在您的ClaimsSchema檔案區ContosoCustomPolicy.XML段中,使用下列程序代碼,在密碼宣告之後宣告 reenterPassword 宣告:

        <ClaimType Id="reenterPassword">
            <DisplayName>Confirm new password</DisplayName>
            <DataType>string</DataType>
            <AdminHelpText>Confirm new password</AdminHelpText>
            <UserHelpText>Reenter password</UserHelpText>
            <UserInputType>Password</UserInputType>
        </ClaimType>    
    
  2. 若要從使用者收集密碼確認輸入,請找出UserInformationCollector自我判斷技術配置檔,使用下列程式代碼將 reenterPassword 宣告新增為顯示宣告:

        <DisplayClaim ClaimTypeReferenceId="reenterPassword" Required="true"/>
    
  3. 在您的ContosoCustomPolicy.XML檔案中UserInformationCollector,找出自我判斷技術配置檔,使用下列程序代碼,將 reenterPassword 宣告新增為輸出宣告:

        <OutputClaim ClaimTypeReferenceId="reenterPassword"/>
    

步驟 5 - 上傳自定義原則檔案

此時,您已建置原則來解決使用者輸入驗證的前三種方法。

請遵循上傳自定義原則檔案中的步驟。 如果您要上傳與入口網站中已有相同名稱的檔案,請確定您已選取 [覆寫自定義原則] ,如果檔案已經存在

步驟 6 - 測試自定義原則

  1. 在 [自定義原則] 底下,選取 [B2C_1A_CONTOSOCUSTOMPOLICY]。

  2. 針對在 自定義原則的概觀頁面上選取應用程式 ,請選取您先前註冊的 Web 應用程式,例如 webapp1 。 請確定 [選擇取回覆 URL ] 值已設定為https://jwt.ms

  3. 選取 [ 立即 執行] 按鈕。

  4. 輸入指定名稱和姓氏

  5. 選取 [ 帳戶類型]。

  6. 針對 [電子郵件位址],輸入格式不正確的電子郵件值,例如 maurice@contoso

  7. 針對 [ 密碼],輸入密碼值,該值不符合設定的強密碼的所有特性。

  8. 選取 [ 繼續] 按鈕。 您會看到類似如下所示的畫面:

    screenshot of validating user inputs.

    您必須先更正輸入,才能繼續。

  9. 輸入錯誤訊息所建議的正確值,然後再次選取 [ 繼續] 按鈕。 原則完成執行之後,系統會將您重新導向至 https://jwt.ms ,您會看到已解碼的 JWT 權杖。 權杖看起來類似下列 JWT 權杖程式碼片段:

    {
      "typ": "JWT",
      "alg": "RS256",
      "kid": "pxLOMWFg...."
    }.{
      ...
      "sub": "c7ae4515-f7a7....",
      ...
      "acr": "b2c_1a_contosocustompolicy",
      "accountType": "work",
      ...
      "email": "maurice@contoso.com",
      "name": "Maurice Paulet",
      "message": "Hello Maurice Paulet"
    }.[Signature]

步驟 7 - 使用驗證技術設定檔驗證使用者輸入

我們在步驟 1、步驟 2 和步驟 3 中使用的驗證技術不適用於所有案例。 如果您的商務規則在宣告層級定義很複雜,您可以設定 驗證技術,然後從 自我判斷技術 設定檔 呼叫它。

注意

只有自我判斷技術設定檔可以使用驗證技術設定檔。 深入瞭解 驗證技術設定檔

案例概觀

我們需要,如果使用者的 帳戶類型 Contoso 員工帳戶 ,我們必須確定其電子郵件網域是以一組預先定義的網域為基礎。 這些網域是 contoso.com、fabrikam.com woodgrove.com 。 否則,我們會向使用者顯示錯誤,直到他們使用有效的 Contoso 員工帳戶 或切換至 個人帳戶 為止。

使用下列步驟,瞭解如何使用驗證技術設定檔來驗證使用者輸入。 您可以使用宣告轉換類型驗證技術設定檔,但您也可以呼叫 REST API 服務來驗證資料,因為您稍後會在本系列中瞭解。

  1. 在您的 ClaimsSchema 檔案區 ContosoCustomPolicy.XML 段中,使用下列程式碼宣告 網域 domainStatus 宣告:

        <ClaimType Id="domain">
          <DataType>string</DataType>
        </ClaimType>
    
        <ClaimType Id="domainStatus">
          <DataType>string</DataType>
        </ClaimType>
    
  2. 找出 區 ClaimsTransformations 段,並使用下列程式碼設定宣告轉換:

        <ClaimsTransformation Id="GetDomainFromEmail" TransformationMethod="ParseDomain">
            <InputClaims>
                <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="emailAddress"/>
            </InputClaims>
            <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="domain" TransformationClaimType="domain"/>
            </OutputClaims>
        </ClaimsTransformation>
        <ClaimsTransformation Id="LookupDomain" TransformationMethod="LookupValue">
            <InputClaims>
                <InputClaim ClaimTypeReferenceId="domain" TransformationClaimType="inputParameterId"/>
            </InputClaims>
            <InputParameters>
                <InputParameter Id="contoso.com" DataType="string" Value="valid"/>
                <InputParameter Id="fabrikam.com" DataType="string" Value="valid"/>
                <InputParameter Id="woodgrove.com" DataType="string" Value="valid"/>
                <InputParameter Id="errorOnFailedLookup" DataType="boolean" Value="true"/>
            </InputParameters>
            <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="domainStatus" TransformationClaimType="outputClaim"/>
            </OutputClaims>
        </ClaimsTransformation>
    

    GetDomainFromEmail 宣告轉換會使用 ParseDomain 方法從電子郵件擷取網域,並將其儲存在網域 宣告中 LookupDomain 宣告轉換會使用擷取的網域來檢查它是否有效,方法是在預先定義的網域中查閱,並將有效 指派 domainStatus 宣告。

  3. 使用下列程式碼,在與 技術設定檔相同的宣告提供者中新增技術設定檔 Id=UserInformationCollector

        <TechnicalProfile Id="CheckCompanyDomain">
            <DisplayName>Check Company validity </DisplayName>
            <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
            <InputClaimsTransformations>
                <InputClaimsTransformation ReferenceId="GetDomainFromEmail"/>
            </InputClaimsTransformations>
            <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="domain"/>
            </OutputClaims>
            <OutputClaimsTransformations>
                <OutputClaimsTransformation ReferenceId="LookupDomain"/>
            </OutputClaimsTransformations>
        </TechnicalProfile>
    

    我們已宣告宣告宣告轉換技術設定檔,其會 執行 GetDomainFromEmail LookupDomain 宣告轉換。

  4. 使用下列程式碼找出 具有 Id=UserInformationCollector 的技術設定檔,並在 ValidationTechnicalProfile 專案後面 OutputClaims 找到 :

        <ValidationTechnicalProfiles>
            <ValidationTechnicalProfile ReferenceId="CheckCompanyDomain">
                <Preconditions>
                    <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
                        <Value>accountType</Value>
                        <Value>work</Value>
                        <Action>SkipThisValidationTechnicalProfile</Action>
                    </Precondition>
                </Preconditions>
            </ValidationTechnicalProfile>
        </ValidationTechnicalProfiles>
    

    我們已將驗證技術配置檔新增至 UserInformationCollector 自我判斷技術配置檔。 只有在 accountType 值不等於運作時,才會略過技術配置檔。 如果技術配置檔執行,且電子郵件網域無效,則會擲回錯誤。

  5. 找出具有 Id=UserInformationCollector的技術配置檔,並在標記內 metadata 新增下列程序代碼。

        <Item Key="LookupNotFound">The provided email address isn't a valid Contoso Employee email.</Item>
    

    我們已設定自定義錯誤,以防使用者未使用有效的電子郵件。

  6. 請遵循上傳自定義原則檔案中的指示來上傳您的原則檔案。

  7. 請遵循步驟 6 中的指示來測試您的自訂原則:

    1. 針對 [ 帳戶類型],選取 [Contoso 員工帳戶]
    2. 針對 [電子郵件位址],輸入無效的電子郵件位址,例如 maurice@fourthcoffee.com
    3. 視需要輸入其餘詳細數據,然後選取 [ 繼續]

    由於 maurice@fourthcoffee.com 不是有效的電子郵件,因此您會看到類似以下螢幕快照所示的錯誤。 您必須使用有效的電子郵件位址,才能成功執行自定義原則並接收 JWT 令牌。

    screenshot of error due to invalid email address.

下一步