Veritabanı "doğrulama"

4 Cevap php

Ben veritabanında şifre ile kullanıcı tarafından girilen parolayı doğrulamak için çalışıyorum. Ben bunu asla çalışır mysql şifre ile şifreyi doğrulamak çalışır ancak zaman, (adı yoksa bir hata görüntüler) adı cezası denetler dışarı çalıştık. Çalışma 'örnek' http://scapersclearing.com/fansite/login.php yer almaktadır; ve bu PHP (not base.php veritabanı bilgi ve header.php, navigation.php ve footer.php ve tüm ön uç içerir) olduğunu. Ben html varlıkları ekleme ve bu işleri bir kez SQL enjeksiyon önlenmesi planlıyorum. Adı: Test - Şifre: password89 (md5 c1c2434f064da663997b1a2a233bf9f6)

<?php 
include("base.php"); //Include MySQL connection

$username = $_POST['username']; //Connect form username with strings
$password = $_POST['password']; //Connect form password with strings

$salt = "xia8u28jd0ajgfa"; //Define the salt string
$salt2 = "oqipoaks42duaiu"; //Define the second salt string
$password = md5($salt.$password.$salt2); //Encrypt the password

$result = mysql_query("SELECT * FROM members WHERE username = '".$username."'"); //Open the members table
while($row = mysql_fetch_array( $result )) { //Convert the members table into an array

if ( $username != $row['username'] ) { //If user entered username doesn't equal the database username
    include("header.php"); //Print the message
    include("navigation.php");
    echo "Invalid username or password!";
    include("footer.php");
}
else {

if ( $row['password'] == $password ) { //Validate username and password
    setcookie('c_username', $username, time()+6000);  //Set the username cookie
    setcookie('c_password', $password, time()+6000);  //Set the cookie
    header("Location:index.php"); //Redirect to home page
} else {
    include("header.php"); //Print the message
    include("navigation.php");
    echo "<div class=\"content\"><p>Invalid username or password!<p></div>";
    include("footer.php");
} } }
?>

4 Cevap

İşte benim yorum:

<?php 
include("base.php"); //Include MySQL connection

'username' veya 'password' endeksleri var yoksa aşağıdaki başarısız olur. array_key_exists() to test the $_POST dizisi ilk kullanımı.

$username = $_POST['username']; 
$password = $_POST['password'];

Tek bir tuz size sonuna kadar başlangıç ​​ve diğer yarısı bunun yarısı eklenerek hiçbir şey kazanacaktır, yeterli.

Ayrıca: kodu yorumlar tamamen yararsız. Böyle bariz ve uninformative demeçler yorumlarla kodunuzu kaplamak için zahmet etmeyin.

$salt = "xia8u28jd0ajgfa"; //Define the salt string
$salt2 = "oqipoaks42duaiu"; //Define the second salt string

Ama kullanıcı başına bir different rastgele tuz saklamak için daha güvenli bulunuyor. Sen members tabloda, veritabanında bu saklayabilirsiniz. Bir tuz kullanmanın amacı, sözlük saldırıları yenilgidir. Saldırgan tüm üye hesapları için single tuz kullanmak olduğunu biliyorsa, o zaman senin tuz kullanarak sözlük kelimelerin öncesi hesaplanan hash değerleri tek bir set oluşturabilirsiniz.

MD5() çok güçlü bir karma işlev değil. MD5 uzlaşma için bazı yöntemler yayınlanmıştır. Iyi SHA1, ama daha iyi SHA-256. SHA-256 PHP hash() fonksiyonu ile desteklenen ancak henüz MySQL yerli bir fonksiyonu olarak desteklenmiyor değil.

$password = md5($salt.$password.$salt2);

Sorgunuzda geniş açık SQL injection açığı var. Ben bazı sorgular için bunu yapmak için unutmak çok kolay, çünkü "daha sonra güvenlik açıklarını tespit" şiddetle karşı dikkatli olun. Sadece sağ ön güvenlik için kod ve sonra herhangi bir kaçırmayacaksınız. Bu SQL sorgu parametreleri kullanmak kolaydır, bu yüzden yerine sorguları içine güvensiz değişkenleri interpolasyon bunu.

Orada bu gün antika ext / mysql API kullanmak için hiçbir neden gerçekten, ve sorgu parametreleri gibi özellikleri desteklemez çünkü kötü bir uygulamadır. Ext / mysqli veya başka PDO'yu kullanın.

$result = mysql_query("SELECT * FROM members WHERE username = '".$username."'");
while($row = mysql_fetch_array( $result )) {

Sadece bu maçlar satırlar için sorgulanan eğer neden $username hiç $row['username'] farklı olurdu? Lütfen while() döngü sıfır kez tekrarlayacak ve aşağıdaki kodu çalıştırın asla bu durumda - Bir kullanıcı varolmayan bir kullanıcı adı girerse ne olurdu, boş bir sonuç kümesi için test edilmelidir.

if ( $username != $row['username'] ) {
    include("header.php"); //Print the message
    include("navigation.php");
    echo "Invalid username or password!";
    include("footer.php");
}
else {
. . .

Ben şifreleri doğrulayarak olduğumda aşağıdaki gibi bir sorgu çalıştırmak için tercih:

SELECT (password = SHA1(CONCAT(?, salt))) AS password_matches
FROM members WHERE username = ?

Sorgu boş bir sonuç kümesi döndürürse, verilen kullanıcı adı yanlış oldu. Bir satır döndürür ama password_matches sıfır değilse, o zaman verilen şifre yanlış oldu. Tabii ki which kullanıcılara yanlış olduğunu ortaya çıkarmak için, ama kendi amaçları için bilmek isteyebilirsiniz istemiyorum. Örneğin, birçok başarısız giriş denemesinden aldığı belirli bir hesabın kilitli olmalıdır.

SHA-256 kullanmak isterseniz, kullanıcının tuzu alıp ve sonra PHP kodu hash() kullanmak zorunda:

$stmt = $pdo->prepare("SELECT salt FROM members WHERE username = ?");
$stmt->execute( array($username) );
$rows = $stmt->fetchAll();
if (count($rows) > 0) {
  $password_hash = hash('sha256', $password . $rows[0]['salt']);
  $stmt = $pdo->prepare("SELECT password=? AS password_matches 
                         FROM members WHERE username = ?");
  $stmt->execute( array($password_hash, $username) );
  $rows = $stmt->fetchAll();
  if ($rows[0]['password_matches'] > 0) {
    // username and password are correct
  } else {
    // password was wrong
  }
} else {
  // username was not found
}

Birkaç notlar / öneri:

  • Geçerli bir kullanıcı adı / şifre kombinasyonu için datebase kontrol edilmeli ve tam bir satır başarı durumunda iade edilmelidir, geçerli kullanıcı adları için bir süre döngü yalnızca adları benzersiz değildir ben onlar olmalıdır varsayalım (hatalara sebep olabilir ama o size kalmış) ve bulunan ilk satır şifrenizi eşleşmiyor.

Lütfen tabloda herhangi bir yinelenen kullanıcılar, orada değil, değil mi? Yani açıklamak soruna yol açacak: İlk satır false döndürür çıktı tarayıcıya gönderilir ve bir sonraki satır geçerli olabilir, ancak başlıkları, artık gönderilemez.

  • Sizin ilk deyim mantıklı değilse, zaten $ username == $ row ['username'] tüm satırları seçmiş böylece temelde 1! = 1 için test

Yani sizin kodu basitleştirmek gerektiğini düşünüyorum ve hataları bundan sonra hala varsa, onlar bulmak çok daha kolay olacaktır.

PHP bu tür bir şey için mükemmel bir crypt işlevi vardır. www.php.net / crypt

Bu kullanımı çok kolay hale rastgele tuzları ve şifre ile mağaza onu otomatik oluşturur. Sadece aşağıdaki kodu görebilirsiniz.

Hazırlanan tablolar ile ilgili diğer olanlarla bu cevabı birleştirin ve altın olacak.

Bu (ben sadece bu yüzden şartları alırsınız, bir sürü kod kesmek ve kısayollar götürüyorum) yapardım nasıl:

<?php
# to register:
query('INSERT INTO users (user, pass) VALUES (?, ?)', array($user, crypt($pass)));

# to verify:
$urow = query('SELECT user, pass FROM users WHERE user = ?', array($user));
if (rows() < 1) {
  die('No such user');
} 
else if (crypt($pass, $urow['pass']) != $urow['pass']) {
  die('Wrong password!');
} 
#once you're here, it passed, and so on...
?>

Her şeyden önce üreten konum karma Eğer kayıt sırasında veritabanında eklediğiniz biri ile aynı olduğundan emin olun.

Sonra, bir kullanıcının kimliğini doğrulamak gerektiğini yolu budur:

$res = mysql_query("SELECT just,the,needed,info FROM `members` WHERE `username` = '". esc($user) ."' AND `password` = '". esc($pass) ."'");

if ($hlp = mysql_fetch_assoc($res))
    echo 'ok';
else
    echo 'invalid username or password';

esc () fav nerede. fonksiyonu (mysql_escape_string veya mysql_real_escape_string) kaçarlar.

Şimdi şifre geçerlilik veritabanı içinde kontrol, böylece gerçek karma çıkmak asla.