У мене є веб-проект, який дозволяє користувачам працювати як в Інтернеті, так і в режимі офлайн, і я шукаю спосіб генерувати унікальні ідентифікатори для записів на стороні клієнта. Я хотів би, щоб підхід, який працює в режимі офлайн (тобто не в змозі спілкуватися з сервером), гарантовано є унікальним і захищеним. Під захистом я спеціально переживаю за те, щоб клієнти надсилали дублікати ідентифікаторів (зловмисно чи іншим чином) і тим самим спричиняли хаос щодо цілісності даних.
Я робив якийсь гугл, сподіваючись, що це вже вирішена проблема. Я не знайшов нічого дуже остаточного, особливо з точки зору підходів, які використовуються у виробничих системах. Я знайшов кілька прикладів для систем, де користувачі отримуватимуть доступ лише до створених ними даних (наприклад, список Todo, до якого можна отримати доступ на декількох пристроях, але лише користувач, який його створив). На жаль, мені потрібно щось дещо складніше. Я знайшов деякі дійсно хороші ідеї тут , які відповідно до тим, як я думав , речі могли б працювати.
Нижче моє запропоноване рішення.
Деякі вимоги
- Ідентифікатори повинні бути глобально унікальними (або принаймні унікальними в системі)
- Створено на клієнті (тобто через javascript у браузері)
- Безпечний (як зазначено вище та в іншому випадку)
- Дані можуть переглядати / редагувати кілька користувачів, включаючи користувачів, які не авторували їх
- Не спричиняє значних проблем продуктивності для резервних копій (таких як MongoDB або CouchDB)
Пропоноване рішення
Коли користувачі створюють обліковий запис, їм буде надано uuid, який генерується сервером і, як відомо, є унікальним у системі. Цей ідентифікатор НЕ повинен бути таким же, як маркер автентифікації користувачів. Назвемо цей id користувачів "ідентифікатором ідентифікатора"
Коли користувач створює нову запис, вони генерують новий uuid у javascript (згенерований за допомогою window.crypto, коли він доступний. Див. Приклади тут ). Цей ідентифікатор поєднується з "маркером ідентифікатора", отриманим користувачем під час створення акаунта. Цей новий складений ідентифікатор (сторона ідентифікатора сторони сервера + uuid на стороні клієнта) тепер є унікальним ідентифікатором для запису. Коли користувач перебуває в Інтернеті і подає цю нову запис на сервер, який надає сервер, сервер:
- Ідентифікуйте це як дію "вставлення" (тобто не оновлення чи видалення)
- Перевірка обох частин складеного ключа є дійсними uuids
- Перевірте, що надана частина складеного ідентифікатора "маркер ідентифікатора" є правильною для поточного користувача (тобто вона відповідає маркеру ідентифікатора серверу, призначеному користувачеві під час створення облікового запису)
- Якщо все Copasetic, вставка даних в БД (дотримуючись обережності , щоб зробити вставку , а не «upsert» , так що якщо ідентифікатор робить вже існує , він не оновлює існуючу запис помилково)
Для запитів, оновлень та видалень не потрібна спеціальна логіка. Вони просто використовувати ідентифікатор для запису таким же чином, як і традиційні програми.
Які переваги такого підходу?
Код клієнта може створювати нові дані в режимі офлайн і негайно знати ідентифікатор для цієї записи. Я розглядав альтернативні підходи, коли на клієнті буде створений тимчасовий ідентифікатор, який пізніше буде замінено на "остаточний" ідентифікатор, коли система була в мережі. Однак це було дуже крихким. Особливо, коли ви починаєте думати про створення дочірніх даних із зовнішніми ключами, які також потрібно було б оновити. Не кажучи вже про спілкування з URL-адресами, які змінюватимуться, коли змінювався би ідентифікатор.
Здійснюючи ідентифікатори складеними клієнтським значенням І значенням, створеним сервером, кожен користувач ефективно створює ідентифікатори в пісочниці. Це призначено для обмеження шкоди, яку може нанести зловмисний / шахрайський клієнт. Крім того, будь-яке зіткнення id відбувається на основі кожного користувача, а не глобально для всієї системи.
Оскільки маркер ідентифікатора користувачів прив’язаний до їх облікового запису, ідентифікатори можуть створюватись у пісочниці користувачів лише клієнтами, які мають автентифікацію (тобто там, де користувач успішно увійшов). Це покликане уберегти зловмисних клієнтів від створення поганих ідентифікаторів для користувача. Звичайно, якщо маркер авторів авторів був викрадений зловмисним клієнтом, вони можуть зробити погані речі. Але після того, як викрадений маркер авторства, рахунок все одно порушується. У випадку, якщо це сталося, завдана шкода буде обмежена компрометованим рахунком (не всією системою).
Побоювання
Ось деякі мої проблеми з таким підходом
Чи створить це достатньо унікальний ідентифікатор для широкомасштабного застосування? Чи є підстави думати, що це призведе до зіткнення ідентифікаторів? Чи може JavaScript створити достатньо випадковий uuid для цього? Схоже, що window.crypto досить широко доступний, і цей проект вже потребує досить сучасних браузерів. ( це питання тепер має окреме запитання щодо ПП )
Чи є якісь пропуски, які мені не вистачають, які могли б дозволити зловмисникові порушити систему?
Чи є підстави турбуватися про продуктивність БД під час запитів на складений ключ, що складається з 2-х уідів. Як цей ідентифікатор повинен зберігатися для найкращої продуктивності? Два окремих поля або одне поле об’єкта? Чи був би інший "найкращий" підхід для Монго проти Куше? Я знаю, що наявність непослідовного первинного ключа може спричинити помітні проблеми з роботою при виконанні вставок. Чи було б розумніше мати автоматичне значення для основного ключа та зберегти цей ідентифікатор як окреме поле? ( це питання тепер має окреме запитання щодо ПП )
За допомогою цієї стратегії було б легко визначити, що певний набір записів створювався тим самим користувачем (оскільки всі вони мають один і той же публічно видимий маркер id). Хоча я не бачу жодних негайних проблем із цим, завжди краще не просочувати більше інформації про внутрішні деталі, ніж це потрібно. Іншою можливістю може стати хеш-композитний ключ, але, схоже, це може бути більше проблем, ніж варто.
У випадку, якщо користувач зіткнеться з ідентифікатором, не існує простого способу відновлення. Я думаю, що клієнт міг створити новий ідентифікатор, але це здається великою роботою для кращого випадку, який насправді ніколи не повинен відбуватися. Я маю намір залишити це без розгляду.
Лише автентифіковані користувачі можуть переглядати та / або редагувати дані. Це прийнятне обмеження для моєї системи.
Висновок
Чи вище розумного плану? Я усвідомлюю, що щось із цього зводиться до виклику судового рішення, заснованого на більш повному розумінні розглянутої заявки.