2013-11-18 2 views
0

Я новичок как в PHP, так и в MySQL, однако в настоящее время я изучаю оба, чтобы создать базовый веб-сайт для администрирования учетных записей RADIUS. (Я перешел на использование MySQL для аутентификации пользователей)Форма PHP/MySQL не отображает вывод

Я создал сценарий, который вставляет значения пользователя в базу данных, однако мне нужно сделать так, чтобы учетная запись пользователя уже существовала, дубликат не может быть создано.

Я использовал учебник, который я нашел, чтобы попытаться создать его, и это действительно работает. Когда я добавляю пользователя, когда нет дублированной учетной записи, я возвращаю сообщение «Успешно», однако, когда есть дублированный пользователь, возвращаемая страница пуста, и я не уверен, что я делаю неправильно. Его работоспособным, но раздражающим.

Мне также интересно, если можно создать пул чисел (это будет IP-адрес), а затем использовать его так, чтобы при создании нового пользователя использовался номер из этого пула, а затем удалялся из это пул. Сделав это, я надеюсь, что смогу автоматизировать назначение IP-адресов пользователям без необходимости вручную добавлять их каждый раз при создании нового пользователя. В настоящее время для достижения чуть менее желательного подхода я сделал еще один скрипт, который отображает список IP-адресов пользователей из моей таблицы, чтобы можно было просто добавить IP-адрес, который отсутствует в этом списке. Любые советы о том, где я мог бы научиться этому, были бы весьма признательны, я не знаю с чего начать.

Ниже приведен код php, который я использую, и код html для формы. Спасибо за любую помощь или совет.

<?php 

define('DB_HOST', 'localhost'); 
define('DB_NAME', 'test'); 
define('DB_USER','root'); 
define('DB_PASSWORD','123'); 

$con=mysql_connect(DB_HOST,DB_USER,DB_PASSWORD) or die("Failed to connect to MySQL: " .  mysql_error()); 
$db=mysql_select_db(DB_NAME,$con) or die("Failed to connect to MySQL: " .  mysql_error()); 


function AuthAccount() 
{ 
    $username = $_POST['username']; 
    $value = $_POST['value']; 
    $query = "INSERT INTO radcheck(username, attribute, op, value) VALUES ('$username',  'Cleartext-Password', ':=', '$value')"; 
    $data = mysql_query ($query)or die(mysql_error()); 
    if($data) 
    { 
    echo "User added to authentication database"; 
    } 
} 

function AddAccount() 
{ 
if(!empty($_POST['username'])) 
{ 
    $query = mysql_query("SELECT * FROM radcheck WHERE username = '$_POST[username]'")  or die(mysql_error()); 

    if(!$row = mysql_fetch_array($query) or die(mysql_error())) 
    { 
     AuthAccount(); 
    } 
    else 
    { 
     echo "Username already registered"; 
    } 
} 
} 
if(isset($_POST['submit'])) 
{ 
    AddAccount(); 
} 
?> 

страница регистрации:

<!DOCTYPE HTML> 
<html> 
<head> 
<title>Sign-Up</title> 
</head> 
<body id="body-color"> 
<div id="Sign-Up"> 
<fieldset style="width:50%"><legend>Registration Form</legend> 
<table border="0"> 
<form method="POST" action="SignUp.php"> 
<tr> 
<td>Username</td><td> <input type="text" name="username"></td> 
</tr> 
<tr> 
<td>Password</td><td> <input type="text" name="value"></td> 
</tr> 
<tr> 
<td><input id="button" type="submit" name="submit" value="Sign-Up"></td> 
</tr> 
</form> 
</table> 
</fieldset> 
</div> 
</body> 
</html> 
+2

Безопасность всегда беспокойство - то, что, если один из этих сотрудников случайно разместили что-то разрушенное вашу базу данных? –

+0

Я думаю, что функции mysql * устарели, вместо этого используйте mysqli * functoins – tinybyte

+0

1. пожалуйста, воздержитесь от использования расширений mysql *, они устарели, попробуйте использовать mysqli * или pdo * – Satya

ответ

1

Вашего подход пронизан проблема:

  1. Вы ввели гонки опасности, в результате чего две сессии одновременно пытается зарегистрировать такое же имя пользователя могут оба пройти через тест SELECT, прежде чем один из них перейдет к INSERT.

    Если вы используете транзакционный механизм хранения (например, Innodb), один может решить эту проблему за счет правильного использования транзакций и locking reads, но это гораздо проще просто наложить ограничение уникальности в базе данных и оставить MySQL для делать все остальное:

    ALTER TABLE radcheck ADD UNIQUE (username) 
    

    вы можете просто идти прямо к INSERT и, если имя пользователя уже существует, то ошибка будет увеличена, что вы можете справиться с соответственно.

  2. Вы не избегаете своих строковых литералов при их встраивании в свой SQL. Это не только (серьезный) security vulnerability, но также вводит ошибку, из-за которой ваш код будет ломаться, если кто-то опубликует имя пользователя или пароль, содержащий символ '. Передача литеральных значений как parameters to prepared statements позволяет избежать этих проблем.

  3. Вы используете древнее расширение PHP для доступа к MySQL. Он не обновлялся с 2006 года, и его использование явно не поощрялось в руководстве по PHP с 2011 года. Начиная с PHP v5.5, он устарел и полностью удаляется из PHP в будущей версии. Вы должны переключиться на improved MySQL extension, PHP Data Objects или на уровень абстракции третьей стороны.

  4. Вы сохраняете пароли открытого текста в своей базе данных. Это не только создает значительный риск для безопасности вашего приложения, если ваша база данных скомпрометирована, но также создает гораздо более серьезные риски для ваших пользователей (поскольку вполне вероятно, что они используют одни и те же пароли для других учетных записей). Ради их, вы должны всегда хэш каждый пароль с солью; вы также должны быть осторожны, чтобы защитить свои пароли между своим браузером и вашим сервером, например. используя HTTPS.

Что касается назначения IP-адресов, в вашем вопросе не содержится подробностей о том, как такие адреса выбраны или для чего они используются. Обычно такие вопросы оставляют для существующих служб, таких как DHCP, которые требуют только настройки в соответствии с вашими политическими требованиями.

+0

Спасибо за ваши советы. Я был немного неясен с IP-адресами, но я нашел решение, в данном случае я не могу использовать DHCP, к сожалению. Теперь я использую свои пароли, и я создал новую страницу php и использую PDO вместо mysql_ *, основываясь на ваших советах и ​​советах @steven, и он отлично работает! Приветствия. И теперь такие имена, как О'Брайен, не нарушают мой сценарий! – user3003333

0

Я думаю, if(!$row = mysql_fetch_array($query) or die(mysql_error())) не подходит.

Я хотел бы сделать это следующим образом:

class db { 
    public static function dbFactory($host, $dbase, $user, $pass) { 
     $pdo = new PDO("mysql:host=$host;dbname=$dbase", $user, $pass); 
     $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
     $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);   
     return $pdo; 
    } 
} 
$db = db::dbFactory('localhost','mydbname','myusername','mypassword'); 

$db->beginTransaction(); 
try { 

    $stmt = $db->prepare("SELECT COUNT(*) as cnt FROM radcheck WHERE username = :uname"); 
    $stmt->bindValue(':uname',$_POST[username]); 
    $stmt->execute(); 
    $res = $stmt->fetch(PDO::FETCH_ASSOC); 

    if($res['cnt'] == 0) { 
     // go on ... 
    } 

    $db->commit(); 

} catch (Exception $e) { 
    $db->rollBack(); 
} 
+1

Остерегайтесь опасности гонки (точка №1 в моем ответе) все еще существует здесь. – eggyal

+0

@eggyal спасибо, ты прав. Пытался решить эту проблему, используя транзакцию. Считаете ли вы его безопасным без добавления уникальности? – steven

+0

Вам нужно использовать блокировку чтения: 'SELECT ... FOR UPDATE'. – eggyal

Смежные вопросы