Java .class
dosyaları oldukça kolay bir şekilde derlenebilir. Giriş verilerini kodda kullanmak zorunda kalırsam veritabanımı nasıl koruyabilirim?
Java .class
dosyaları oldukça kolay bir şekilde derlenebilir. Giriş verilerini kodda kullanmak zorunda kalırsam veritabanımı nasıl koruyabilirim?
Yanıtlar:
Şifreleri asla kodunuza sabit kodlamayın. Bu, yakın zamanda En Tehlikeli 25 Programlama Hatası arasında gündeme getirildi :
Yetenekli tersine mühendisler için yazılımınıza gizli bir hesabı ve parolayı sabit kodlamak son derece kullanışlıdır. Parola tüm yazılımlarınızda aynıysa, bu parola kaçınılmaz olarak öğrenildiğinde her müşteri savunmasız hale gelir. Ve sabit kodlu olduğu için düzeltilmesi çok büyük bir acı.
Parolalar dahil olmak üzere yapılandırma bilgilerini, uygulamanın başladığında okuduğu ayrı bir dosyada saklamalısınız. Bu, kod çözme işleminin bir sonucu olarak parolanın sızmasını engellemenin tek gerçek yoludur (başlamak için asla ikili dosyada derlemeyin).
Bu yaygın hata hakkında daha fazla bilgi için CWE-259 makalesini okuyabilirsiniz . Makale, sorunla ilgili daha kapsamlı bir tanım, örnekler ve birçok başka bilgi içerir.
Java'da bunu yapmanın en kolay yollarından biri Tercihler sınıfını kullanmaktır. Bazıları bir kullanıcı adı ve şifre içerebilen her türlü program ayarını saklamak için tasarlanmıştır.
import java.util.prefs.Preferences;
public class DemoApplication {
Preferences preferences =
Preferences.userNodeForPackage(DemoApplication.class);
public void setCredentials(String username, String password) {
preferences.put("db_username", username);
preferences.put("db_password", password);
}
public String getUsername() {
return preferences.get("db_username", null);
}
public String getPassword() {
return preferences.get("db_password", null);
}
// your code here
}
Yukarıdaki kodda, setCredentials
kullanıcı adı ve şifre için bir iletişim kutusu gösterdikten sonra yöntemi çağırabilirsiniz . Veritabanına bağlanmanız gerektiğinde , depolanan değerleri almak için getUsername
ve getPassword
yöntemlerini kullanabilirsiniz. Oturum açma kimlik bilgileri ikili dosyalarınıza sabit bir şekilde kodlanmayacaktır, bu nedenle de derleme bir güvenlik riski oluşturmayacaktır.
Önemli Not: Tercih dosyaları yalnızca düz metin XML dosyalarıdır. Yetkisiz kullanıcıların ham dosyaları görüntülemesini önlemek için uygun adımları attığınızdan emin olun (UNIX izinleri, Windows izinleri vb.). En azından Linux'ta bu bir sorun değildir, çünkü çağırmak Preferences.userNodeForPackage
XML dosyasını mevcut kullanıcının ev dizininde oluşturur ve bu zaten diğer kullanıcılar tarafından okunamaz. Windows'ta durum farklı olabilir.
Daha Önemli Notlar: Bu cevabın yorumlarında ve diğerlerinde bu durum için doğru mimarinin ne olduğu hakkında birçok tartışma yapılmıştır. Orijinal soru, uygulamanın kullanıldığı bağlamdan gerçekten bahsetmiyor, bu yüzden aklıma gelen iki durum hakkında konuşacağım. Birincisi, programı kullanan kişinin veritabanı kimlik bilgilerini zaten bildiği (ve bilmeye yetkili olduğu) durumdur. İkincisi, geliştirici olarak, veritabanı kimlik bilgilerini programı kullanan kişiden gizli tutmaya çalıştığınız durumdur.
İlk Durum: Kullanıcı, veritabanı oturum açma kimlik bilgilerini bilmeye yetkilidir
Bu durumda yukarıda bahsettiğim çözüm işe yarayacaktır. Java Preference
sınıfı, kullanıcı adını ve parolayı düz metin olarak saklayacak, ancak tercihler dosyası yalnızca yetkili kullanıcı tarafından okunabilecektir. Kullanıcı basitçe tercihler XML dosyasını açabilir ve oturum açma kimlik bilgilerini okuyabilir, ancak bu bir güvenlik riski değildir çünkü kullanıcı başlangıçta kimlik bilgilerini biliyordu.
İkinci Durum: Oturum açma kimlik bilgilerini kullanıcıdan gizlemeye çalışmak
Bu daha karmaşık bir durumdur: kullanıcı oturum açma kimlik bilgilerini bilmemeli, ancak yine de veritabanına erişmesi gerekir. Bu durumda, uygulamayı çalıştıran kullanıcının veritabanına doğrudan erişimi vardır, bu da programın oturum açma kimlik bilgilerini önceden bilmesi gerektiği anlamına gelir. Yukarıda bahsettiğim çözüm bu durum için uygun değil. Veritabanı oturum açma kimlik bilgilerini bir tercihler dosyasında saklayabilirsiniz, ancak kullanıcı, sahibi olacağı için bu dosyayı okuyabilecektir. Aslında, bu davayı güvenli bir şekilde kullanmanın gerçekten iyi bir yolu yok.
Doğru Durum: Çok katmanlı mimari kullanma
Bunu yapmanın doğru yolu, veritabanı sunucunuz ile istemci uygulamanız arasında, tek tek kullanıcıların kimliğini doğrulayan ve sınırlı sayıda işlemin gerçekleştirilmesine izin veren bir orta katmana sahip olmaktır. Her kullanıcının kendi oturum açma kimlik bilgileri olur, ancak veritabanı sunucusu için değil. Kimlik bilgileri, orta katmana (iş mantığı katmanı) erişime izin verir ve her kullanıcı için farklı olur.
Her kullanıcının kendi kullanıcı adı ve şifresi olacaktır ve bunlar herhangi bir güvenlik riski olmaksızın bir tercihler dosyasında yerel olarak depolanabilir. Buna üç katmanlı mimari denir (katmanlar veritabanı sunucunuz, iş mantığı sunucunuz ve istemci uygulamanızdır). Daha karmaşık, ancak bu tür şeyleri yapmanın gerçekten en güvenli yolu.
Temel işlem sırası şöyledir:
getInventoryList
.Tüm süreç boyunca , istemci uygulamasının hiçbir zaman doğrudan veritabanına bağlanmadığını unutmayın . İş mantığı katmanı, kimliği doğrulanmış bir kullanıcıdan bir istek alır, istemcinin bir envanter listesi isteğini işler ve ancak o zaman bir SQL sorgusu yürütür.
Parolayı uygulamanın okuyacağı bir dosyaya koyun. Parolaları ASLA bir kaynak dosyaya yerleştirmeyin. Dönem.
Ruby'nin bu tür bir kullanım için DBI :: DBRC adında az bilinen bir modülü vardır . Java'nın bir eşdeğeri olduğundan şüphem yok. Neyse, yazmak zor değil.
Bir web uygulaması mı yazıyorsun? Öyleyse, JNDI'yı uygulamaya harici olarak yapılandırmak için kullanın. Burada bir genel bakış mevcuttur :
JNDI, bir uygulamanın ağ üzerinden uzak hizmetleri bulması ve bunlara erişmesi için tek tip bir yol sağlar. Uzak hizmet, bir mesajlaşma hizmeti veya uygulamaya özgü bir hizmet dahil olmak üzere herhangi bir kurumsal hizmet olabilir, ancak tabii ki bir JDBC uygulaması esas olarak bir veri tabanı hizmetiyle ilgilenir. Bir DataSource nesnesi oluşturulduktan ve bir JNDI adlandırma hizmetine kaydedildikten sonra, bir uygulama bu DataSource nesnesine erişmek için JNDI API'sini kullanabilir ve bu, daha sonra temsil ettiği veri kaynağına bağlanmak için kullanılabilir.
Ne yaparsanız yapın, hassas bilgiler bir yerde bir dosyada saklanacaktır. Amacınız bunu mümkün olduğunca zorlaştırmaktır. Bunun ne kadarını elde edebileceğiniz, projenize, ihtiyaçlarınıza ve şirketinizin cüzdanının kalınlığına bağlıdır.
En iyi yol, herhangi bir yerde herhangi bir şifre saklamamaktır. Bu, parola karmaları oluşturmak ve depolamak için karma işlevler kullanılarak elde edilir:
hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366
Karma algoritmalar tek yönlü işlevlerdir. Herhangi bir miktarda veriyi tersine çevrilemeyen sabit uzunlukta bir "parmak izine" dönüştürürler. Ayrıca, giriş çok küçük bir bit bile olsa, ortaya çıkan karmanın tamamen farklı olma özelliğine sahiptirler (yukarıdaki örneğe bakın). Bu, parolaları korumak için harikadır, çünkü parolaları, parola dosyası ele geçirilse bile onları koruyan bir biçimde saklamak istiyoruz, ancak aynı zamanda bir kullanıcının parolasının doğru olduğunu doğrulayabilmemiz gerekir.
İlgisiz not: İnternetin eski günlerinde, 'şifremi unuttum' bağlantısını tıkladığınızda, web siteleri size düz metin şifrenizi e-posta ile gönderiyordu. Bunları muhtemelen bir yerde bir veritabanında saklıyorlardı. Bilgisayar korsanları veritabanlarına eriştiklerinde, tüm şifrelere erişim elde edeceklerdi. Birçok kullanıcı aynı parolayı birden fazla web sitesinde kullanacağından, bu çok büyük bir güvenlik sorunuydu. Şans eseri, günümüzde bu yaygın bir uygulama değil.
Şimdi soru geliyor: şifreleri saklamanın en iyi yolu nedir? Ben ele alacak bu (kimlik doğrulama ve kullanıcı yönetimi hizmeti stormpath en) çözümü bayağı İdeal bir:
Açıkçası Google veya banka değilsin, bu yüzden bu senin için aşırı bir çözüm. Ama sonra şu soru geliyor: Projeniz ne kadar güvenlik gerektiriyor, ne kadar zamanınız ve paranız var?
Pek çok uygulama için, önerilmese de, kodda sabit kodlanmış parolanın saklanması yeterince iyi bir çözüm olabilir. Ancak yukarıdaki listeden birkaç ekstra güvenlik adımını kolayca ekleyerek uygulamanızı çok daha güvenli hale getirebilirsiniz.
Örneğin, 1. adımın projeniz için kabul edilebilir bir çözüm olmadığını varsayalım. Kullanıcıların her seferinde şifre girmesini istemezsiniz veya kullanıcıların şifreyi bilmesini bile istemezsiniz / buna ihtiyaç duymazsınız. Yine de bir yerlerde hassas bilgileriniz var ve bunu korumak istiyorsunuz. Basit bir uygulamanız var, dosyalarınızı depolayacak bir sunucu yok veya bu projeniz için çok fazla güçlük yaratıyor. Uygulamanız, dosyaların güvenli bir şekilde saklanmasının mümkün olmadığı ortamlarda çalışır. Bu en kötü durumlardan biridir, ancak yine de bazı ek güvenlik önlemleriyle çok daha güvenli bir çözüme sahip olabilirsiniz. Örneğin, hassas bilgileri bir dosyada saklayabilir ve dosyayı şifreleyebilirsiniz. Şifreleme özel anahtarının kodda sabit kodlanmasını sağlayabilirsiniz. Kodu gizleyebilirsiniz, böylece birinin onu kırmasını biraz daha zor hale getirebilirsiniz.bu bağlantı . (Bunun% 100 güvenli olmadığı konusunda sizi bir kez daha uyarmak istiyorum. Doğru bilgi ve araçlara sahip akıllı bir bilgisayar korsanı bunu hackleyebilir. Ancak gereksinimlerinize ve ihtiyaçlarınıza göre bu sizin için yeterince iyi bir çözüm olabilir).
Bu soru, şifrelerin ve diğer verilerin şifrelenmiş bir dosyada nasıl saklanacağını gösterir: Java 256-bit AES Şifre Tabanlı Şifreleme
MD5 bir şifreleme algoritması değil, bir karma algoritmadır, kısacası karma işlemi yapamazsınız, yalnızca karşılaştırabilirsiniz. İdeal olarak kullanıcı kimlik doğrulama bilgilerini saklarken kullanılmalı ve kullanıcı adı ve şifresini değil. db kullanıcı adı ve pwd, en azından şifrelenmeli ve bir yapılandırma dosyasında saklanmalıdır.