Групповой набор команд в виде атомарных транзакций (C++)

Групповой набор команд в виде атомарных транзакций (C++)
Групповой набор команд в виде атомарных транзакций (C++) - heftiba @ Unsplash

На практике таких атомарных транзакций не существует

Вместо этого вы можете попытаться сделать все операции идемпотентными, чтобы их можно было безопасно повторить.

Идемпотентность особенно важна для сетевых операций. Обычно устройство отправляет запрос и получает ответ. Но сети ненадежны. Конечно, отправка запроса может завершиться ошибкой. Но также может случиться так, что вы отправляете запрос, он успешно обрабатывается на сервере, но потом теряется сетевое соединение и вы так и не получаете ответ. Идемпотентность означает, что такие операции можно безопасно повторять, что не имеет значения, выдается ли запрос 1 или 10 раз. Это проще, когда вы выражаете эти операции не как изменение состояния или действие, а как желаемое состояние, которого вы хотите достичь.

Здесь имеет смысл сделать так, чтобы сетевой запрос достиг состояния «устройство с этим кодом погашения привязано к этому паролю». Это позволяет изначально установить новый пароль и позволяет устройству убедиться, что оно правильно зарегистрировано, но не позволяет устройству изменить пароль позже.

Затем этот фрагмент кода может сначала безопасно создать и сохранить пароль, а затем всегда повторять сетевой запрос:

template<class T> T load_or_default(StorageLocation, T default);
template<class T> void store_or_fail(StorageLocation, T value);

// 1. ensure that we have created a password
auto password = load_or_default(PASSWORD, "");
if (!password) {
  password = generate_password();
  store_or_fail(PASSWORD, password);
}

// 2. ensure that we are registered
ensure_registration_with_server_or_fail(password, redeem_code);

В качестве оптимизации вы можете сохранить дополнительную переменную, которая представляет статус регистрации:

// 2. ensure that we are registered
auto is_registered = load_or_default(IS_REGISTERED, false);
if (!is_registered) {
  ensure_registration_with_server_or_fail(password, redeem_code);
  store_or_fail(IS_REGISTERED, true);
}

Концепция идемпотентности особенно важна в протоколе HTTP. Согласно анализу Роя Филдинга, этот протокол хорошо подходит для передачи состояния (REST API). В HTTP некоторые методы, такие как GET и PUT, считаются идемпотентными, а POST — нет. Ваша регистрация может быть элегантно выражена с помощью операции в стиле PUT.

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

Если устройство входит в систему со старым паролем, оно проходит, но процедура смены пароля считается неудачной. В этот момент смена пароля может быть повторена.

Также необходимо иметь два файла для пароля на флэш-памяти устройства. Более новый используется при условии, что он соответствует (правильный размер, возможно, контрольная сумма). При обнаружении несоответствия он может быть удален, и тогда используется более старый. Новый пароль перезаписывает старый файл.

В течение короткого времени два пароля действительны, но если они достаточно сложны, я не считаю это большим нарушением безопасности.

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


LetsCodeIt, 7 апреля 2023 г., 17:06