Kullanıcıların hem çevrimiçi hem de çevrimdışı çalışmasını sağlayan web tabanlı bir projem var ve müşteri tarafında kayıtlar için benzersiz kimlikler üretmenin bir yolunu arıyorum. Bir kullanıcı çevrimdışıyken (yani bir sunucu ile konuşamıyor) çalışan, benzersiz olduğu garantili ve güvenli bir yaklaşım istiyorum. "Güvenli" olarak, yinelenen kimlikleri (kötü niyetli veya başka şekilde) gönderen ve bu nedenle veri bütünlüğüne zarar veren müşteriler hakkında özellikle endişeleniyorum.
Bazı googling yapıyorum, umarım bu zaten çözülmüş bir problemdir. Özellikle üretim sistemlerinde kullanılan yaklaşımlar açısından çok kesin bir şey bulamadım. Kullanıcıların yalnızca oluşturdukları verilere erişebilecekleri sistemler için bazı örnekler buldum (örneğin, birden fazla cihazda erişilen bir Yapılacaklar listesi, ancak yalnızca oluşturan kullanıcılar tarafından). Ne yazık ki, biraz daha sofistike bir şeye ihtiyacım var. Ben gerçekten iyi fikirler buldunuz burada İşlerin işe yarayabilecek düşünüyordum nasıl ile uyumludur.
Aşağıda benim önerdiğim çözüm.
Bazı Gereksinimler
- Kimlikler küresel olarak benzersiz olmalıdır (veya sistem içinde en azından benzersiz olmalıdır)
- İstemcide oluşturulmuş (yani tarayıcıda javascript aracılığıyla)
- Güvenli (yukarıda belirtildiği gibi)
- Veriler, yazmamış kullanıcılar dahil olmak üzere birden fazla kullanıcı tarafından görüntülenebilir / düzenlenebilir
- Arka uç db'lerde (MongoDB veya CouchDB gibi) önemli performans sorunlarına neden olmaz
Önerilen çözüm
Kullanıcılar bir hesap oluşturduklarında, sunucu tarafından oluşturulan ve sistemde benzersiz olduğu bilinen bir kullanıcı adı verilir. Bu kimlik, kullanıcıların kimlik doğrulama belirteciyle aynı olmamalıdır. Kullanıcılara "id token" diyelim.
Bir kullanıcı yeni bir kayıt oluşturduğunda, javascript'te yeni bir uuid oluşturur (mevcut olduğunda window.crypto kullanılarak oluşturulur. Buradaki örneklere bakın ). Bu kimlik, kullanıcının hesabını oluştururken aldığı "kimlik simgesi" ile birleştirilir. Bu yeni bileşik kimliği (sunucu tarafı kimliği belirteci + istemci tarafı uuid) şimdi kayıt için benzersiz tanımlayıcıdır. Kullanıcı çevrimiçi olduğunda ve bu yeni kaydı arka uç sunucusuna gönderdiğinde, sunucu şunları yapar:
- Bunu bir "ekle" işlemi olarak tanımlayın (yani bir güncelleme veya silme değil)
- Bileşik anahtarın her iki parçasını doğrula geçerli uuids
- Bileşik kimliğin "kimlik belirteci" kısmının mevcut kullanıcı için doğru olduğunu doğrulayın (yani, hesaplarını oluştururken kullanıcıya atanmış kimliği belirten sunucuyla eşleşir)
- Her şey db içine veri ekleme, Copasetic ise (bir ekleme not olarak "Upsert" yapmak için dikkatli olmak çok id eğer yapar zaten yanlışlıkla varolan kaydı güncelleştir vermez var)
Sorgular, güncellemeler ve silme işlemleri özel bir mantık gerektirmez. Sadece kayıt için kimliği geleneksel uygulamalarla aynı şekilde kullanırlardı.
Bu yaklaşımın avantajları nelerdir?
Müşteri kodu çevrimdışıyken yeni veriler oluşturabilir ve bu kaydın kimliğini hemen bilir. İstemci üzerinde geçici bir kimliğin üretileceği ve daha sonra sistem çevrimiçi olduğunda "son" bir kimliğe dönüştürülecek alternatif yaklaşımlar olduğunu düşündüm. Ancak, bu çok kırılgan hissettim. Özellikle yabancı anahtarlarla çocuk verisi oluşturmayı düşünmeye başladığınızda, bunun da güncellenmesi gerekir. Kimlik değiştiğinde değişecek olan URL'lerle uğraşmaktan bahsetmiyorum bile.
ID'leri bir müşteri tarafından üretilen değerin VE bir sunucu tarafından üretilen değerin bir bileşiği haline getirerek, her kullanıcı etkin olarak bir sanal alanda kimlikler oluşturur. Bunun, kötü niyetli / hileli bir müşteri tarafından yapılabilecek zararı sınırlandırması amaçlanmıştır. Ayrıca, herhangi bir kimlik çarpışması tüm sistem için küresel değil kullanıcı bazındadır.
Bir kullanıcı kimliği belirteci hesaplarına bağlı olduğundan, kimlikleri yalnızca kimliği doğrulanan istemciler tarafından bir kullanıcı sanal alanında oluşturulabilir (yani, kullanıcının başarıyla oturum açtığı yer). Bu, kötü niyetli istemcilerin bir kullanıcı için kötü kimlikler oluşturmasını engellemek içindir. Elbette bir kullanıcı kimlik belirteci kötü niyetli bir müşteri tarafından çalınmışsa, kötü şeyler yapabilir. Ancak, bir yetkili belirteç çalındığında, hesap yine de tehlikeye girer. Bunun gerçekleşmesi durumunda, verilen hasar, tehlikeye atılan hesapla sınırlı olacaktır (sistemin tamamı değil).
Endişeler
İşte bu yaklaşımla ilgili endişelerimden bazıları
Bu, büyük ölçekli bir uygulama için yeterince benzersiz kimlikler üretecek mi? Bunun kimlik çarpışmalarına neden olacağını düşünmek için herhangi bir sebep var mı? Javascript bunun çalışması için yeterince rastgele bir uuid oluşturabilir mi? Window.crypto oldukça yaygın bir şekilde kullanılabilir durumda ve bu proje zaten oldukça modern tarayıcılar gerektiriyor. ( bu sorunun şimdi ayrı bir SO sorusu var )
Kötü niyetli bir kullanıcının sistemin güvenliğini tehlikeye sokmasına izin verebilecek herhangi bir boşluk var mı?
2 uuid'den oluşan bir bileşik anahtar sorgulanırken DB performansı hakkında endişelenmek için bir neden var mı. Bu kimlik en iyi performans için nasıl saklanmalıdır? İki ayrı alan mı yoksa tek bir nesne alanı mı? Mongo'ya Couch'a karşı farklı bir "en iyi" yaklaşım olur mu? Sıralı olmayan bir birincil anahtara sahip olmanın kesici uçlar yaparken dikkate değer performans sorunlarına neden olabileceğini biliyorum. Birincil anahtar için otomatik olarak oluşturulan bir değere sahip olmak ve bu kimliği ayrı bir alan olarak depolamak daha akıllıca olur mu? ( bu sorunun şimdi ayrı bir SO sorusu var )
Bu stratejiyle, aynı kullanıcı tarafından belirli bir kayıt kümesinin oluşturulduğunu belirlemek kolay olacaktır (çünkü herkes aynı genel olarak görülebilen kimlik kartını paylaşır). Bununla ilgili herhangi bir acil sorun görmemekle birlikte, iç detaylar hakkında gerekenden daha fazla bilgi sızdırmamak her zaman daha iyidir. Diğer bir olasılık, bileşik anahtarı kullanmak olabilir, ancak bu değerden daha fazla sorun olabilir gibi görünüyor.
Bir kullanıcı için bir kimlik çarpışması olması durumunda, kurtarmanın basit bir yolu yoktur. Müşterinin yeni bir kimlik oluşturabileceğini düşünüyorum, ancak bu gerçekten gerçekleşmemesi gereken son bir vaka için çok iş gibi görünüyor. Bunu adressiz bırakmak niyetindeyim.
Yalnızca kimliği doğrulanmış kullanıcılar verileri görüntüleyebilir ve / veya düzenleyebilir. Bu benim sistemim için kabul edilebilir bir sınırlamadır.
Sonuç
Makul bir planın üstünde mi? Bunun bir kısmının, söz konusu uygulamayı daha iyi anlayabilmesi için yapılan bir karar çağrısına bağlı olduğunun farkındayım.