Эта статья включена в блог GitHub Shanyuexing:shfshanyue/blog, который содержит проблемы, с которыми я столкнулся в реальной работе, размышлениях о бизнесе и обучении в направлении полного стека.
Юмористические back-end программисты обычно высмеивают себя как CURD Boy. CURD, то есть добавление, удаление, изменение и проверка ресурса хранения, является полностью ориентированным на данные программированием.
Это здорово, программирование, ориентированное на данные, имеет тенденцию более глубоко понимать бизнес, чтобы писать более качественный код и создавать меньше ошибок. Поскольку это программирование, ориентированное на данные, более необходимо избегать появления грязных данных и усиливать проверку данных. В противном случае нужно ли доверять проверке данных внешнего интерфейса?В конце концов, проверка данных внешнего интерфейса идет непосредственно к пользователю для более удобной обратной связи с пользователем на уровне пользовательского интерфейса.
Слой проверки данных
Серверная часть разделена на различные уровни из-за тяжелой бизнес-логики и различных данных, которые необходимо обработать.Controller
,Service
,Model
,Helper
,Entity
Существуют различные именованные слои и так далее. Но здесь определенно есть слой, называемыйController
, стоящий на верхнем уровне серверной части, чтобы напрямую получать данные, передаваемые клиентом.
из-заController
Уровень — это верхний уровень взаимодействия данных на стороне сервера с клиентом, придерживающийсяFail Fast
Принцип , берет на себя функцию фильтра данных и напрямую наносит ответный удар незаконным данным, таким же величественным, как Цинь Цюн и Ючи Гунмэнь.
Проверка данных также создает полудокументированный побочный продукт.Вам нужно только взглянуть на слой проверки данных, чтобы узнать, какие поля и в каком формате передавать.
Ниже приведены общие проверки данных, и в этой статье описывается, как их проверить:
- required/optional
- Проверка основных данных, таких как число, строка, отметка времени и условия, которым должно соответствовать значение.
- Сложная проверка данных, таких как IP, номер мобильного телефона, электронная почта и доменное имя
const body = {
id,
name,
mobilePhone,
email
}
Shanyue связалась с серверным проектом без уровня проверки данных.if/else
Наполненный различными уровнями, он крайне болезненный, а рефакторится за считанные минуты.
JSON Schema
JSON Schema
Формат проверки данных на основе JSON со спецификациейjson-schema.org, текущая (2020-08) последняя версия — 7.0. Спецификацию реализуют различные серверные языки программирования, такие какgo
,java
,php
и т. д., конечно, есть и отличные javascripts, такие как tepidajv.
Ниже приведена схема проверки информации о пользователе, видно, что синтаксис сложный и громоздкий:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "User",
"description": "用户信息",
"type": "object",
"properties": {
"id": {
"description": "用户 ID",
"type": "integer"
},
"name": {
"description": "用户姓名",
"type": "string"
},
"email": {
"description": "用户邮箱",
"type": "string",
"format": "email",
"maxLength": 20
},
"mobilePhone": {
"description": "用户手机号",
"type": "string",
"pattern": "^(?:(?:\+|00)86)?1[3-9]\d{9}$",
"maxLength": 15
}
},
"required": ["id", "name"]
}
Для проверки сложных типов данных схема JSON имеет следующие встроенные форматы, которые удобно и быстро проверить.
- Dates and times
- Email addresses
- Hostnames
- IP Addresses
- Resource identifiers
- URI template
- JSON Pointer
- Regular Expressions
Для мобильных номеров не во встроенном формате используйтеajv.addFormat
Формат можно добавить вручную
ajv.addFormat('mobilePhone', (str) => /^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(str));
Joi
joiСамопровозглашенная самая мощная библиотека проверки JS также получила 16 000 звезд на github. По сравнению со схемой JSON ее синтаксис более краткий и мощный.
The most powerful data validation library for JS
Выполнение той же проверки требует меньше кода и обеспечивает более надежную проверку. Ниже приведен только пример, дополнительные примеры можно найти в документации.
const schema = Joi.object({
id: Joi.number().required(),
name: Joi.number().required(),
email: Joi.string().email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } }),
mobilePhone: Joi.string().pattern(/^(?:(?:\+|00)86)?1[3-9]\d{9}$/),
password: Joi.string().pattern(/^[a-zA-Z0-9]{3,30}$/),
// 与 password 相同的校验
repeatPassword: Joi.ref('password'),
})
// 密码与重复密码需要同时发送
.with('password', 'repeat_password');
// 邮箱与手机号提供一个即可
.xor('email', 'mobilePhone')
Проверка данных и интеграция уровня маршрутизации
Поскольку данные передаются непосредственно из маршрута,koajs
Официально на основеjoi
понялjoi-router, внешние данные проверяются на уровне маршрутизации, а данные передаются от внешнего интерфейса.query
,body
а такжеparams
Проверьте это.
joi-router
также на основеco-body
Различные типы передних трансмиссийcontent-type
Разбирать и ограничивать. если ограничитьсяapplication/json
, он также может в определенной степени предотвратить атаки CSRF.
const router = require('koa-joi-router');
const public = router();
public.route({
method: 'post',
path: '/signup',
validate: {
header: joiObject,
query: joiObject,
params: joiObject,
body: joiObject,
maxBody: '64kb',
output: { '400-600': { body: joiObject } },
type: 'json',
failure: 400,
continueOnError: false
},
pre: async (ctx, next) => {
await checkAuth(ctx);
return next();
},
handler: async (ctx) => {
await createUser(ctx.request.body);
ctx.status = 201;
},
});
Регулярные выражения и безопасные регулярные выражения
Когда Шаньюэ исследовал проблемы с производительностью, он обнаружил, что API занимает слишком много времени на уровне проверки данных, о чем я никогда не думал. Корень проблемы лежит в небезопасных регулярных выражениях, так что же такое небезопасное регулярное выражение?
Например, приведенное ниже регулярное выражение, которое может повесить ЦП, — это бомба замедленного действия, а количество возвратов вошло в экспоненциальный взрыв.
Вы можете обратиться к статьеАнализ принципа и практики Redos
const safe = require('safe-regex')
const re = /(x+x+)+y/
// 能跑死 CPU 的一个正则
re.test('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
// 使用 safe-regex 判断正则是否安全
safe(re) // false
Верификация данных в основном направлена на проверку строк, а также насыщена различными регулярными выражениями, очень важно обеспечить безопасность регулярных выражений.safe-regexМожет обнаружить, какие небезопасные регулярные выражения.
Суммировать
- Уровень контроллера должен выполнять унифицированную проверку данных и может использовать схему JSON (узел реализует ajv) и Joi.
- У JSON Schema есть официальные спецификации и реализации на разных языках, но синтаксис громоздкий, можно использовать Joi, у которого более мощная функция проверки.
- При проверке строки обратите внимание на проблемы с производительностью, вызванные небезопасным