Поделиться через


Проверка входных данных пользователей с помощью пользовательской политики 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 и RadioSingleSelectUserInputType. В этой статье вы будете использовать тип входных данных RadioSingleSelect :

  1. В VS Code откройте файл ContosoCustomPolicy.XML.

  2. В элементе ContosoCustomPolicy.XML файла объявите ClaimsSchema следующий тип утверждения:

        <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 также позволяет разместить политику на разных языках и предоставить ограничения типа учетной записи для нескольких языков. Дополнительные сведения проверка локализации пользовательского интерфейса статьи "Добавление атрибутов пользователя".

  3. Найдите технический профиль и Id="UserInformationCollector"добавьте утверждение accountType в качестве отображаемого утверждения с помощью следующего кода:

        <DisplayClaim ClaimTypeReferenceId="accountType" Required="true"/>
    
  4. В техническом профиле Id="UserInformationCollector"добавьте утверждение accountType в качестве выходного утверждения с помощью следующего кода:

        <OutputClaim ClaimTypeReferenceId="accountType"/>
    
  5. Чтобы включить утверждение типа учетной записи в маркер доступа, найдите RelyingParty элемент, добавьте утверждение accountType в качестве утверждения токена с помощью следующего кода:

        <OutputClaim ClaimTypeReferenceId="accountType" />
    

Шаг 2. Проверка входных данных пользователей с помощью регулярных выражений

Если заранее не удается узнать все возможные входные значения пользователей, можно разрешить пользователю вводить данные самостоятельно. В этом случае можно использовать регулярные выражения (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, чтобы проверка, находится ли пароль пользователя в диапазоне минимальных и максимальных параметров (значений).

Хотя предикаты определяют проверку для проверка для типа утверждения, предикаты группируют набор предикатов для формирования проверки ввода пользователем, которую можно применить к типу утверждения. Например, вы создаете группу предиката проверки, которая проверяет различные типы разрешенных символов для пароля. Элементы Predicates и 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, CustomPassword и SimplePassword. В зависимости от характеристик пароля, который требуется ввести пользователям, можно использовать любой из вариантов проверки предиката. В этой статье мы будем использовать надежный пароль.

  6. Найдите объявление типа утверждения пароля и добавьте проверку предиката StrongPassword сразу после объявления элемента UserInputType, содержащегося в следующем коде:

        <PredicateValidationReference Id="StrongPassword" />
    
  7. Найдите технический профиль с Id="UserInformationCollector"помощью , добавьте утверждение пароля в качестве отображаемого утверждения с помощью следующего кода:

        <DisplayClaim ClaimTypeReferenceId="password" Required="true"/>
    
  8. В техническом профиле Id="UserInformationCollector"добавьте утверждение пароля в качестве выходного утверждения с помощью следующего кода:

        <OutputClaim ClaimTypeReferenceId="password"/>
    

Примечание.

По соображениям безопасности мы не добавим пароль пользователей в качестве утверждения в маркере, созданном политикой. Поэтому мы не добавляем утверждение пароля в элемент проверяющей стороны.

Шаг 4. Проверка пароля и подтверждение пароля

Вы можете требовать, чтобы пользователи вводили свой пароль дважды в качестве средства, чтобы убедиться, что пользователь запоминает введенный пароль. В этом случае необходимо проверка, что совпадают значения двух записей. Пользовательская политика предоставляет простой способ достижения этого требования. Пароль типов утверждений и reenterPassword считаются специальными, поэтому, когда они используются для сбора входных данных пользователей, пользовательский интерфейс проверяет правильность ввода пароля пользователем.

Чтобы проверить пароль повторно введите пароль в настраиваемую политику, выполните следующие действия.

  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. Для выбора приложения на странице обзора настраиваемой политики выберите веб-приложение , например webapp1 , которое вы ранее зарегистрировали. Убедитесь, что для параметра Select reply URL заданоhttps://jwt.ms значение URL-адреса ответа.

  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 В разделе файла объявите утверждения домена и domainStatus с помощью следующего ContosoCustomPolicy.XML кода:

        <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=UserInformationCollectorValidationTechnicalProfile сразу после элемента с помощью следующего 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.

Следующие шаги