如何在满足最少条件时使用 yup 验证密码

How to validate a password with yup when minimum amount of conditions met

我正在尝试使用 yup 进行密码验证,其中至少满足 4 个密码条件中的 3 个。我无法找到执行此操作的现有方法。

我的要求是这样的:

At least 8 characters It must use characters from at least three of the following four character types: • English alphabet uppercase letters (A-Z) • English alphabet lowercase letters (a-z) • Numerals (0-9) • Non-alphanumeric symbols (such as !, #, $, %)

我的验证(使用 react-hook-form)是这样的:

newPassword: yup
.string()
.required('Please enter a password')
.min(8, 'Password too short')
.matches(/^(?=.*[a-z])/, 'Must contain at least one lowercase character')
.matches(/^(?=.*[A-Z])/, 'Must contain at least one uppercase character')
.matches(/^(?=.*[0-9])/, 'Must contain at least one number')
.matches(/^(?=.*[!@#%&])/, 'Must contain at least one special character'),

问题当然是这使得所有 4 个条件都成为必需条件,而 4 个条件中只需要至少 3 个条件。解决此问题的任何帮助将不胜感激!谢谢

我建议您使用 yup 方法 yup.test() 编写自定义测试函数,如下所示,当您有自定义测试时,如果您想重用,也可以使用 yup.addMethod() 扩展它测试函数

 password: Yup.string()
      .required("Please enter a password")
      .min(8, "Password too short")
      .test("isValidPass", " is not valid", (value, context) => {
        const hasUpperCase = /[A-Z]/.test(value);
        const hasLowerCase = /[a-z]/.test(value);
        const hasNumber = /[0-9]/.test(value);
        const hasSymbole = /[!@#%&]/.test(value);
        let validConditions = 0;
        const numberOfMustBeValidConditions = 3;
        const conditions = [hasLowerCase, hasUpperCase, hasNumber, hasSymbole];
        conditions.forEach((condition) =>
          condition ? validConditions++ : null
        );
        if (validConditions >= numberOfMustBeValidConditions) {
          return true;
        }
        return false;
      })

这是一个带有工作示例的演示codesandbox

希望它能提供完整的帮助(使用密码和确认密码验证)并且它会满足所有密码要求。

import * as yup from 'yup';

 const PasswordValidation = yup.object().shape({
  password: yup
    .string()
    .required('Password Required')
    .min(8, 'Password too short')
    .test(
      'isValidPass',
      'Passowrd must be 8 char (One UpperCase & One Symbol)',
      (value: any, context: any) => {
        const hasUpperCase = /[A-Z]/.test(value);
        const hasNumber = /[0-9]/.test(value);
        const hasLowerCase = /[a-z]/.test(value);
        const hasSymbole = /["!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"]/.test(value);
        let validConditions = 0;
        const numberOfMustBeValidConditions = 3;
        const conditions = [hasUpperCase, hasLowerCase, hasNumber, hasSymbole];
        conditions.forEach(condition => (condition ? validConditions++ : null));
        if (validConditions >= numberOfMustBeValidConditions) {
          return true;
        }
        return false;
      },
    ),
  confirmpassword: yup
    .string()
    .required('Confirm Password Required')
    .oneOf([yup.ref('password'), null], 'Passwords must match'),
});