Güvenlik kısıtlamaları bir hizmetin boş olmasına veya bir istisna atmasına neden olmalı mı? [kapalı]


11

Bu konuda daha deneyimli bir geliştirici ile biraz anlaşmazlık yaşıyorum ve başkalarının bu konuda ne düşündüğünü merak ediyorum; ortamımız Java, EJB 3, hizmetler vb.

Yazdığım kod, bir şeyler almak ve bir şeyler yaratmak için bir servisi çağırıyor. Karşılaştığım sorun, anlamlı olmayan boş gösterici istisnalarım oldu. Örneğin, hizmetten bir nesne oluşturmasını istediğimde, null geri alıyorum; Bilinen geçerli bir kimliği olan bir nesneyi aramaya çalıştığımda null değerini geri alıyorum. Kodumda neyin yanlış olduğunu anlamaya çalışırken biraz zaman geçirdim; daha az tecrübeli olduğum için genellikle yanlış bir şey yaptığımı varsayıyorum, ama bu sıfır getirinin güvenlik olduğu ortaya çıkıyor. Hizmetimi kullanan kullanıcı sorumlusu hedef hizmet için doğru izinlere sahip değilse, yalnızca null değerini döndürür. Buradaki diğer hizmetlerin çoğu da çok iyi belgelenmemiş, bu yüzden görünüşe göre bu sadece bilmeniz gereken bir şey.

Bu, hizmetle etkileşim kuran bir geliştirici yazma kodu olarak oldukça kafa karıştırıcıdır. Hizmetin, kullanıcının bu şeyi yüklemek veya bu şeyi oluşturmak için uygun izinlere sahip olmadığını söyleyecek bir istisna olması benim için çok daha mantıklı olacaktır; O zaman hemen servisimin neden beklendiği gibi çalışmadığını anlayacağım.

Hizmeti yazan daha deneyimli geliştirici, veri istemenin bir hata koşulu olmadığını ve istisnaların, kullanıcının verilere erişimi olmadığında değil, yalnızca bir hata durumunda atılması gerektiğini savundu. Bu veriler genellikle bir GUI'de aranır ve doğru izinleri olmayan kullanıcılar için bu şeyler yalnızca "mevcut değildir". Kısacası: sormak yanlış değil, bu yüzden istisna yok. Yöntemleri boş döndür çünkü bu kullanıcılara bu şeyler "yok". Oluşturma yöntemleri, kullanıcının bu şeyi oluşturmasına izin verilmediğinde null değerini döndürür.

Bu normal ve / veya iyi bir uygulama mı? İstisnaları kullanmayı tercih ediyorum çünkü neler olduğunu bilmek daha kolay. Bu nedenle, örneğin, geçersiz kimliğe sahip bir nesneyi null döndürmektense sorduğunuzda bir NotFoundException oluşturmayı da tercih ederim.



@ChrisF: 1) bilmediğim boş referansları parlatan insanlar hakkında. Pek çok durumda uygundurlar, ben sadece bunda olduklarını sanmıyorum. 2) parametreleri kontrol etmekle ilgilidir ve istisna atmakla aynı türden bir sonuç ortaya alamaz mı? 3) Hata kodlarına karşı istisnalar da farklı bir konudur, çünkü her ikisi de neyin yanlış gittiğini "göstermenin" yollarıdır. Hata kodları, örneğin istisnaları desteklemeyen bir sistemi bilgilendirmeniz gerekiyorsa veya son kullanıcının koddan başka bir şey görmesini istemiyorsanız uygundur.
Svish

Burada sorduğum konu, "bir şeyin var olmadığını veya gerçekleşmediğini iddia etmek" ve "neden bir şeyin var olmadığını ya da gerçekleşmediğini söylemek" ile ilgilidir.
Svish

3
Onların sizin için yararlı bilgilere sahip olabileceğini yinelemelerini önermedim.
ChrisF

Doğru, bunun için üzgünüm! Bir sebepten dolayı "olası kopyalar" yorumu olarak aldı ... muhtemelen uyku eksikliği nedeniyle hehe.
Svish

Yanıtlar:


19

İstisnalar yalnızca bir hata olduğunda ve bir şey istemek hata olmadığında atılmalıdır.

Bir şey istemek bir hata olmayabilir, ancak istediğiniz bir şeye izin vermemek kesinlikle bir çeşit hatadır. İstisnalar, özel dönüş değerleri yerine kullanılacak istisnai durumları bildirmenin alternatif bir yoludur (örneğin null, yazdığınız gibi, işlerin ters gitmesinin 1 olası nedeni varsa ( Tam olarak 1 olası neden, bir sonraki sürümde 2 olası neden olabilir, bu nedenle nullbaşarısızlığı gösteren bir dönüş değeri olarak kullanmak kendinizi köşeye boyamak olacaktır)). Hizmet neden istediğinizi yapmayacağını hiçbir şekilde bildirmezse, kesinlikle kötü bir tasarımdır.

Özel bir dönüş değerinin kullanılıp kullanılmayacağı (örneğin, negatif tamsayılar normalde negatif olmayan bir tamsayı döndüren işlevler için yararlıdır), bir istisna, genel bir hata işleyici veya logger vb., Sonunda bir uygulama detayıdır. Seçim dile, duruma, sözleşmelere bağlıdır ve aynı zamanda bir zevk meselesidir. Ana nokta olması gerektiğidir bazı bulmanın doğrudan bir yolu neden bir şey çalışmaz. Aksi takdirde, tek seçeneğiniz farklı seçeneklerle ve kara kutunun davranışı ile neyin ilişkili olduğunu bulmak için ne olursa olsun, zaman kaybıdır.

String.substring()IndexOutOfBoundsExceptionindeks sınırların dışındaysa bir atar . Bunun nullyerine geri dönmenin herhangi bir avantajını düşünemiyorum - felsefi olarak - biri Stringsınırlarının dışında bir şey içermediğini iddia edebilir , bu yüzden nullmantıklı bir dönüş değeri olacaktır. Mantıksal-felsefi ve pratik olmak açıkçası iki farklı hayvandır.


Substring (), sınırların dışındaki dizinler için bir değer döndürecekse, dizenin dizinler arasındaki kısmını, muhtemelen boş olarak döndürmesi gerekir. Bu, bazı arama kodlarında bir test kaydedebilir.
kevin cline

2
Evet, null -discussion'a karşı hiç bitmeyen bir "boş değer" var: Sınır dışı dizinler için alt dize boş olmalı mı, yoksa boş bir dize mi? Bilmiyorum, her ikisi de etkili bir şekilde "hiçbir şey" (iyi, belki de boş "boş bir dize daha" hiçbir şey "?), Ama ne bir istisna yapar bilgi miktarı verir.
Joonas Pulakka

@kevincline: Biri boş başvurunun boş bir dizeyi belirtmek için deyimsel bir yol olmadığı bir çerçeve kullanmadığı sürece, boş bir başvuruyu substringdöndürmek için herhangi bir temel göremiyorum . IMHO, iki ayrı işlev olmalıdır - bunlardan biri istenen sayıda karakteri döndürme veya bir istisna atma sözü verir ve bunlardan biri olabildiğince geri döner. Her yöntem, bazı bağlamlarda diğerinden önemli ölçüde daha üstün olacaktır.
supercat

@supercat: Boş dönüş hakkında hiçbir şey söylemedim. 'Dönüş ... kısmı ... muhtemelen boş' dedim. Oracle dışında boş bir dize null değil.
kevin cline

@JoonasPulakka: Seni önceki yorumuma pinglemeliydim.
supercat

5

Sözleşmenin ne olduğu ile ilgili. Sözleşmenizde olmayan bir şey talep edebileceğinizi söylüyorsa, ne olduğunu (null veya null nesne) söylemelidir.

Öte yandan, sözleşmeniz önce farklı bir yöntem çağırmanız ( DoesSomethingExist()) ve ardından Getyöntemi çağırmanız gerektiğini söylüyorsa, sözleşmeniz yalnızca var olan şeyleri alabileceğinizi ve yoksa bir istisna atabileceğinizi söyleyebilir. İstisna mesajı, DoesSomethingExist()yararlı bir hata mesajı olan "Önce aradığınızdan emin olun" gibi bir şey söyleyebilir .


Bu durumda, var olmayan bir şey istemenin normal olmadığını söyleyebilirim, çünkü muhtemelen var olmayan bir kimlik istemezsiniz. Genellikle ilk önce bir şeyler listesi alırsınız ve daha sonra daha fazla ayrıntı için bunlardan belirli bir tanesine bakarsınız. Yani bir findAllThingsyöntem varsa, görmenize izin verilmeyen bazı şeyler veya tüm şeyler varsa boş bir liste veya bir alt küme döndürmenin uygun olduğunu söyleyebilirim. Aynı şekilde, bir blogda yalnızca geçerli kullanıcıya ait olan yayınları listeleyebilirim. Ama o kullanıcı daha sonra url tweak ve farklı bir yazı düzenlemek çalıştı ...
Svish

4

Sorunun tek bir boyutuna uyan tek yanı yoktur. İstisnaların kullanılıp kullanılmayacağı veya null değerinin döndürüleceği duruma bağlıdır.

Buna sadece dogmatik bir bakış açısından bakmak yerine, arayüze bir kullanıcı arayüzü olarak bakın . Kullanıcı arayüzleri kullanılabilir olmalıdır . Dolayısıyla, bir şeyi yapmanın "doğru" yolu hakkındaki kendi görüşleriniz ne olursa olsun, arayüzünüzü kullanan birinin bakış açısından en kullanışlı olan yöntemi seçin.

Arayanın neden bir nesnenin döndürülmediğini bilmesi gerekiyorsa, bir istisna uygundur. Bununla birlikte, genel kavram "izniniz yoksa, mevcut değildir" ise, null değeri kabul edilebilir.

Özellikle sizin durumunuzda, arayan kişinin ilk olarak oturum açması veya sunucuya bağlanması gerekiyorsa, bir öğeyi aramak için null değerlerinin kabul edilebilir olduğunu söyleyebilirim. O zaman izniniz olduğu veya izniniz olmadığı söylenir. Kapıyı geçtikten sonra, bir şey ararken, izniniz olmadığına (hatta var olduğunu bile bilmenize) izin vermeniz mantıklıdır.

Öte yandan, ilk bağlantınız veya oturum açma adımınız yoksa, bir istisna mantıklıdır. Arayan bir öğenin var olduğunu biliyorsa ve öğeyi geri alamıyorsa API yalnızca boş bir değer döndürmek için yardımcı olmaz.

Bununla birlikte, bir öğe oluşturmak için bu farklı bir hikaye. Muhtemelen başarısız olmasının birçok nedeni olabilir - izinler, kötü parametreler, sunucu belleği yetersiz, vb. .

Bu nedenle, soruyu cevaplamak için, hizmeti kullanan biri açısından kendinize en uygun çözümün ne olduğunu sorun. Onu kullanma şekliniz atipik olabilir ve en yaygın durumda null doğru cevaptır.

Bu yüzden, dini bir savaşa girmeyin, bu sorun için neyin doğru olduğuna karar verin.


Bunun için savaş teçhizatı giymeyi düşünmüyorum hehe. Sadece ne düşündüğümü düşünüp düşünmediğimi merak ediyordum. Öğrenmek istiyorum, ama sadece bir kişi söylediği için bir şeye atlamak istemiyorum. Ve özellikle kendi deneyimime ve mantığıma aykırı değilse (ne kadar küçük olursa olsun). Her neyse, bu son kullanıcı arayüzü olsaydı, o zaman gerçekten mantıklı olabilir. Bu kadar bildiğim kadarıyla, sadece kod tarafından erişilebilir bir fasulye olduğundan Ancak, ben, bir geliştirici olarak, söyleyebilirim olduğunu kullanıcı.
Svish

1
Ve bir geliştirici olarak, son kullanıcının bu konuda ne öğrenmesi gerektiğinden bağımsız olarak, bir şeyin neden yanlış olduğunu önemsiyorum.
Svish

Bryan ile tamamen aynı fikirdeyim. Develpers bile kullanıcılar, diğer bazı geliştiriciler kodunu tüketmek. Atma veya null kararları, belirli bir görev için yardımcı olması gereken bir tür arabirim / gui'dir. Sadece genel mantık veya felsefe terimiyle değil.
Bağımsız

3

Kesinlikle kötü bir tasarım olduğunu düşünüyorum . Boş gösterici benim için geçerli bir cevap değil ve yönetimi zor olabilir.

Kullanıcı uygun bir kimlik bilgisi olmadan bir hizmeti bağlamaya çalışırsa, açık ve öz bir cevapla cevap vermeliyim. Cevap bir istisna veya özel bir nesne olabilir, ancak boş olamaz.

Ağ bağlantısı koptuğunda veya beklenmeyen diğer kritik arızalarda null cevabı bırakmalısınız.

Dahası, null değerine sahip olduğunuzu anlamak için harcadığınız zaman güçlü bir argüman. Herhangi bir kod parçasını anlamak ve kullanmak kolay olmalıdır. Boş bir değere sahip olmak durum böyle değildir.


Son cümlenizle, " Yalnızca ağ bağlantısı kesildiğinde vs. null değerini döndürmelisiniz " anlamına mı geliyorsunuz? veya " Ağ bağlantısı kesildiğinde vs. null değerini döndürmeyi bırakmalısınız ." ?
Péter Török

@ Péter Török: "return null;" ifadesinin açıkça kullanılmasını önermiyorum. Ancak büyük bir arıza meydana geldiğinde, bazı hizmetlerin null değerine dönmesi kabul edilebilir.
Amine

Beklenmedik kritik bir arıza meydana gelirse bir istisna daha uygun olmaz mıydı?
Svish

2
@Amine: Bunun null değerini döndürmek için en uygun durum olduğunu söyleyebilirim .
Michael Borgwardt

@Svish: büyük bir arıza tespit ederseniz, elbette bir istisna harika olacaktır.
Amine

3

İyi yazılım tasarımı göz önünde bulundurarak, projenizin ömrü hakkında düşünmelisiniz.
Söylendiği gibi null, geri dönerek müşteriye herhangi bir bilgi vermezsiniz. Bak sana ne oldu, ilk başta sorunun nerede olduğunu fark etmedin. Ayrıca, herhangi bir belge verilmezse, bu bir karışıklıktır.

Bir istisna atarak neyin yanlış gittiğini anlayabilirsiniz. İsterseniz, görüntülenen metni daha spesifik olacak şekilde özelleştirebilirsiniz.

Diğer taraftan, geri dönerek nullmüşteriye neler olup bittiğini araştırmasını sağlayabilirsiniz.

Ayrıca, başka bir yerde olduğunuz için bir sorun olduğunu fark ettiniz NullPointerException. Şimdi bu işlevin geri dönüşünü kaydetmediğinizi hayal edin ... Bu işleve yapılan her çağrıyı bir if elseblokla kuşatmak zorunda kalacaksınız ...

Benim açımdan, geri dönmek nullkötü bir uygulamadır.


2

Hizmeti yazan daha deneyimli geliştirici, veri istemenin bir hata koşulu olmadığını ve istisnaların, kullanıcının verilere erişimi olmadığında değil, yalnızca bir hata durumunda atılması gerektiğini savundu.

Benim açımdan, bu hiç mantıklı değil.

İzinsiz veriler için sorgulama gereken bir olduğu için, özel duruma neden beklenmedik hiçbir sonuç elde etmek - - Uygun erişimi olmadan sonucu.

Analoji : GETYetkisiz bir yanıt kodu200 ok veri içermiyor, aslında 401 Unauthorized.


1

Null değeri döndürmek harika değil. Size hiçbir şey söylemiyor. Örneğin, bir uygulama bir şey aramaya çalışıyorsa ve her iki güvenlik sorunu için yanıt boşsa ve öğe yoksa, ikisi arasındaki farkı nasıl anlarsınız?

Anlamlı bir yanıt, uygulamanın bir sonraki adımda ne yapılacağı veya sorunların nasıl çözüleceği hakkında mantıklı seçimler yapmasına izin verebilir.


Orada olmayan bir nesne arasındaki farkı nasıl anlatacağınızı soruyorsunuz ve onu görme izniniz yok. Belki sistemin tasarımı bilmemenizi gerektirir. Bu özel durumda cevaplamak için yeterli bilgiye sahip olduğumuzu düşünmüyorum ve her durumda çalışan bir cevap yok. Mükemmel geçerli kullanım örnekleri vardır, eğer göremiyorsanız etkili bir şekilde orada değildir. Ve göremiyorsanız, neden göremediğinizi belirtmek için bir istisna almanız gereken kullanım durumları vardır.
Bryan Oakley

"Sistemin tasarımı bilmemenizi gerektirir" ile ne demek istiyorsun? Bu nasıl bir tasarım olabilir?
Svish

2
Güvenlik politikası bunu izlemenize izin verilmediğini söylüyorsa, çoğu durumda bunun da var olduğunu bilmemelisiniz. Bu dönen "bulunamadı" mükemmel kabul edilebilir hale getirir.
Blrfl

1

Kök neden kimliği doğrulanmamış bir kullanıcıysa, belki de güzel bir mesaj sayfasına yönlendiren (ve önemseyen birine bir bildirim) sert bir HTTP 401 yanıtı tercih ederim. Yetkilendirmeyle ilgili nedenler daha fazla durumdur; HTTP yanıtlarını döndürme argümanları (403, mesela) ve servis yanıtında özel olarak oluşturulmuş kodları / mesajları döndürme argümanları vardır.

İstisnalar yalnızca istisnai durumlarda kullanılmalı ve bir şeylerin yanlış gittiği anlamına gelmelidir. Aşırı yüklenmeleri gerektiğini "izin verilmiyor" demek için katılmıyorum. (Aynı değer null dönüş değeri için de geçerlidir: "izin verilmiyor" anlamına gelmesi için katılmıyorum.)


GUI'de bunu yapabilirsiniz, ancak sahne arkasındaki işleri yapan fasulyeye gelince, sadece istisnalarınız ve özel dönüş değerleriniz mevcuttur. Tabii ki kullanıcının istisna alması gerektiği anlamına gelmez, ancak istisna örneğin web servisine / sunucu uygulamasına / ne olursa olsun yakalanabilir ve sonra uygun olanı yapabilir. Bir yere, sert http 4xx sayfasına veya başka bir şeye yönlendirin.
Svish

İyi bir nokta, ama bu davaları yakalamak için AOP gibi bir paradigma kullanabilirsiniz. Unsur, belirli bir işlemi arama ayrıcalığını test edebilir ve yönlendirme / işlemenin uygun şekilde devam etmesine izin verebilir.
Mark

0

Şeytanlar savunucusu oynamak için boş dönen tarafını almaya çalışacağım.

Benim düşünceme göre, bu tür bir yanıtın neredeyse kabul edilebilir olduğu tek bir durum vardır ve bu durumda, güvenlik söz konusu olduğunda.

Yetkisiz kişilerin bilmemesi gereken sistemle ilgili ayrıntıları yanlışlıkla vermek çok kolaydır. Bundan kaçınılmalıdır.

Örneğin, bir kullanıcı adı ve parola denetleyicisi alın. Ayrı hata kodları olarak bir "Kullanıcı adı bulunamadı" hatası ve "Yanlış şifre" hatası döndürmek, öncelikle geçerli bir kullanıcı adı arayabilir ve ardından bir şifre arayabileceğinden, sizi ciddi güvenlik sorunlarına açacaktır. Genel bir "Geçersiz kullanıcı adı / şifre" döndürmek daha iyi bir seçenek olacaktır.

Böylece, bu özel durumda geri dönmek için neredeyse tamam olduğunu söyleyebilirim nullama katılıyorum, çalışmak çok tatsız olurdu.


Evet, katılmıyorum. Bence uygun yanıt bir istisna olurdu, ama aynı kullanıcı adı bulunamadı ve yanlış şifre için aynı olacaktır. FailedToLogin, InvalidCredentials, her neyse.
Svish

@Svish - Ama başarısızlığın nedeni hakkında hiçbir ipucu vermeye çalışıyorsanız, o zaman geri dönmek nulltam olarak en az yardımcı yanıttır. Sistem hakkında bir şeyler keşfetmek için hemen hemen her şey potansiyel olarak kullanılabilir. OP şikayet nedeni sadece nulldönüş bile yararsızdır hiçbir şey açıklamak değil çünkü . Bu kasıtlı amaçtır ... kesinlikle hiçbir şey söylememek ve yararsız olmak. Bence görev tamamlandı.
OldCurmudgeon

Öyle olabilir, ama yine de bunu yapmanın kötü olduğunu söyleyebilirim. En azından bir sistemin içinde. Son kullanıcının bir şeyler gördüğü kenarlarda, o zaman emin olabilirim. Ancak sistem içinde geliştiriciler biz kullanıcıyız ve dünyada neden işleri kendimiz için daha kafa karıştırıcı hale getirmek istiyoruz? Yazılım geliştirmek zaten yeterince zor değil gibi ...
Svish

1
Ve giriş örnekle, ben az söylemek değil kullanıcı deneyimi için 's kötü söyleyebilirim şey hiçbir şey onlar (onlar düşünce) ne zaman oldu gibi görünüyordu neden kimlik bilgilerini girdi. Sayfa sadece yenileniyorsa ve giriş yapma girişimimi görmezden gelmiş gibi görünüyorsa, girdiğim şeyin yanlış olduğunu değil, sistemde bir şeylerin yanlış olduğunu varsayacağım.
Svish

-2

Ben dönüş null düşmanca olduğunu düşünüyorum, istemci bu yöntemi çağırmak ve null dönmek, istemci ne olduğunu ve neden null döndü bilmiyorum. Bu nedenle, mantıklı olan ve bu yürütmeyi tanımlamak için bir belge sağlayan yürütme atmalıyız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.