Заголовок
В заголовок шапки рекомендуется добавить поля:
- Authorization
Используется для хранения access_token, через который проходит аутентификация пользователя. Можно понять, что его роль эквивалентна session_id в куки, С этим токеном пользователь прошел аутентификацию и вошел в систему по умолчанию.
- Подпись подпись клиента
Он используется для определения того, является ли запрос запросом, инициированным клиентским приложением.Два наиболее распространенных метода в настоящее время реализуются через шифрование и дешифрование ASE. Одним из них является сравнение информационных сводок. Самый простой способ его сгенерировать — дать случайное значение и метку времени, а солт-значение согласовано с сервером для выполнения шифрования MD5 в определенном порядке.
signture = md5(nonce + timastamp + salt)
Когда сервер получает подпись, он выполняет шифрование MD5 и сравнивает подписи в согласованном порядке.Если подпись, сгенерированная сервером, не соответствует подписи клиента, можно считать, что это не запрос, инициированный клиентом. , и в настоящее время на запрос не будет дан ответ. Конечно, использование этого метода требует отправки как временной метки, так и произвольной строки.
- версия клиентская версия
Он используется для хранения номера версии клиента, в основном маленькой версии.Если версия большая, сервер откроет новый интерфейс. Но лучше иметь номер версии для каждого выпуска клиента. Даже в этом релизе сервер не вносил никаких изменений, так как клиент только что выпущен, должен быть указан новый номер версии. Затем запишите этот номер версии в заголовок заголовка. Преимущество этого заключается в том, что если в запросе есть ошибка, мы можем определить, какая версия приложения имеет ошибку, и ее легче найти и воспроизвести. Более подробно операционная система и модель устройства также могут быть представлены в шапке.
- метка времени запроса метки времени
Отметка времени, когда клиент отправляет запрос, которую можно использовать для оценки срока действия запроса.
Сведения о подписи клиента
- предотвратить повторные атаки
Хотя наличие подписи позволяет нам судить о том, генерируется ли запрос клиентом, чтобы отвечать только на запрос клиента. Но этой безопасности недостаточно.
Типичным методом атаки является постоянное выполнение запросов к интерфейсу через подпись, сгенерированную клиентом перехвата пакетов. Наиболее распространенным является использование подписи для непрерывного запроса интерфейса кода подтверждения SMS до тех пор, пока баланс кода подтверждения на сервере не будет исчерпан.
Самый эффективный способ предотвратить повторные атаки — сохранить уникальность подписи. Клиент должен сгенерировать уникальную подпись, а сервер также должен гарантировать, что на подпись будет дан ответ только на один запрос.
- Гарантия уникальности подписи клиента
Самый простой способ для клиента обеспечить генерацию уникальной подписи каждый раз — включить метку времени в метод, генерирующий подпись.
Сервер гарантирует, что подпись каждой подписи используется только один раз.Метод реализации заключается в оценке каждого запроса.Если подпись, содержащаяся в запросе, не использовалась, он ответит на запрос и запишет подпись на сервере и отметьте его как использованный. Если будет обнаружено, что подпись, содержащаяся в запросе, помечена как использованная, на запрос не будет дан ответ.
Сервер записывает подпись, как правило, тремя способами:
- записать в файл
- Запись в базу данных MySql
- Написать в Редис
Недостатком записи в файл является то, что он не может использоваться распределенной системой. Недостатком MySql является то, что он увеличивает нагрузку на базу данных при большом количестве запросов. Так что лучше всего писать в Redis.
- Добавлен механизм тайм-аута подписи.
Способ, которым мы гарантируем уникальность подписи клиента, заключается в записи подписи каждого запроса на сервере. Но по мере увеличения запросов регистрируется все больше и больше подписей. Сравнивать сигнатуры, записанные всеми предыдущими запросами для каждого запроса по отдельности, явно неразумно.
Таким образом, наш правильный путь не должен состоять в том, чтобы просто записать подпись в файл, mysql или redis. Вместо этого это должен быть кеш файлов, или записи временных таблиц базы данных, или кеш Redis.
Но если мы сравниваем сигнатуру только в течение периода кеша, злоумышленник все еще может выполнять атаки с повторением, используя сигнатуру, срок действия которой истек и которая была удалена из кеша. Таким образом, мы ввели механизм тайм-аута, если временная метка, передаваемая запросом, длиннее, чем время кэширования сигнатуры от текущего времени сервера, на запрос не будет дан ответ. Это гарантирует, что злоумышленник не сможет использовать сигнатуру с очищенным кешем для повторной атаки.
Конечно, время ожидания не может быть слишком маленьким, потому что требуется определенное время, чтобы клиентский запрос достиг сервера. Поэтому установка времени тайм-аута должна соответствовать
(服务端当前时间 - 客户端提交的timestamp) < 超时时间 < signture缓存到期时间
Еще одним преимуществом введения механизма тайм-аута является предотвращение некоторых атак типа «человек посередине». Поскольку перехват увеличивает время запроса, перехваченный запрос может быть признан недействительным из-за существования механизма тайм-аута.
- Предотвращение атаки недополнения тайм-аута
После введения механизма тайм-аута мы можем вообще написать так
if( (服务端当前时间 - 客户端提交的timestamp) < 超时时间 ){
超时了;
}
Но если злоумышленник изменяет время клиента, временная метка, отправленная клиентом, является временной меткой, опережающей время сервера на несколько дней или лет, и генерируется соответствующая подпись. На этот раз, когда на запрос ответят. Злоумышленник ждет в течение определенного периода времени, и когда срок действия подписи в кеше истечет, злоумышленник может использовать подпись и отметку времени для повторения атаки, поскольку отметка времени на несколько дней или лет опережает время сервера, поэтому
服务端 - 客户端提交的timestamp = 负数 < 超时时间
Следовательно, через отрицательное число, меньшее времени тайм-аута, механизм тайм-аута обходится, так что подпись можно использовать повторно. Конечно, повторная атака в этом случае очень слаба, потому что сигнатура будет закэширована после ее использования, поэтому повторное использование сигнатуры через underflow придется ждать, пока кеш предыдущей сигнатуры не станет недействительным. Тогда между двумя атаками должен быть период действия кэша.
Поэтому разумнее сравнить, меньше ли время запроса, чем время тайм-аута. Также следует судить о том, что:
服务端时间 - 客户端提交的timestamp > 0
- Обеспечение согласованности времени между клиентом и сервером
Предпосылкой введения механизма тайм-аута является то, что временная ошибка между клиентом и сервером находится в допустимом диапазоне.
Представьте, что клиентский запрос доходит до сервера за 0,5 с, поэтому тайм-аут на сервере устанавливается равным 1 с. Но время клиента на 2 секунды медленнее, чем время сервера. В это время, когда временная метка клиента отправляется на сервер должны были быть
服务端当前时间-客户端提交的timestamp = 0.5 < 1 // 不超时
В результате, поскольку время клиента на 2 секунды медленнее, чем время сервера, когда метка времени достигает сервера, она становится
服务端当前时间-客户端提交的timestamp = 2.5s > 1 // 超时
Следовательно, несогласованное время между клиентом и сервером приведет к тому, что все запросы от клиента не будут отвечать из-за тайм-аута.
Так как же обеспечить согласованность времени между сервером и клиентом? Одним из наиболее распространенных решений является:
服务端给出一个接口返回当前时间戳,
客户端请求该接口获取时间戳,加上该请求的响应时间与当前时间戳相减得出时间差。
而客户端提交的timestamp 就是当前时间戳加上服务端与客户端的时间差。
Метод генерации подписи клиента
Шифрование или дайджест сообщения?
- Сводка информации
Преимущество информационного дайджеста в том, что обработка на стороне сервера проще, и для сравнения нужно только сгенерировать соответствующую подпись.
- шифрование
Шифрование ASE обычно используется для генерации подписей путем шифрования, а метод генерации подписи WeChat Alipay sdk используется для справки, а важные параметры заголовка участвуют в генерации подписи. Преимущество этого в том, что это более безопасно: если параметры заголовка заголовка в передаче будут перехвачены и изменены, сервер не сможет проверить подпись, и запрос, естественно, не ответит.
Timestamp
временная метка Нужно ли отправлять 10-значную или 13-значную временную метку?
Эта проблема чаще всего встречается с серверными частями приложений, написанными на PHP. Поскольку временная метка, используемая в PHP, состоит из 10 цифр,time()
Также возвращает только 10-значную метку времени.
Тем не менее, я все еще думаю, что следует использовать 13-битную метку времени. По крайней мере, вы должны использовать 13-битную временную метку при создании подписи, потому что она работает в режиме реального времени и предотвращает создание одной и той же подписи, когда слишком много клиентов и разные клиенты генерируют подписи одновременно.
Так или иначе, клиент использует 13-битную метку времени, и если будет отправлена 10-битная метка времени, она также будет перехвачена. Лучше подать его напрямую, а как его использовать, сервер решает сам.
<?php
// 13 位时间戳转10位 进行比对
time() - ceil($timestamp/1000);
// 如果是生成13位时间戳进行比对
list($micro,$time) = expload(' ',microtime());
ceil(($time + $micro)*1000) - $timestamp;
// 更新 其实microtime()是可以直接返回一个float数据,只需要传一个常数true
ceil(microtime(true)*1000) - $timestamp
запрос журнала ошибок
Одна из трудностей в разработке приложений заключается в том, что трудно найти и воспроизвести ошибки. Поэтому ведение журнала очень важно. Информация, которая должна быть записана в текущий журнал ошибок, должна содержать как минимум следующие типы информации:
- Адрес интерфейса и время, когда произошла ошибка
- Access_token в заголовке запроса на самом деле разумнее получить идентификатор пользователя через access_token и записать его, потому что access_token может быть изменен.
- Запрашиваемый номер версии клиента, а более подробно — операционная система и модель устройства. Поэтому рекомендуется прописывать эти параметры в шапке и отправлять каждый запрос. Номер версии клиента можно использовать, чтобы определить, какая версия запроса завершится ошибкой, а затем решить, как ее изменить. Операционная система и модель устройства в основном используются для устранения ошибок интерфейсной совместимости.
- Этот запрос выдает сообщение об ошибке.
- Код состояния http для этого запроса.
- Если на бизнес-уровне есть код состояния ошибки, его также необходимо записать
формат возврата запроса
Разработка приложений теперь более популярна или возвращает формат json вместо формата xml.
Данные, возвращаемые в формате json, обычно выглядят так:
{
"status" :200,
"message":"ok",
"data" :{},
}
status 返回请求状态码,一般复用http状态码。
message 返回请求消息,如果有错误这里写错误信息。
data 是返回的数据
Но я все же предпочитаю следующий способ возврата
{
"code":0
"data":{}
}
// 为什么请求成功 要使用0作为code状态码呢,0的第一感觉不是false吗?
嗯,错误情况千千万,而成功只有一种情况。正数负数千千万,而0也只有一个。
{
"code":1001
"message":"某个控制器请求出错"
}
Зачем?
Поскольку вы не хотите использовать статус http для передачи статуса запроса API, статус http передает статус коммуникационного уровня. API должен удовлетворять потребности бизнеса, а возвращаемые данные должны содержать код состояния бизнес-уровня. Бизнес-уровень не связан с коммуникационным уровнем и не использует статус http.
Конечно, студенты, которым нравится использовать статус http, также имеют разные мнения по этому поводу, это зависит от личных предпочтений.
Я думаю, что преимущества использования кода:
- Мы можем настроить больше кодов состояния и сообщений об ошибках. Как правило, я создаю класс карты ошибок интерфейса, а затем получаю соответствующее сообщение в соответствии со значением кода.
- Улучшенная классификация и определение кода, например, начало 1000 указывает на различные ошибки, генерируемые каждым интерфейсом контроллера. Начало 2000 года указывает на различные ошибки, генерируемые каждым интерфейсом b-контроллера. -1 означает неопределенную ошибку в классе карты ошибок.
- Код состояния бизнес-уровня не связан с кодом состояния коммуникационного уровня, и информация об ошибках бизнес-уровня отображается более подробно.
- Чтобы избежать ситуации, когда интерфейс возвращает код состояния HTTP, отличный от 200 ok, который не рассматривается на стороне клиента, что приводит к зависанию клиента. Мне нравится судить о коде состояния ответа http на бэкэнде.Если код ответа запроса не равен 200, преобразуйте класс карты ошибок просмотра в соответствующий код состояния кода и сообщение об ошибке, запишите журнал и измените код состояния http назад 200. Это гарантирует, что каждый http-запрос в основном вернет 200, а предсказуемые ошибки будут преобразованы в коды состояния кода в возвращаемых данных json.
Authorization
- Разработка серверной части приложения не может использовать сеанс?
Хотя приложение взаимодействует с серверной частью через интерфейсный запрос, файл cookie отсутствует, но сеанс можно использовать. Реализация сеанса не зависит от файла cookie, если вы поместите session_id в файл cookie, а токен, который открывает сеанс. Затем access_token, представленный полем авторизации в заголовке заголовка, также может рассматриваться как токен для выполнения той же функции.
- Разрешить ли учетной записи входить в систему более чем на двух устройствах одновременно
Потому что мы получаем аутентификацию через Авторизацию, поэтому:
-
Если вы разрешаете одновременный вход в систему нескольких устройств, вам нужно только повторно использовать access_token в пользовательской таблице после входа в систему.
-
Если вам не разрешен вход на несколько устройств одновременно, вы можете обновить access_token при входе в систему, чтобы access_token, отправленный в поле Authorization в заголовке запроса других онлайн-устройств, не совпадал с таковым в пользовательскую таблицу, и она естественно будет сжата в оффлайн.
- Проблемы безопасности access_token
Мы получаем пользователей через access_token, а это означает, что если access_token будет взломан, это эквивалентно краже учетной записи пользователя.
Думаете ли вы о том же токене, используемом для получения сеанса на стороне сервера, при использовании файлов cookie, что мы обычно делаем для безопасности?
- При создании файла cookie будет указано значение Expire, которое является жизненным циклом файла cookie.В течение этого цикла файл cookie действителен, и файл cookie будет очищен, если он превысит цикл.
- Зашифруйте файл cookie и вставьте метку времени, чтобы гарантировать, что зашифрованный текст после каждого шифрования отличается
- Междоменное использование запрещено
Поэтому, хотя уникальность подписи доказала нам, что это законный запрос, инициированный APP, строго говоря, мы не можем просто передать access_token в открытом виде. Мы можем считать, что вместо того, чтобы просто передавать значение access_token в поле Authorization, мы можем передать зашифрованную строку access_token и timestamp, расшифровать ее на сервере и сначала определить, истекло ли время ожидания. Если вам нужна более высокая безопасность, вы также можете обратиться к подписи для уникальной обработки.
обновление версии
Рекомендуется создать таблицу обновления версии для хранения информации об обновлении версии. И нужно ли принудительно обновлять поле.
Мы отправляем параметр версии в заголовке заголовка и пишем журнал, потому что мы не хотим терять контроль над клиентом и можем лучше находить ошибки. Но одно различие между приложением и традиционной веб-разработкой заключается в том, что страница веб-разработки была изменена, и все пользователи могут видеть изменение, но в случае с приложением, пока пользователь не обновляется, ошибка, которая было исправлено, все еще существует для пользователя.
Дизайн таблицы обновления версии
имя поля | тип | Примечание |
---|---|---|
id | int | идентификатор первичного ключа |
app_type | varchar | Тип версии клиента ios или android |
version | int | Номер версии разработки |
version_code | varchar | Номер версии клиента (1.0.2) |
upagrade_desc | varchar | запрос на обновление |
apk_url | varchar | Ссылка на пакет обновлений |
is_force | tinyint | Нужно ли принудительно обновлять |
created_at | int | время создания |
status | tinyint | Это опубликовано |
С помощью таблицы обновления версий мы можем более удобно и интуитивно управлять нашими выпущенными версиями и просматривать их.
И мы можем запросить интерфейс при открытии приложения, запросить таблицу дизайна версии, чтобы получить последнюю версию, и сравнить ее с полем версии, представленным в заголовке заголовка, чтобы определить, нужно ли его обновлять, и появится окно обновления.
Для версии, которую необходимо принудительно обновить, всплывающее окно должно быть настроено так, чтобы пользователь не мог щелкнуть кнопку для отмены, а приложение должно быть обновлено, чтобы использовать приложение. Таким образом, мы можем установить некоторые основные обновления или версии, которые исправляют некоторые важные ошибки, как обязательные обновления, и мы не можем продолжать использовать их без обновления.
пользовательский анализ
Чтобы лучше анализировать пользователей, мы также можем создать таблицу записей входа в приложение. Когда приложение открывается, информация о пользователе записывается через заголовок для пользовательского анализа. Дневная активность пользователя, ежемесячная активность.
Клиенту нужно только отправить данные на этот интерфейс, как только он будет открыт, клиенту не нужно заботиться о том, успешен запрос или нет.
таблица app_active_log
имя поля | тип | Примечание |
---|---|---|
id | int | идентификатор первичного ключа |
app_type | varchar | Тип версии клиента ios или android |
version | int | Номер версии разработки |
version_code | varchar | Номер версии клиента (1.0.2) |
model | varchar | Модель устройства Xiaomi Apple |
uid | int | Идентификатор пользователя |
created_at | int | время создания |
Другая функция этой таблицы также может подсчитывать количество пользователей определенной версии или количество пользователей Android или IOS, чтобы мы могли сначала выбрать версию IOS или версию Android при обновлении версии или решить, какую версию использовать. исправляйте первым, когда возникает ошибка.
Мониторинг и анализ клиентских исключений
Общие исключения на стороне приложения:
- сбой внезапно падает при использовании приложения
- заикание экран заикание
- Исключительная программа поймана Исключение
- ANR не предлагает всплывающее окно ответа (Android)
Мы пишем логи на сервере и отправляем информацию об устройстве в шапку, чтобы лучше находить ошибки клиента. Но наш журнал может записывать только исключения вызовов интерфейса. Он ничего не может сделать с исключением клиента.
Для этого мы должны сотрудничать с клиентом. Регулярно сообщайте об исключениях, сгенерированных клиентом, на сервер. Разработчикам клиентов удобно находить, воспроизводить и исправлять клиентские исключения.
Мы можем создать таблицу app_crap для сбора статистики о количестве сбоев и исключений ANR, а также о количестве затронутых пользователей.
имя поля | тип | Примечание |
---|---|---|
id | int | идентификатор первичного ключа |
app_type | varchar | Тип версии клиента ios или android |
version | int | Номер версии разработки |
version_code | varchar | Номер версии клиента (1.0.2) |
model | varchar | Модель устройства Xiaomi Apple |
type | tinyint | Конечный тип исключения Caton Flashback |
description | varchar | описывать |
created_at | int | время создания |
Конечно, клиенту сложнее записывать эти данные, лучшее решение — интегрировать в клиент SDK, предоставленный сторонним сервисом, и отправлять данные на стороннюю платформу, а клиентский инженер может авторизуйтесь на сторонней платформе, чтобы просмотреть клиентскую статистику исключений.
Часто используемые сторонние платформы:
сообщение
- родной путь
- Опрос клиентов Не рекомендуется
- Серверу сложно активно пушить клиента
- Сторонний push-сервис
- Аврора толчокРекомендуется использовать спокойный интерфейс API, который более удобен в использовании, чем другие SDK.
- Облако Baidu
- почтовый голубь
Рекомендуемые инструменты для разработки приложений
Артефакт отладки интерфейса, инициировать HTTP-запрос
Артефакт захвата пакетов может захватывать запросы, отправленные APP, чтобы увидеть, есть ли какие-либо параметры, отправленные запросом.
php — это пакет http-запросов, который можно быстро установить и использовать через composer.Его можно использовать для написания тестового кода интерфейса и имитации инициирования http-запросов.Преимущество перед postman в том, что его удобнее настраивать через код выполнение.
Эмулятор мобильного телефона, который может имитировать несколько мобильных телефонов с системой Android на компьютере.
Инструмент картирования интрасети. Трудная часть разработки приложения заключается в том, что его нельзя отлаживать локально, потому что клиенту необходимо запросить код на стороне сервера с доменным именем или IP-адресом общедоступной сети.Хотя у компании есть тестовый сервер, иногда на тесте бывает много людей. сервер, использующий его в то же время Я git отправил модификацию Последующий код сервера не может быть жестко сброшен, чтобы вступить в силу немедленно. Или тестовый сервер не в моей ветке разработки. Преимуществом ngrok является сопоставление интрасети, которое связывает доменное имя с вашим компьютером. Заполнение этого доменного имени во время тестирования клиента может получить доступ к серверному коду вашего компьютера, что делает отладку в реальном времени более удобной.
Выше приведено краткое изложение моей разработки серверной части приложения. Поскольку это первая разработка серверной части приложения, уровень ограничен. Пожалуйста, дайте мне больше советов.