web-dev-qa-db-fra.com

Comment valider la force du mot de passe avec Angular 5 Pattern Validator

Je dois valider la force d'un champ de formulaire de saisie de mot de passe.
Les exigences sont les suivantes:
- au moins un caractère minuscule
- au moins un caractère majuscule
- au moins un numéro
(peu importe l'ordre)

Ce que j'ai cherché et essayé jusqu'ici va en dessous, les résultats sont incohérents. Il semble valider l'ordre de la validation regex.
Ce dont j'ai besoin, c’est de vérifier si au moins un des "types" de caractères est présent.
Merci

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
    selector: 'signup',
    templateUrl: './signup.component.html',
    styleUrls: ['./signup.component.scss']
})
export class SignupComponent {

    form: FormGroup;

    constructor() {
        this.init();
    }

    init() {
        this.form = this.fb.group({
            name: ['', [Validators.required]],
            email: ['', [Validators.required, Validators.email],
            password: ['', [
                Validators.required, 
                Validators.pattern('((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,30})')
            ]]
        }); 
    }
}
16
guillefd

J'ai essayé de résoudre ce problème avec le validateur de modèle intégré d'Angular et j'ai pu trouver ce qui suit pour vérifier:

  • Au moins 8 caractères
  • Minuscules
  • Lettres capitales
  • Nombres
  • Caractères spéciaux

    password: [
      '',
      [
        Validators.required,
        Validators.pattern('(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&].{8,}')
       ]
    ]
    

J'ajouterai que je ne suis en aucun cas un expert en regex. C’est tout simplement ce qui a fonctionné pour moi pour un cas étroitement lié au PO. Peut-être que cela aidera quelqu'un d'autre. La documentation de Mozilla a beaucoup aidé à comprendre cela, en particulier la section Écriture d'un modèle d'expression régulière .

22
Desmond

Je n’ai pas pu utiliser correctement le motif Validator, j’ai donc créé un validateur personnalisé et validé la chaîne de champ du mot de passe avec trois expressions rationnelles simples.
Quoi qu'il en soit, j'ai hâte d'utiliser correctement le modèle de validation Angular.).

Validateur personnalisé

// password.validator.ts

import { FormControl } from '@angular/forms';

export interface ValidationResult {
    [key: string]: boolean;
}

export class PasswordValidator {

    public static strong(control: FormControl): ValidationResult {
        let hasNumber = /\d/.test(control.value);
        let hasUpper = /[A-Z]/.test(control.value);
        let hasLower = /[a-z]/.test(control.value);
        // console.log('Num, Upp, Low', hasNumber, hasUpper, hasLower);
        const valid = hasNumber && hasUpper && hasLower;
        if (!valid) {
            // return what´s not valid
            return { strong: true };
        }
        return null;
    }
}

Remplacé le motif du validateur par mon validateur personnalisé

// signup.component.ts

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { PasswordValidator } from 'validators/password.validator';

@Component({
    selector: 'signup',
    templateUrl: './signup.component.html',
    styleUrls: ['./signup.component.scss']
})
export class SignupComponent {

    form: FormGroup;

    constructor() {
        this.init();
    }

    init() {
        this.form = this.fb.group({
            name: ['', [Validators.required]],
            email: ['', [Validators.required, Validators.email],
            password: ['', [
                Validators.required, 
                PasswordValidator.strong
            ]]
        }); 
    }
}
13
guillefd

Si vous examinez Validator.js , vous remarquerez que vous pouvez passer à la fois une chaîne ou un littéral de regex au Validators.pattern.

Regex passé sous forme de littéral de chaîne

  • La chaîne entière doit correspondre au motif (c'est-à-dire que le motif est ancré des deux côtés)
  • Les barres obliques inverses peuvent former des séquences d'échappement de chaîne et vous devez utiliser une double barre oblique inversée pour définir une barre oblique inverse littérale utilisée pour définir un échappement de regex. Donc, pour définir un motif de correspondance, utilisez '\\d', pour définir un motif d’espace, utilisez '\\s', pour définir une barre oblique inverse, utilisez '\\\\'.

Regex passé comme un littéral de regex

  • L'expression régulière ne nécessite pas automatiquement une correspondance de chaîne complète.
  • Utilisez des barres obliques inverses uniques pour définir les échappements de regex (par exemple, /\s+/)

Donc, ce que vous pouvez utiliser est l’un des deux:

this.form = this.fb.group({
    name: ['', [Validators.required]],
    email: ['', [Validators.required, Validators.email],
    password: ['', [
        Validators.required, 
        Validators.pattern('(?=\\D*\\d)(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z]).{8,30}')
 ]]
});

Ou

this.form = this.fb.group({
    name: ['', [Validators.required]],
    email: ['', [Validators.required, Validators.email],
    password: ['', [
        Validators.required, 
        Validators.pattern(/^(?=\D*\d)(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z]).{8,30}$/)
 ]]
});

Détails sur les expressions rationnelles

Notez que les changements de modèle que je suggère sont simplement ceux liés à principe de contraste :

  • ^ - début de chaîne (implicite dans le motif chaîne regex)
  • (?=\D*\d) - il doit y avoir 1 chiffre
  • (?=[^a-z]*[a-z]) - il doit y avoir 1 minuscule ASCII lettre
  • (?=[^A-Z]*[A-Z]) _ - il doit y avoir 1 majuscule ASCII lettre
  • .{8,30} - 8 à 30 caractères autres que les caractères de saut de ligne
  • $ - fin de chaîne (implicite dans le motif chaîne regex).
3
Wiktor Stribiżew