Ověřování v podnikových aplikacích

Poznámka:

Tato elektronická kniha byla publikována na jaře roku 2017 a od té doby nebyla aktualizována. Existuje mnoho v knize, která zůstává cenná, ale některé materiály jsou zastaralé.

Každá aplikace, která přijímá vstup od uživatelů, by se měla ujistit, že vstup je platný. Aplikace může například zkontrolovat vstup, který obsahuje pouze znaky v určitém rozsahu, má určitou délku nebo odpovídá určitému formátu. Bez ověření může uživatel zadat data, která způsobí selhání aplikace. Ověřování vynucuje obchodní pravidla a brání útočníkovi v vkládání škodlivých dat.

V kontextu modelu Model-View-ViewModel (MVVM) se model zobrazení nebo model často vyžaduje k ověření dat a k označení všech chyb ověření do zobrazení, aby je uživatel mohl opravit. Mobilní aplikace eShopOnContainers provádí synchronní ověření vlastností modelu zobrazení na straně klienta a upozorní uživatele na případné chyby ověření zvýrazněním ovládacího prvku, který obsahuje neplatná data, a zobrazením chybových zpráv, které uživatele informují o tom, proč jsou data neplatná. Obrázek 6-1 ukazuje třídy, které se týkají ověřování v mobilní aplikaci eShopOnContainers.

Validation classes in the eShopOnContainers mobile app

Obrázek 6-1: Ověřovací třídy v mobilní aplikaci eShopOnContainers

Umožňuje zobrazit vlastnosti modelu, které vyžadují ověření typu ValidatableObject<T>, a každá ValidatableObject<T> instance má do své Validations vlastnosti přidaná ověřovací pravidla. Ověření se vyvolá z modelu zobrazení voláním Validate metody ValidatableObject<T> instance, která načte ověřovací pravidla a provede je proti ValidatableObject<T>Value vlastnosti. Všechny chyby ověření se umístí do Errors vlastnosti ValidatableObject<T> instance a IsValid vlastnost ValidatableObject<T> instance se aktualizuje, aby indikovala, jestli ověření proběhlo úspěšně nebo selhalo.

Oznámení o změně vlastnosti je poskytováno ExtendedBindableObject třídou, a proto Entry může ovládací prvek vytvořit vazbu na IsValid vlastnost ValidatableObject<T> instance ve třídě modelu zobrazení, aby byla upozorněna na to, zda jsou zadaná data platná nebo ne.

Zadání ověřovacích pravidel

Ověřovací pravidla jsou určena vytvořením třídy, která je odvozena z IValidationRule<T> rozhraní, což je znázorněno v následujícím příkladu kódu:

public interface IValidationRule<T>  
{  
    string ValidationMessage { get; set; }  
    bool Check(T value);  
}

Toto rozhraní určuje, že třída ověřovacího pravidla musí poskytovat metodu booleanCheck , která se používá k provedení požadovaného ověření, a ValidationMessage vlastnost, jejíž hodnota je ověřovací chybová zpráva, která se zobrazí v případě selhání ověření.

Následující příklad kódu ukazuje IsNotNullOrEmptyRule<T> ověřovací pravidlo, které slouží k ověření uživatelského jména a hesla zadaného uživatelem LoginView při použití napodobení služeb v mobilní aplikaci eShopOnContainers:

public class IsNotNullOrEmptyRule<T> : IValidationRule<T>  
{  
    public string ValidationMessage { get; set; }  

    public bool Check(T value)  
    {  
        if (value == null)  
        {  
            return false;  
        }  

        var str = value as string;  
        return !string.IsNullOrWhiteSpace(str);  
    }  
}

Metoda Check vrátí boolean indikující, zda je nullargument hodnota , prázdný, nebo se skládá pouze z prázdných znaků.

I když mobilní aplikace eShopOnContainers nepoužívá, následující příklad kódu ukazuje ověřovací pravidlo pro ověřování e-mailových adres:

public class EmailRule<T> : IValidationRule<T>  
{  
    public string ValidationMessage { get; set; }  

    public bool Check(T value)  
    {  
        if (value == null)  
        {  
            return false;  
        }  

        var str = value as string;  
        Regex regex = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");  
        Match match = regex.Match(str);  

        return match.Success;  
    }  
}

Metoda Check vrátí boolean určující, zda je argument hodnota platná e-mailová adresa. Toho dosáhnete vyhledáním argumentu hodnoty prvního výskytu vzoru regulárního výrazu zadaného v konstruktoru Regex . Zda vzor regulárního výrazu byl nalezen ve vstupním řetězci lze určit kontrolou hodnoty vlastnosti objektu MatchSuccess .

Poznámka:

Ověření vlastnosti může někdy zahrnovat závislé vlastnosti. Příkladem závislých vlastností je, když sada platných hodnot pro vlastnost A závisí na konkrétní hodnotě, která byla nastavena ve vlastnosti B. Chcete-li zkontrolovat, zda hodnota vlastnosti A je jednou z povolených hodnot, by zahrnoval načtení hodnoty vlastnosti B. Kromě toho, když hodnota vlastnosti B změní, vlastnost A bude nutné znovu aktualizovat.

Přidání ověřovacích pravidel do vlastnosti

V mobilní aplikaci eShopOnContainers zobrazte vlastnosti modelu, které vyžadují ověření, jsou deklarovány jako typ ValidatableObject<T>, kde T je typ dat, která se mají ověřit. Následující příklad kódu ukazuje příklad dvou takových vlastností:

public ValidatableObject<string> UserName  
{  
    get  
    {  
        return _userName;  
    }  
    set  
    {  
        _userName = value;  
        RaisePropertyChanged(() => UserName);  
    }  
}  

public ValidatableObject<string> Password  
{  
    get  
    {  
        return _password;  
    }  
    set  
    {  
        _password = value;  
        RaisePropertyChanged(() => Password);  
    }  
}

Aby mohlo dojít k ověření, musí být ověřovací pravidla přidána do Validations kolekce každé ValidatableObject<T> instance, jak je znázorněno v následujícím příkladu kódu:

private void AddValidations()  
{  
    _userName.Validations.Add(new IsNotNullOrEmptyRule<string>   
    {   
        ValidationMessage = "A username is required."   
    });  
    _password.Validations.Add(new IsNotNullOrEmptyRule<string>   
    {   
        ValidationMessage = "A password is required."   
    });  
}

Tato metoda přidá IsNotNullOrEmptyRule<T> ověřovací pravidlo do Validations kolekce každé ValidatableObject<T> instance a určuje hodnoty pro vlastnost ověřovacího pravidla ValidationMessage , která určuje chybovou zprávu ověření, která se zobrazí v případě selhání ověření.

Aktivace ověřování

Ověřovací přístup použitý v mobilní aplikaci eShopOnContainers může ručně aktivovat ověření vlastnosti a automaticky aktivovat ověření při změně vlastnosti.

Ruční aktivace ověření

Ověření lze aktivovat ručně pro vlastnost modelu zobrazení. K tomu například dochází v mobilní aplikaci eShopOnContainers, když uživatel klepne na tlačítko Přihlásit se na LoginView, při použití napodobení služeb. Delegát příkazu volá metodu MockSignInAsyncLoginViewModelv , která vyvolá ověření spuštěním Validate metody, která je znázorněna v následujícím příkladu kódu:

private bool Validate()  
{  
    bool isValidUser = ValidateUserName();  
    bool isValidPassword = ValidatePassword();  
    return isValidUser && isValidPassword;  
}  

private bool ValidateUserName()  
{  
    return _userName.Validate();  
}  

private bool ValidatePassword()  
{  
    return _password.Validate();  
}

Metoda Validate provádí ověření uživatelského jména a hesla zadaného uživatelem v aplikaci LoginView, vyvoláním metody Validate v každé ValidatableObject<T> instanci. Následující příklad kódu ukazuje Metodu ValidatableObject<T> Validate z třídy:

public bool Validate()  
{  
    Errors.Clear();  

    IEnumerable<string> errors = _validations  
        .Where(v => !v.Check(Value))  
        .Select(v => v.ValidationMessage);  

    Errors = errors.ToList();  
    IsValid = !Errors.Any();  

    return this.IsValid;  
}

Tato metoda vymaže Errors kolekci a pak načte všechna ověřovací pravidla, která byla přidána do kolekce objektu Validations . Spustí se Check metoda pro každé načtené ověřovací pravidlo a ValidationMessage hodnota vlastnosti pro každé ověřovací pravidlo, které se nepodaří ověřit data, se přidají do Errors kolekce ValidatableObject<T> instance. IsValid Nakonec je vlastnost nastavena a její hodnota je vrácena volající metodě označující, zda ověření bylo úspěšné nebo neúspěšné.

Aktivace ověření při změně vlastností

Ověření lze aktivovat také při každé změně vázané vlastnosti. Pokud například obousměrná vazba v LoginView sadě nebo UserNamePassword vlastnosti nastaví, aktivuje se ověření. Následující příklad kódu ukazuje, jak k tomu dochází:

<Entry Text="{Binding UserName.Value, Mode=TwoWay}">  
    <Entry.Behaviors>  
        <behaviors:EventToCommandBehavior  
            EventName="TextChanged"  
            Command="{Binding ValidateUserNameCommand}" />  
    </Entry.Behaviors>  
    ...  
</Entry>

Ovládací Entry prvek vytvoří vazbu na UserName.Value vlastnost ValidatableObject<T> instance a kolekce ovládacího prvku Behaviors má přidanou EventToCommandBehavior instanci. Toto chování spustí ValidateUserNameCommand v reakci na událost [TextChanged] vysílané na Entry, která je vyvolána při změně textu Entry . Delegát pak ValidateUserNameCommand spustí metodu ValidateUserName , která spustí metodu Validate v ValidatableObject<T> instanci. Proto se při každém zadání znaku v ovládacím Entry prvku pro uživatelské jméno provede ověření zadaných dat.

Další informace o chování naleznete v tématu Implementace chování.

Zobrazení chyb ověření

Mobilní aplikace eShopOnContainers upozorní uživatele na případné chyby ověření zvýrazněním ovládacího prvku, který obsahuje neplatná data červenou čárou, a zobrazením chybové zprávy, která informuje uživatele o tom, proč jsou data neplatná pod ovládacím prvku obsahujícím neplatná data. Při opravě neplatných dat se řádek změní na černou a chybová zpráva se odebere. Obrázek 6-2 ukazuje LoginView v mobilní aplikaci eShopOnContainers, když se zobrazí chyby ověření.

Displaying validation errors during login

Obrázek 6–2: Zobrazení chyb ověření během přihlášení

Zvýraznění ovládacího prvku, který obsahuje neplatná data

Připojené LineColorBehavior chování se používá ke zvýraznění Entry ovládacích prvků, u kterých došlo k chybám ověření. Následující příklad kódu ukazuje, jak LineColorBehavior je připojené chování připojeno k ovládacímu Entry prvku:

<Entry Text="{Binding UserName.Value, Mode=TwoWay}">
    <Entry.Style>
        <OnPlatform x:TypeArguments="Style">
            <On Platform="iOS, Android" Value="{StaticResource EntryStyle}" />
            <On Platform="UWP" Value="{StaticResource UwpEntryStyle}" />
        </OnPlatform>
    </Entry.Style>
    ...
</Entry>

Ovládací Entry prvek využívá explicitní styl, který je znázorněn v následujícím příkladu kódu:

<Style x:Key="EntryStyle"  
       TargetType="{x:Type Entry}">  
    ...  
    <Setter Property="behaviors:LineColorBehavior.ApplyLineColor"  
            Value="True" />  
    <Setter Property="behaviors:LineColorBehavior.LineColor"  
            Value="{StaticResource BlackColor}" />  
    ...  
</Style>

Tento styl nastaví ApplyLineColor a LineColor připojené vlastnosti připojeného LineColorBehavior chování Entry ovládacího prvku. Další informace o stylech naleznete v tématu Styly.

Když je nastavena hodnota ApplyLineColor připojené vlastnosti nebo změní, LineColorBehavior připojené chování spustí metodu OnApplyLineColorChanged , která je znázorněna v následujícím příkladu kódu:

public static class LineColorBehavior  
{  
    ...  
    private static void OnApplyLineColorChanged(  
                BindableObject bindable, object oldValue, object newValue)  
    {  
        var view = bindable as View;  
        if (view == null)  
        {  
            return;  
        }  

        bool hasLine = (bool)newValue;  
        if (hasLine)  
        {  
            view.Effects.Add(new EntryLineColorEffect());  
        }  
        else  
        {  
            var entryLineColorEffectToRemove =   
                    view.Effects.FirstOrDefault(e => e is EntryLineColorEffect);  
            if (entryLineColorEffectToRemove != null)  
            {  
                view.Effects.Remove(entryLineColorEffectToRemove);  
            }  
        }  
    }  
}

Parametry pro tuto metodu poskytují instanci ovládacího prvku, ke kterému je chování připojeno, a staré a nové hodnoty ApplyLineColor připojené vlastnosti. Třída EntryLineColorEffect se přidá do kolekce ovládacího prvkuEffects, pokud je truepřipojená ApplyLineColor vlastnost , jinak je odebrána z kolekce ovládacího prvkuEffects. Další informace o chování naleznete v tématu Implementace chování.

Podtřídy EntryLineColorEffectRoutingEffect třídy a jsou uvedeny v následujícím příkladu kódu:

public class EntryLineColorEffect : RoutingEffect  
{  
    public EntryLineColorEffect() : base("eShopOnContainers.EntryLineColorEffect")  
    {  
    }  
}

Třída RoutingEffect představuje efekt nezávislý na platformě, který zabalí vnitřní efekt specifický pro platformu. To zjednodušuje proces odebrání efektu, protože neexistuje žádný přístup k informacím o typu pro efekt specifický pro platformu. Volání EntryLineColorEffect konstruktoru základní třídy, předání parametru sestávajícího ze zřetězení názvu skupiny překladu a jedinečné ID zadané pro každou třídu efektu specifické pro platformu.

Následující příklad kódu ukazuje implementaci eShopOnContainers.EntryLineColorEffect pro iOS:

[assembly: ResolutionGroupName("eShopOnContainers")]  
[assembly: ExportEffect(typeof(EntryLineColorEffect), "EntryLineColorEffect")]  
namespace eShopOnContainers.iOS.Effects  
{  
    public class EntryLineColorEffect : PlatformEffect  
    {  
        UITextField control;  

        protected override void OnAttached()  
        {  
            try  
            {  
                control = Control as UITextField;  
                UpdateLineColor();  
            }  
            catch (Exception ex)  
            {  
                Console.WriteLine("Can't set property on attached control. Error: ", ex.Message);  
            }  
        }  

        protected override void OnDetached()  
        {  
            control = null;  
        }  

        protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)  
        {  
            base.OnElementPropertyChanged(args);  

            if (args.PropertyName == LineColorBehavior.LineColorProperty.PropertyName ||  
                args.PropertyName == "Height")  
            {  
                Initialize();  
                UpdateLineColor();  
            }  
        }  

        private void Initialize()  
        {  
            var entry = Element as Entry;  
            if (entry != null)  
            {  
                Control.Bounds = new CGRect(0, 0, entry.Width, entry.Height);  
            }  
        }  

        private void UpdateLineColor()  
        {  
            BorderLineLayer lineLayer = control.Layer.Sublayers.OfType<BorderLineLayer>()  
                                                             .FirstOrDefault();  

            if (lineLayer == null)  
            {  
                lineLayer = new BorderLineLayer();  
                lineLayer.MasksToBounds = true;  
                lineLayer.BorderWidth = 1.0f;  
                control.Layer.AddSublayer(lineLayer);  
                control.BorderStyle = UITextBorderStyle.None;  
            }  

            lineLayer.Frame = new CGRect(0f, Control.Frame.Height-1f, Control.Bounds.Width, 1f);  
            lineLayer.BorderColor = LineColorBehavior.GetLineColor(Element).ToCGColor();  
            control.TintColor = control.TextColor;  
        }  

        private class BorderLineLayer : CALayer  
        {  
        }  
    }  
}

Metoda OnAttached načte nativní ovládací prvek pro Xamarin.FormsEntry ovládací prvek a aktualizuje barvu čáry voláním UpdateLineColor metody. Přepsání OnElementPropertyChanged reaguje na změny vlastností s možností vázání v ovládacím Entry prvku aktualizací barvy čáry, pokud se připojená LineColor vlastnost změní nebo Height vlastnost Entry změn. Další informace o efektech naleznete v tématu Efekty.

Pokud jsou do Entry ovládacího prvku zadána platná data, použije se v dolní části ovládacího prvku černá čára, která indikuje, že nedošlo k chybě ověření. Obrázek 6–3 ukazuje příklad.

Black line indicating no validation error

Obrázek 6–3: Černá čára označující chybu ověření

Ovládací Entry prvek má také přidanou DataTrigger do své Triggers kolekce. Následující příklad kódu ukazuje DataTrigger:

<Entry Text="{Binding UserName.Value, Mode=TwoWay}">  
    ...  
    <Entry.Triggers>  
        <DataTrigger   
            TargetType="Entry"  
            Binding="{Binding UserName.IsValid}"  
            Value="False">  
            <Setter Property="behaviors:LineColorBehavior.LineColor"   
                    Value="{StaticResource ErrorColor}" />  
        </DataTrigger>  
    </Entry.Triggers>  
</Entry>

Tato DataTrigger funkce monitoruje UserName.IsValid vlastnost a pokud se hodnota stane false, spustí Setter, která změní LineColor připojenou vlastnost připojeného LineColorBehavior chování na červenou. Obrázek 6–4 ukazuje příklad.

Red line indicating validation error

Obrázek 6–4: Červená čára označující chybu ověření

Řádek v ovládacím Entry prvku zůstane červený, zatímco zadaná data jsou neplatná, jinak se změní na černou, aby indikuje, že zadaná data jsou platná.

Další informace o aktivačních událostech najdete v tématu Aktivační události.

Zobrazení chybových zpráv

Uživatelské rozhraní zobrazuje chybové zprávy ověřování v ovládacích prvcích Popisek pod každým ovládacím prvku, jehož data selhala při ověřování. Následující příklad kódu ukazuje Label , že se zobrazí chybová zpráva ověření, pokud uživatel nezadali platné uživatelské jméno:

<Label Text="{Binding UserName.Errors, Converter={StaticResource FirstValidationErrorConverter}}"  
       Style="{StaticResource ValidationErrorLabelStyle}" />

Každá Label vazba na Errors vlastnost objektu modelu zobrazení, který se ověřuje. Vlastnost Errors je poskytována ValidatableObject<T> třídou a je typu List<string>. Errors Protože vlastnost může obsahovat více chyb ověření, FirstValidationErrorConverter instance se používá k načtení první chyby z kolekce pro zobrazení.

Shrnutí

Mobilní aplikace eShopOnContainers provádí synchronní ověření vlastností modelu zobrazení na straně klienta a upozorní uživatele na případné chyby ověření zvýrazněním ovládacího prvku, který obsahuje neplatná data, a zobrazením chybových zpráv, které uživatele informují o tom, proč jsou data neplatná.

Umožňuje zobrazit vlastnosti modelu, které vyžadují ověření typu ValidatableObject<T>, a každá ValidatableObject<T> instance má do své Validations vlastnosti přidaná ověřovací pravidla. Ověření se vyvolá z modelu zobrazení voláním Validate metody ValidatableObject<T> instance, která načte ověřovací pravidla a provede je proti ValidatableObject<T>Value vlastnosti. Všechny chyby ověření se umístí do Errors vlastnosti ValidatableObject<T>instance a IsValid vlastnost ValidatableObject<T> instance se aktualizuje, aby indikovala, jestli ověření proběhlo úspěšně nebo selhalo.