Saya memiliki proyek berbasis web yang memungkinkan pengguna untuk bekerja baik online maupun offline dan saya sedang mencari cara untuk menghasilkan id unik untuk catatan di sisi klien. Saya ingin pendekatan yang berfungsi saat pengguna offline (tidak dapat berbicara dengan server), dijamin unik, dan aman. Dengan "aman", saya secara khusus khawatir tentang klien yang mengirimkan duplikat id (jahat atau sebaliknya) dan dengan demikian mendatangkan malapetaka pada integritas data.
Saya sudah melakukan beberapa googling, berharap ini sudah masalah yang diselesaikan. Saya belum menemukan apa pun yang sangat pasti, terutama dalam hal pendekatan yang digunakan dalam sistem produksi. Saya menemukan beberapa contoh untuk sistem di mana pengguna hanya akan mengakses data yang telah mereka buat (misalnya daftar Todo yang diakses di beberapa perangkat, tetapi hanya oleh pengguna yang membuatnya). Sayangnya, saya butuh sesuatu yang sedikit lebih canggih. Saya memang menemukan beberapa ide yang sangat bagus di sini , yang sejalan dengan cara saya berpikir bahwa segala sesuatunya mungkin berhasil.
Di bawah ini adalah solusi yang saya usulkan.
Beberapa persyaratan
- ID harus unik secara global (atau setidaknya unik dalam sistem)
- Dihasilkan pada klien (yaitu melalui javascript di browser)
- Aman (seperti yang dijelaskan di atas dan lainnya)
- Data dapat dilihat / diedit oleh banyak pengguna, termasuk pengguna yang tidak mengarangnya
- Tidak menyebabkan masalah kinerja yang signifikan untuk backend db (seperti MongoDB atau CouchDB)
Solusi yang Diusulkan
Saat pengguna membuat akun, mereka akan diberikan uuid yang dihasilkan oleh server dan dikenal unik di dalam sistem. Id ini TIDAK harus sama dengan token otentikasi pengguna. Sebut id ini pengguna "id token".
Ketika pengguna membuat catatan baru, mereka menghasilkan uuid baru dalam javascript (dihasilkan menggunakan window.crypto bila tersedia. Lihat contoh di sini ). Id ini digabungkan dengan "id token" yang diterima pengguna ketika mereka membuat akun mereka. ID komposit baru ini (token id sisi server + sisi klien uuid) sekarang menjadi pengidentifikasi unik untuk catatan. Ketika pengguna sedang online dan mengirimkan catatan baru ini ke server backend, server akan:
- Identifikasi ini sebagai tindakan "sisipkan" (yaitu bukan pembaruan atau penghapusan)
- Validasi kedua bagian kunci komposit adalah uuids yang valid
- Validasi bahwa bagian "id token" yang disediakan dari id komposit benar untuk pengguna saat ini (yaitu cocok dengan token id yang diberikan server kepada pengguna ketika mereka membuat akun mereka)
- Jika semuanya copasetic, insert data ke db (berhati-hati untuk melakukan insert dan bukan "upsert" sehingga jika id tidak sudah ada tidak update data yang sudah ada dengan kesalahan)
Kueri, pembaruan, dan penghapusan tidak memerlukan logika khusus. Mereka hanya akan menggunakan id untuk catatan dengan cara yang sama seperti aplikasi tradisional.
Apa kelebihan dari pendekatan ini?
Kode klien dapat membuat data baru saat offline dan tahu id untuk catatan itu segera. Saya mempertimbangkan pendekatan alternatif di mana id sementara akan dihasilkan pada klien yang nantinya akan ditukar dengan id "final" ketika sistem sedang online. Namun, ini terasa sangat rapuh. Terutama ketika Anda mulai berpikir tentang membuat data anak dengan kunci asing yang juga perlu diperbarui. Belum lagi berurusan dengan url yang akan berubah ketika id berubah.
Dengan membuat id gabungan dari nilai yang dihasilkan klien DAN nilai server yang dihasilkan, setiap pengguna secara efektif membuat id di kotak pasir. Ini dimaksudkan untuk membatasi kerusakan yang dapat dilakukan oleh klien jahat / jahat. Juga, setiap tabrakan id adalah berdasarkan per pengguna, bukan global ke seluruh sistem.
Karena token id pengguna diikatkan ke akun mereka, id hanya dapat dibuat di kotak pasir pengguna oleh klien yang diautentikasi (yaitu tempat pengguna berhasil masuk). Ini dimaksudkan untuk menjaga klien jahat dari membuat id buruk untuk pengguna. Tentu saja jika token pengguna otomatis dicuri oleh klien jahat, mereka dapat melakukan hal-hal buruk. Tapi, begitu token autentik telah dicuri, akun itu dikompromikan. Jika hal ini terjadi, kerusakan yang terjadi akan terbatas pada akun yang dikompromikan (bukan seluruh sistem).
Kekhawatiran
Inilah beberapa keprihatinan saya dengan pendekatan ini
Apakah ini menghasilkan id yang cukup unik untuk aplikasi skala besar? Apakah ada alasan untuk berpikir ini akan menghasilkan tabrakan id? Bisakah javascript menghasilkan uuid yang cukup agar ini berfungsi? Sepertinya window.crypto cukup banyak tersedia dan proyek ini sudah membutuhkan browser yang cukup modern. ( pertanyaan ini sekarang memiliki pertanyaan SO sendiri )
Apakah ada celah yang saya lewatkan yang dapat memungkinkan pengguna jahat untuk membahayakan sistem?
Apakah ada alasan untuk khawatir tentang kinerja DB ketika meminta kunci komposit yang terdiri dari 2 uuids. Bagaimana seharusnya id ini disimpan untuk kinerja terbaik? Dua bidang terpisah atau satu bidang objek tunggal? Apakah akan ada pendekatan "terbaik" yang berbeda untuk Mongo vs Couch? Saya tahu bahwa memiliki kunci primer non-sekuensial dapat menyebabkan masalah kinerja penting saat melakukan sisipan. Apakah akan lebih pintar untuk memiliki nilai yang dibuat secara otomatis untuk kunci utama dan menyimpan id ini sebagai bidang terpisah? ( pertanyaan ini sekarang memiliki pertanyaan SO sendiri )
Dengan strategi ini, akan mudah untuk menentukan bahwa serangkaian catatan tertentu dibuat oleh pengguna yang sama (karena mereka semua akan membagikan token id yang terlihat secara publik yang sama). Meskipun saya tidak melihat masalah langsung dengan ini, selalu lebih baik untuk tidak membocorkan lebih banyak info tentang detail internal daripada yang dibutuhkan. Kemungkinan lain adalah dengan hash kunci komposit, tetapi sepertinya itu mungkin lebih banyak masalah daripada nilainya.
Jika ada tabrakan id untuk pengguna, tidak ada cara mudah untuk memulihkan. Saya kira klien dapat menghasilkan id baru, tetapi ini sepertinya banyak pekerjaan untuk kasus tepi yang benar-benar tidak boleh terjadi. Saya berniat untuk membiarkan ini tidak terselesaikan.
Hanya pengguna terautentikasi yang dapat melihat dan / atau mengedit data. Ini adalah batasan yang dapat diterima untuk sistem saya.
Kesimpulan
Apakah di atas rencana yang masuk akal? Saya menyadari beberapa dari ini datang ke panggilan penilaian berdasarkan pemahaman yang lebih lengkap dari aplikasi yang bersangkutan.