Formik,是的,使用 React 进行密码强度验证
Formik, Yup Password Strength Validation with React
我是 React 的新手,我有一个注册页面,其中有一个密码字段需要使用 Regex 进行验证。
我正在使用 Formik 和 Yup 进行验证,但我遇到了一个错误,当我在 "password" 字段中键入时,它说正在调用长度函数的 属性 未定义。
yup 中有一个名为 "matches" 的函数,我正试图利用它来检查正则表达式。那是我收到此错误的时间。我删除了此验证,之后设置为密码字段的其他验证工作正常。
下面是 SignUp.js 文件的代码:-
import React from "react";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import "./SignUp.css";
import * as yup from "yup";
import { Formik } from "formik";
const schema = yup.object({
username: yup.string().required('Please Enter a username'),
email: yup
.string()
.email()
.required('Please Enter your Email'),
confirmEmail: yup
.string()
.email()
.required()
.oneOf([yup.ref("email"), null], "Emails must match"),
password: yup
.string()
.required('Please Enter your password')
.matches(
"^(?=.*[A-Za-z])(?=.*d)(?=.*[@$!%*#?&])[A-Za-zd@$!%*#?&]{8,}$",
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
),
confirmPassword: yup
.string()
.required()
.oneOf([yup.ref("password"), null], "Passwords must match")
});
const SignUp = props => {
return (
<Formik
validationSchema={schema}
onSubmit={console.log}
initialValues={{
username: "",
email : "",
confirmEmail : "",
password: "",
confirmPassword : ""
}}
>
{({
handleSubmit,
handleChange,
handleBlur,
values,
touched,
isValid,
errors,
}) => (
<div className="SignUpForm">
<h1 className="SignInHeading">SIGN UP</h1>
<Form noValidate onSubmit={handleSubmit}>
<Form.Group controlId="formBasicUserName">
<Form.Control
size="lg"
className="SignUpFormControls"
type="text"
name="username"
value={values.username}
onChange={handleChange}
placeholder="Username"
isInvalid={!!errors.username}
/>
<Form.Control.Feedback className="FeedBack" type="invalid">
{errors.username}
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formBasicEmail">
<Form.Control
type="email"
placeholder="Email"
value={values.email}
onChange={handleChange}
name="email"
className="SignUpFormControls"
size="lg"
isInvalid={!!errors.email}
/>
<Form.Control.Feedback className="FeedBack" type="invalid">
{errors.email}
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formBasicConfirmEmail">
<Form.Control
type="email"
className="SignUpFormControls"
size="lg"
name="confirmEmail"
value = {values.confirmEmail}
onChange={handleChange}
placeholder="Confirm Email"
isInvalid={!!errors.confirmEmail}
/>
<Form.Control.Feedback className="FeedBack" type="invalid">
{errors.confirmEmail}
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Control
className="SignUpFormControls"
size="lg"
type="password"
name="password"
value={values.password}
onChange={handleChange}
placeholder="Password"
isInvalid={!!errors.password}
/>
<Form.Control.Feedback className="FeedBack" type="invalid">
{errors.password}
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formBasicConfirmPassword">
<Form.Control
className="SignUpFormControls"
size="lg"
name="confirmPassword"
onChange={handleChange}
type="password"
value={values.confirmPassword}
placeholder="Confirm Password"
isInvalid={!!errors.confirmPassword}
/><Form.Control.Feedback className="FeedBack" type="invalid">
{errors.confirmPassword}
</Form.Control.Feedback>
</Form.Group>
<Button variant="primary" className="SignUpButton" type="submit">
Sign Up
</Button>
<Form.Text>
Already a User?{" "}
<a href="#signin" onClick={props.toggle}>
Sign In
</a>
</Form.Text>
</Form>
</div>)}
</Formik>
);
};
export default SignUp;
这是 chrome 控制台中的错误:-
formik.esm.js:721 Uncaught (in promise) TypeError: Cannot read property 'length' of undefined
at yupToFormErrors (formik.esm.js:721)
at formik.esm.js:276
好的,经过几个小时的修改,我决定改用自己的自定义验证。
这是我所做的:-
password: yup
.string()
.required("Please Enter your password")
.test(
"regex",
"Password must be min 8 characters, and have 1 Special Character, 1 Uppercase, 1 Number and 1 Lowercase",
val => {
let regExp = new RegExp(
"^(?=.*\d)(?=.*[!@#$%^&*])(?=.*[a-z])(?=.*[A-Z]).{8,}$"
);
console.log(regExp.test(val), regExp, val);
return regExp.test(val);
}
)
目前,这工作正常。但我真的很想知道为什么会弹出错误。如果您能找到解决方案,请post将其作为答案,如果它对我有用,我会将其标记为正确答案。谢谢
您需要将实际的 RegExp 对象传递给 matches
,而不是字符串。只需将密码模式中的双引号替换为正斜杠:
编辑:更新为使用来自@Bren
的正则表达式
password: yup
.string()
.required('Please Enter your password')
.matches(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%\^&\*])(?=.{8,})/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character"
),
None 以上对我有用,下面是我的解决方案
password: yup
.string()
.required("Şifreniz kayıt olmak için gereklidir.")
.matches(
/^.*(?=.{8,})((?=.*[!@#$%^&*()\-_=+{};:,<.>]){1})(?=.*\d)((?=.*[a-z]){1})((?=.*[A-Z]){1}).*$/,
"En Az 8 Karakter, Bir Büyük Harf, Bir Küçük Harf, Bir Rakam ve Bir Özel Karakter İçermelidir"
)
这是我终于开始工作的。
password: Yup.string()
.required('Please Enter your password')
.matches(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%\^&\*])(?=.{8,})/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character"
),
我从这篇文章中获取了这个正则表达式字符串:https://www.thepolyglotdeveloper.com/2015/05/use-regex-to-test-password-strength-in-javascript/
这对我有用:
password: yup
.string()
.required('Password is required')
.matches(regExp)
.min(6, 'Your password must be longer than 6 characters.')
昨晚遇到这个问题试图解决类似的 React+Formik+Yup 密码验证问题。总的来说,这里的解决方案很好。我只是评论提供一个稍微不同的正则表达式:
/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,}$/
这在第四个前瞻中有所不同。在此版本中,它会查找 任何非字母或数字的内容。之前的RE都将“特殊字符”的定义限制在8个左右的特定字符。这将匹配更广泛的范围。
我最初使用的是 (?=.*[^\w])
,它否定了“单词”class (\w
),但是 class 包含了下划线。所以这样做不会将下划线视为特殊字符。
当我搜索这个答案时,我在网上找到的大多数答案(即使是在该线程中标记为正确答案的答案)都是这样的,不检查大写字符:
password: yup
.string()
.required('Please Enter your password')
.matches(
/^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
),
但对我来说,这实际上并没有检查是否同时存在大写和小写字符。不过这对我有用(检查特殊字符、大写字符、小写字符和数字):
password: yup
.string()
.required('Please Enter your password')
.matches(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
),
考虑到上面的所有答案并经过一些研究,一个综合的方法可以是检查密码的强度:
password: Yup
.string()
.required('Required')
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
)
但是,此方法不适用于所有特殊字符。如果您想要包括所列的所有可能的特殊字符 here。这个解决方案可以修改为:
password: Yup
.string()
.required('Required')
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~])[A-Za-z\d!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]{8,}$/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
)
这是我在申请中采用的解决方案。但这完全是您的选择,您希望从密码强度检查中 include/exclude 哪些特殊字符。
yup.addMethod(yup.string, "strongPassword", strongPasswordMethod);
function strongPasswordMethod() {
return this.test("strongPasswordTest", _, function (value) {
const { path, createError } = this;
switch (Boolean(value)) {
case !/^(?=.*[a-z])/.test(value):
return createError({ path, message: "password must include lowercase letter" });
case !/^(?=.*[A-Z])/.test(value):
return createError({ path, message: "password must include uppercase letter" });
case !/^(?=.*[0-9])/.test(value):
return createError({ path, message: "password must include digit" });
case !/^(?=.*[!@#$%\^&\*])/.test(value):
return createError({ path, message: "password must include special character" });
default:
return true;
}
});
};
const schema = yup.object().shape({
password: yup.string().required().strongPassword()
});
我决定改用自己的自定义验证。
这是我所做的:-
password: Yup.string()
.required("Please Enter your password")
.min(5, "Your password must be longer than 5 characters.")
.max(25)
.matches(/^(?=.{6,})/, "Must Contain 6 Characters")
.matches(
/^(?=.*[a-z])(?=.*[A-Z])/,
"Must Contain One Uppercase, One Lowercase"
)
.matches(
/^(?=.*[!@#$%\^&\*])/,
"Must Contain One Special Case Character"
)
.matches(/^(?=.{6,20}$)\D*\d/, "Must Contain One Number"),
您可以在此处使用正则表达式来验证密码强度。
使用 .matches(REGEX HERE)
您可以在密码中添加任意数量的条件。
示例:
password: Yup
.string()
.required('Required')
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
)
参考:
我是 React 的新手,我有一个注册页面,其中有一个密码字段需要使用 Regex 进行验证。
我正在使用 Formik 和 Yup 进行验证,但我遇到了一个错误,当我在 "password" 字段中键入时,它说正在调用长度函数的 属性 未定义。
yup 中有一个名为 "matches" 的函数,我正试图利用它来检查正则表达式。那是我收到此错误的时间。我删除了此验证,之后设置为密码字段的其他验证工作正常。
下面是 SignUp.js 文件的代码:-
import React from "react";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import "./SignUp.css";
import * as yup from "yup";
import { Formik } from "formik";
const schema = yup.object({
username: yup.string().required('Please Enter a username'),
email: yup
.string()
.email()
.required('Please Enter your Email'),
confirmEmail: yup
.string()
.email()
.required()
.oneOf([yup.ref("email"), null], "Emails must match"),
password: yup
.string()
.required('Please Enter your password')
.matches(
"^(?=.*[A-Za-z])(?=.*d)(?=.*[@$!%*#?&])[A-Za-zd@$!%*#?&]{8,}$",
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
),
confirmPassword: yup
.string()
.required()
.oneOf([yup.ref("password"), null], "Passwords must match")
});
const SignUp = props => {
return (
<Formik
validationSchema={schema}
onSubmit={console.log}
initialValues={{
username: "",
email : "",
confirmEmail : "",
password: "",
confirmPassword : ""
}}
>
{({
handleSubmit,
handleChange,
handleBlur,
values,
touched,
isValid,
errors,
}) => (
<div className="SignUpForm">
<h1 className="SignInHeading">SIGN UP</h1>
<Form noValidate onSubmit={handleSubmit}>
<Form.Group controlId="formBasicUserName">
<Form.Control
size="lg"
className="SignUpFormControls"
type="text"
name="username"
value={values.username}
onChange={handleChange}
placeholder="Username"
isInvalid={!!errors.username}
/>
<Form.Control.Feedback className="FeedBack" type="invalid">
{errors.username}
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formBasicEmail">
<Form.Control
type="email"
placeholder="Email"
value={values.email}
onChange={handleChange}
name="email"
className="SignUpFormControls"
size="lg"
isInvalid={!!errors.email}
/>
<Form.Control.Feedback className="FeedBack" type="invalid">
{errors.email}
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formBasicConfirmEmail">
<Form.Control
type="email"
className="SignUpFormControls"
size="lg"
name="confirmEmail"
value = {values.confirmEmail}
onChange={handleChange}
placeholder="Confirm Email"
isInvalid={!!errors.confirmEmail}
/>
<Form.Control.Feedback className="FeedBack" type="invalid">
{errors.confirmEmail}
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Control
className="SignUpFormControls"
size="lg"
type="password"
name="password"
value={values.password}
onChange={handleChange}
placeholder="Password"
isInvalid={!!errors.password}
/>
<Form.Control.Feedback className="FeedBack" type="invalid">
{errors.password}
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formBasicConfirmPassword">
<Form.Control
className="SignUpFormControls"
size="lg"
name="confirmPassword"
onChange={handleChange}
type="password"
value={values.confirmPassword}
placeholder="Confirm Password"
isInvalid={!!errors.confirmPassword}
/><Form.Control.Feedback className="FeedBack" type="invalid">
{errors.confirmPassword}
</Form.Control.Feedback>
</Form.Group>
<Button variant="primary" className="SignUpButton" type="submit">
Sign Up
</Button>
<Form.Text>
Already a User?{" "}
<a href="#signin" onClick={props.toggle}>
Sign In
</a>
</Form.Text>
</Form>
</div>)}
</Formik>
);
};
export default SignUp;
这是 chrome 控制台中的错误:-
formik.esm.js:721 Uncaught (in promise) TypeError: Cannot read property 'length' of undefined
at yupToFormErrors (formik.esm.js:721)
at formik.esm.js:276
好的,经过几个小时的修改,我决定改用自己的自定义验证。
这是我所做的:-
password: yup
.string()
.required("Please Enter your password")
.test(
"regex",
"Password must be min 8 characters, and have 1 Special Character, 1 Uppercase, 1 Number and 1 Lowercase",
val => {
let regExp = new RegExp(
"^(?=.*\d)(?=.*[!@#$%^&*])(?=.*[a-z])(?=.*[A-Z]).{8,}$"
);
console.log(regExp.test(val), regExp, val);
return regExp.test(val);
}
)
目前,这工作正常。但我真的很想知道为什么会弹出错误。如果您能找到解决方案,请post将其作为答案,如果它对我有用,我会将其标记为正确答案。谢谢
您需要将实际的 RegExp 对象传递给 matches
,而不是字符串。只需将密码模式中的双引号替换为正斜杠:
编辑:更新为使用来自@Bren
的正则表达式password: yup
.string()
.required('Please Enter your password')
.matches(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%\^&\*])(?=.{8,})/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character"
),
None 以上对我有用,下面是我的解决方案
password: yup
.string()
.required("Şifreniz kayıt olmak için gereklidir.")
.matches(
/^.*(?=.{8,})((?=.*[!@#$%^&*()\-_=+{};:,<.>]){1})(?=.*\d)((?=.*[a-z]){1})((?=.*[A-Z]){1}).*$/,
"En Az 8 Karakter, Bir Büyük Harf, Bir Küçük Harf, Bir Rakam ve Bir Özel Karakter İçermelidir"
)
这是我终于开始工作的。
password: Yup.string()
.required('Please Enter your password')
.matches(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%\^&\*])(?=.{8,})/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character"
),
我从这篇文章中获取了这个正则表达式字符串:https://www.thepolyglotdeveloper.com/2015/05/use-regex-to-test-password-strength-in-javascript/
这对我有用:
password: yup
.string()
.required('Password is required')
.matches(regExp)
.min(6, 'Your password must be longer than 6 characters.')
昨晚遇到这个问题试图解决类似的 React+Formik+Yup 密码验证问题。总的来说,这里的解决方案很好。我只是评论提供一个稍微不同的正则表达式:
/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,}$/
这在第四个前瞻中有所不同。在此版本中,它会查找 任何非字母或数字的内容。之前的RE都将“特殊字符”的定义限制在8个左右的特定字符。这将匹配更广泛的范围。
我最初使用的是 (?=.*[^\w])
,它否定了“单词”class (\w
),但是 class 包含了下划线。所以这样做不会将下划线视为特殊字符。
当我搜索这个答案时,我在网上找到的大多数答案(即使是在该线程中标记为正确答案的答案)都是这样的,不检查大写字符:
password: yup
.string()
.required('Please Enter your password')
.matches(
/^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
),
但对我来说,这实际上并没有检查是否同时存在大写和小写字符。不过这对我有用(检查特殊字符、大写字符、小写字符和数字):
password: yup
.string()
.required('Please Enter your password')
.matches(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
),
考虑到上面的所有答案并经过一些研究,一个综合的方法可以是检查密码的强度:
password: Yup
.string()
.required('Required')
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
)
但是,此方法不适用于所有特殊字符。如果您想要包括所列的所有可能的特殊字符 here。这个解决方案可以修改为:
password: Yup
.string()
.required('Required')
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~])[A-Za-z\d!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]{8,}$/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
)
这是我在申请中采用的解决方案。但这完全是您的选择,您希望从密码强度检查中 include/exclude 哪些特殊字符。
yup.addMethod(yup.string, "strongPassword", strongPasswordMethod);
function strongPasswordMethod() {
return this.test("strongPasswordTest", _, function (value) {
const { path, createError } = this;
switch (Boolean(value)) {
case !/^(?=.*[a-z])/.test(value):
return createError({ path, message: "password must include lowercase letter" });
case !/^(?=.*[A-Z])/.test(value):
return createError({ path, message: "password must include uppercase letter" });
case !/^(?=.*[0-9])/.test(value):
return createError({ path, message: "password must include digit" });
case !/^(?=.*[!@#$%\^&\*])/.test(value):
return createError({ path, message: "password must include special character" });
default:
return true;
}
});
};
const schema = yup.object().shape({
password: yup.string().required().strongPassword()
});
我决定改用自己的自定义验证。
这是我所做的:-
password: Yup.string()
.required("Please Enter your password")
.min(5, "Your password must be longer than 5 characters.")
.max(25)
.matches(/^(?=.{6,})/, "Must Contain 6 Characters")
.matches(
/^(?=.*[a-z])(?=.*[A-Z])/,
"Must Contain One Uppercase, One Lowercase"
)
.matches(
/^(?=.*[!@#$%\^&\*])/,
"Must Contain One Special Case Character"
)
.matches(/^(?=.{6,20}$)\D*\d/, "Must Contain One Number"),
您可以在此处使用正则表达式来验证密码强度。
使用 .matches(REGEX HERE)
您可以在密码中添加任意数量的条件。
示例:
password: Yup
.string()
.required('Required')
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and one special case Character"
)
参考: