Брат фронтенд написал бэкенд первый раз, и он рухнул!

задняя часть
Брат фронтенд написал бэкенд первый раз, и он рухнул!

Юмористическое и легкое знание, давайте взглянем на внутренний код, который мой брат написал впервые, что вы думаете?

Привет всем, я Юпи. Сегодня я делюсь неловким случаем, когда мой брат впервые написал код бэкенда. Надеюсь, все смогут извлечь урок.

восстание

Мой брат, Сяо Аба, в настоящее время первокурсник, он некоторое время изучал программирование самостоятельно, раньше он в основном занимался интерфейсным обучением, поэтому ему было легче начать.

Но этот парень не знает, что происходит в последнее время, и требует написать внутренний код.

Я сказал: Вы только что изучили фронтенд уже давно, так что куда торопиться?

Сяо Аба сказал: «Никто не знает переднюю часть лучше меня!

Молодец, не ожидал тебя увидеть через несколько дней, этот парень так горд сейчас! Это должно убить его дух, дать ему оценить ужас задней части.

Так что я сказал: хорошо, недавно я разрабатывал новую функцию [Удалить сообщения], Функция очень простая, позволяющая пользователям удалять сообщения, которые они уже прочитали. Фронтенд и бэкенд весь передан вам, и время не торопится, я даю вам две недели, берите на практику и знакомьтесь со следующим проектом~

Неожиданно собака Сяо Аба сказала: две недели? На кого ты смотришь свысока, просто такая маленькая функция, я тебе ее за 3 дня исправлю!

Я был в шоке: молодежь сейчас такая сильная? Хорошо, я буду ждать тебя!

Неожиданно менее чем за 3 дня Сяо Аба действительно представил код, давайте посмотрим на его идеи реализации и код.

Реализовать идеи

Реализация функции включает в себя две части: front-end и back-end, давайте подумаем об этом отдельно.

внешний интерфейс

Для реализации функции удаления сообщений, которые были прочитаны пользователями, фронтенд работает относительно просто, добавляя кнопку удаления, и добавляя событие нажатия на кнопку, и вызывая бэкенд после нажатия消息删除интерфейс.

前端界面

Интерфейсный код, написанный Сяо Аба:

<!-- 伪代码 -->
<button onClick={doDelete(消息)}>删除</button>
<script>
  // 删除消息
  function doDelete(msg) {
    // 消息 id 存在且为已读
    if(msg.id && msg.isRead) {
      // 调用后端接口
      service.deleteMsgById(msg.id);
    }
  }
</script>

Вроде проблем нет, написание достаточно аккуратное, а спецификация кода хвалят!

Посмотрим, как выглядит задняя часть.

задняя часть

Серверная часть должна принять запрос от внешнего интерфейса, управлять базой данных, удалить сообщение с указанным идентификатором в базе данных, а затем сообщить внешнему интерфейсу об успешном удалении.

存放消息的数据库

Для написания бэкэндов можно использовать многие языки программирования, такие как Java, Go и т. д. Но так как Сяо Аба впервые делал бэкенд, мне было его жаль, поэтому пусть он использует NodeJS (синтаксис JavaScript) для его написания.

Взгляните на внутренний код, написанный Сяо Аба:

// 删除消息接口
// @params msgId 消息 id
function deleteMsgById(msgId) {
  // 调用数据库删除函数,得到结果
  const res = db.deleteById(msgId);
  return res;
}

Всего несколько строчек кода, все лаконично и понятно, неудивительно, что Сяо Аба потратил 3 дня на его написание.

Я не знаю, что все думают об этом коде, он похож на код, который я написал в первый раз?

Пожалуйста, подумайте об этом, нет ли проблем с кодом, который он написал?

анализировать проблему

На самом деле проблема кода Сяо Аба очень большая! После выхода в интернет последствия невообразимы!

Есть три основные проблемы.Я позвонил Сяо Аба, чтобы дать ему набор в зависимости от серьезности проблемы.

1. Не проверено

Я сказал Сяо Аба: «Присмотритесь к своему коду, не хватает ли логики проверки?»

Маленький Аба задается вопросом: я не сужу, существует ли идентификатор сообщения и было ли сообщение прочитано на внешнем интерфейсе?

Я: Что, если пользователь не нажимает кнопку удаления в браузере, а напрямую запрашивает интерфейс и небрежно передает идентификатор сообщения?

Маленький Аба задумался.

Это частая ошибка студентов, которые впервые пишут фон, особенно когда фронт и бэкенд пишет один человек, думая, что этого достаточно, чтобы судить о том, допустимы ли параметры во фронтенде. Но на самом деле злоумышленникам все равно, они могут напрямую использовать различные инструменты для отправки запросов к вашему бэкенду вне браузера, передачи некоторых идентификаторов сообщений или даже прямого обхода возможных идентификаторов. Если серверная часть не выполняет проверку, сообщения обычных пользователей могут быть удалены, как только они выходят в сеть! абсолютныйпревосходная авария!

Сяо Аба: Не ожидал, что все так серьезно, поэтому дополняю проверку статуса сообщения в фоновом режиме, вроде не работает? Ведь пользователи могут произвольно передавать параметры запроса.

Я: Это довольно умно, это правда, поэтому мы должны компенсировать проверку текущего пользователя, вошедшего в систему.

Полный код примерно такой:

// 删除消息接口
// @params msgId 消息 id
function deleteMsgById(msgId) {
  // 校验参数合法性
  if (!mgsId) {
    return false;
  }
  // 从数据库查消息最新状态
  const msg = db.getMsgById(msgId);
  // 从 session 或中间件获取当前用户信息
  const user = getCurrentUser();
  // 消息未读或不是该用户的消息
  if (!msg.isRead || !user || msg.userId !== user.id) {
    return false;
  }
  // 调用数据库删除函数,得到结果
  return db.deleteById(msgId);
}

Сяо Аба: Я помню, внутренний интерфейс — это основа бизнеса, мы должны усилить проверку!

Я: Да, давайте посмотрим на другие вопросы.

2. Жесткое удаление

я: В вашем коде звоните напрямуюdeleteФункция удаляет данные напрямую, знаете, что с этим не так?

Маленький Абба: В чем проблема?

Я: удаление данных напрямую оставляет администраторов без подсказок, когда им нужно устранять неполадки. Например, если пользователь отправляет сообщение о нарушении, а затем через некоторое время удаляет сообщение, администратор не сможет узнать его запись о нарушении.

Маленький авва: В самом деле, что мне тогда делать? Можно ли удалить эти данные?

Я: обычно软删除, добавьте дополнительное поле в таблицу данных, чтобы указать статус удаления, напримерisDelete, статус 0 означает не удалено, а 1 означает удалено. В обычных условиях пользователю отображаются только данные с isDelete = 0. При удалении значение этого поля может обновляться с 0 до 1.

Таким образом, последнюю часть приведенного выше кода можно немного изменить:

// 原代码,真实删除
db.deleteById(msgId)
// 新代码,软删除(更新)
db.updateById(msgId, {isDelete: 1})

Таким образом, внутренний код в основном идеален.

Конечно, не все таблицы данных нуждаются в мягком удалении, которое должно решаться в соответствии с бизнес-сценарием.

3. Нет защиты от случайного прикосновения

Наконец, есть небольшая проблема в работе с продуктом: рекомендуется, чтобы когда пользователь нажимал кнопку «Удалить», появлялось всплывающее окно для вторичного подтверждения, иначе пользователь случайно нажмет не ту кнопку и рассердится, если он хочет найти сообщение, но не может найти его обратно. !

确认删除

Чем больше вы будете заниматься фронтенд-разработкой, тем больше вы будете обращать внимания на эти мелкие детали, ведь это очень важно для улучшения пользовательского опыта!


Маленький Абба: Понял, понял! Я хорошо готовлю 555.

Я: Ничего, это нормально, если ты исправишь свои ошибки, у тебя все равно все будет хорошо, Аба.

Многие ли друзья, читающие статью, тоже совершали эти маленькие ошибки? Пожалуйста, выработайте хорошие привычки программирования и почаще проверяйте свой код!

Хорошо, слышишь об этомотличный, впечатляет больше!