本文目录导读:

前端验证(JavaScript)
使用原生HTML5验证
<input type="text"
pattern="[A-Za-z]+"
title="只允许英文字母"
required>
自定义JS验证函数
function validateCustom(value) {
// 自定义规则:必须以"ABC"开头
const regex = /^ABC/;
if (!regex.test(value)) {
return { valid: false, message: '必须以ABC开头' };
}
return { valid: true };
}
// 使用示例
const input = document.getElementById('myInput');
input.addEventListener('blur', function() {
const result = validateCustom(this.value);
if (!result.valid) {
showError(result.message);
}
});
使用验证库(如Yup)
import * as yup from 'yup';
const customSchema = yup.string()
.required('必填')
.test('is-valid-length', '长度必须在5-10之间', function(value) {
return value.length >= 5 && value.length <= 10;
})
.test('no-special-char', '不能包含特殊字符', function(value) {
return /^[a-zA-Z0-9]+$/.test(value);
});
// 使用
async function validateForm(data) {
try {
await customSchema.validate(data.username);
return { valid: true };
} catch (error) {
return { valid: false, message: error.message };
}
}
后端验证
Python (Flask + WTForms)
from wtforms import Form, StringField, validators
from wtforms.validators import ValidationError
class CustomForm(Form):
username = StringField('用户名', [
validators.DataRequired(),
validators.Length(min=3, max=20)
])
def validate_username(form, field):
# 自定义验证:禁止包含admin
if 'admin' in field.data.lower():
raise ValidationError('用户名不能包含admin')
# 自定义验证:必须是邮箱格式但排除特定域名
if not '@' in field.data:
raise ValidationError('请输入有效的邮箱')
if field.data.endswith('@example.com'):
raise ValidationError('不接受example.com邮箱')
# 使用示例
@app.route('/register', methods=['POST'])
def register():
form = CustomForm(request.form)
if form.validate():
return "表单有效"
return str(form.errors)
Java (Spring Boot + Hibernate Validator)
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.Payload;
// 1. 定义注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
public @interface ValidPhone {
String message() default "手机号格式不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// 2. 实现验证逻辑
public class PhoneValidator implements ConstraintValidator<ValidPhone, String> {
@Override
public void initialize(ValidPhone constraintAnnotation) {}
@Override
public boolean isValid(String phone, ConstraintValidatorContext context) {
if (phone == null) return false;
// 自定义验证:11位数字且以1开头
return phone.matches("^1[3-9]\\d{9}$");
}
}
// 3. 在实体中使用
public class User {
@ValidPhone
private String phone;
@Pattern(regexp = "^[a-zA-Z0-9]{5,20}$", message = "用户名必须5-20位字母数字")
private String username;
}
数据库级验证(PostgreSQL)
-- 创建自定义域
CREATE DOMAIN positive_integer AS INTEGER
CHECK (VALUE > 0);
-- 或使用检查约束
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE,
age INTEGER CHECK (age >= 0 AND age <= 150),
status VARCHAR(20) CHECK (status IN ('active', 'inactive', 'banned'))
);
完整示例:前端+后端组合验证
前端 (Vue 3 + VeeValidate)
// 自定义验证规则
import { defineRule } from 'vee-validate';
defineRule('strong_password', (value, [min]) => {
if (!value || !value.length) {
return '密码是必填项';
}
// 检查长度
if (value.length < min) {
return `密码长度不能小于${min}位`;
}
// 检查包含大写字母
if (!/[A-Z]/.test(value)) {
return '密码必须包含大写字母';
}
// 检查包含数字
if (!/[0-9]/.test(value)) {
return '密码必须包含数字';
}
return true;
});
// 在组件中使用
<template>
<input v-model="password" name="password"
:rules="'strong_password:8'" />
</template>
后端 (Node.js + Express-validator)
const { body, validationResult } = require('express-validator');
// 自定义验证器
const customValidators = {
isStrongPassword: (value) => {
if (!value || value.length < 8) {
throw new Error('密码长度至少8位');
}
if (!/[A-Z]/.test(value)) {
throw new Error('密码必须包含大写字母');
}
if (!/[0-9]/.test(value)) {
throw new Error('密码必须包含数字');
}
return true;
},
isNotBannedUser: async (value) => {
const bannedUsers = ['spam1', 'spam2'];
if (bannedUsers.includes(value.toLowerCase())) {
throw new Error('该用户名已被禁用');
}
return true;
}
};
// 路由中使用
app.post('/register', [
body('username')
.isLength({ min: 3, max: 20 })
.custom(customValidators.isNotBannedUser),
body('password')
.custom(customValidators.isStrongPassword)
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// 处理注册逻辑
});
- 前端验证:提升用户体验,但不可靠(可绕过)
- 后端验证:必须的,数据安全的第一道防线
- 数据库验证:最终保障,防止错误数据入库
- 统一规则:前后端验证规则保持一致
- 错误信息:提供清晰、友好的错误提示
选择哪种方式取决于你的技术栈和需求,通常建议前端+后端双重验证来确保数据安全。