Консультация № 172160
14.09.2009, 10:38
0.00 руб.
0 21 5
Доброго времени суток!
Мне нужно было сделать следующую вещь: форму, где вводится логин и пароль, эти данные отсылаются серверу, оттуда приходит код ошибки или ответ, что авторизация прошла успешно - в последнем случае нужно ввести имя файла для отправки на сервер. Так вот, я при ответе сервера об успешной авторизации создаю в рнр-программе html - форму, которая принимает имя файла и возвращает его в эту же рнр-программу. Соответственно, соединение у меня разрывается после выполнения скрипта, и нужно заного авторизоваться, а нужно чтобы соединение не разрывалось, и можно было просто отправить команду с именем файла - помогите, как это можно сделать? В приложении привожу только рнр-файл, без хтмл

Приложение:
<html>
<head>
<title>Aaoi?ecaoey</title>
</head>
<body>
<?php
$hostname = '192.168.0.211';
$port = 3000;
$q = "*ERR,2\r\n";
$w = "*AUTH\r\n";
$e = "*ERR,10\r\n";
$r = "*ERR,3\r\n";
$y = "*ERR,1";
$u = "*ERR,4";
$i = "*ERR,100";
$o = "*ERR,2";
if (!$sock) {
$sock = fsockopen ($hostname, $port);
if (isset($_REQUEST["fileName"])){
$fileName = $_REQUEST["fileName"];
$userName = $_REQUEST["userName"];
$password = $_REQUEST["password"];
$file = file_get_contents($fileName);
$fileSize = filesize($fileName);
fputs ($sock, "AUTH,$userName,$password\r\n\r\n");
$t = fgets ($sock);
fputs ($sock, "FILE,$userName,$fileName,$fileSize\r\n\r\n");
fputs ($sock, "$file\r\n\r\n");
$t = fgets ($sock, 128);
$h = substr($t,0,6);
$g = substr($t,0,8);
echo ($fileSize);
if ($h == $o){
echo ("..............");
}else if($h == $y){
echo ("...........");
}else if($h == $u){
echo (".........");
}else if($g == i){
echo ("..........");
}else{
echo ($t);
}
}else{
$userName = $_REQUEST["userName"];
$password = $_REQUEST["password"];

fputs ($sock, "AUTH,$userName,$password\r\n\r\n");
// while (!feof ($sock) ) {
$t = fgets ($sock);
$q = "*ERR,2\r\n";
$w = "*AUTH\r\n";
$e = "*ERR,10\r\n";
$r = "*ERR,3\r\n";
if ($t == $q){
echo ("..........");

}else if($t == $w){
echo ("<form method='post' action='auth.php'>");
echo ("имя файла:  ");
echo ("<input type = 'text'");
echo ("name = 'fileName'");
echo ("value = ' '>
");
echo ("<input type = 'hidden'");
echo ("name = 'userName'");
echo ("value = '$userName'>");
echo ("<input type = 'hidden'");
echo ("name = 'password'");
echo ("value = '$password'>");
echo ("<input type = 'submit'>");
echo ("</form>");
}else if($t == $e){
echo ("..........");
fclose ($sock);
}else if($t == $r){
echo ("........");
fclose ($sock);
}else{
echo (".........");
fclose ($sock);
}
// socket_set_blocking($sock, FALSE);
}
// }
}
?>
</body>
</html>

Обсуждение

Неизвестный
14.09.2009, 11:06
общий
это ответ
Здравствуйте, Смирнов Павел Владимирович.
Используйте сессии.
В начале документа начните сессию. После успешной авторизации занесите в сессию данные, что авторизация прошла успешно. Далее, если в сессии есть отметка, что авторизация пройдена выводите форму отправки файла ну и соответственно обрабатываете принятый файл, если нет то выводите форму авторизации.
3
С сессиями было бы проще, но подключаться все равно дважды придется!
Неизвестный
14.09.2009, 15:57
общий
это ответ
Здравствуйте, Смирнов Павел Владимирович!
Код приводить не буду, так как это довольно громоздко, а вкратце опишу теорию.
способ чтобы не пользоватяься сессиями (лично мое мнение - мне сессии не нравятся)

1 - выводим страницу авторизации.
2 - проверяем авторизацию и формируем страницу для передачи файла. в эту страницу включаем два невидимых поля "имя" и "пароль" с данными, которые отправлял пользователь
3 - проверяем опять имя и пароль пользователя и загружаем файл

в итоге если у пользователя нету этих двух полей - выводим ему страницу авторизации. если есть (сформированы скриптом) - продолжаем работу.

немного модифицировав код, имя и пароль пользователя можно хранить в cookies. а при каждом обращении к сайту - проверять их наличие. так работает большинство современных сайтов. если при установке cookies указать "время жизни", то пользователю после авотризации можно будет заходить на сайт даже через несколько дней, миную опять процедуру авторизации
4
Куки сохранят пароль, а этого нельзя делать в данном случае...
Неизвестный
15.09.2009, 03:03
общий
Rok-set:
Чем же Вам сессии то не угодили?
"Таскать" пароль "забитый" в HTML всех страниц, или в cookies - очень не безопасно. Его очень просто можно будет подглядеть например, в кэше браузера...
Сессии - простой, достаточно надежный, великое множество раз проверенный и поддерживаемый платформой (PHP), механизм. Не надо больше ничего выдумывать, ИМХО...
Неизвестный
15.09.2009, 03:10
общий
это ответ
Здравствуйте, Смирнов Павел Владимирович!

Существует несколько способов решения проблемы:
1. Запоминать пароль и логин в виде переменных, но это противоречит принципам безопасности, так как данные легко прочитать, посмотрев код, а также подметить, Почти тоже самое, что и передавать данные методов get и считывать данные по ссылке;
2. С помощью файла cookie;
3. С помощью ссесий;
4. Комбинированный - cookie и сессии.

Более подробно о методах авторизации и хранения данных (логин и пароль) расcказано в статье по ссылке: http://www.tisbi.ru/resource/lib/Eltext/PHP/Glava%208/GL8.htm

C уважением, maska!
Неизвестный
15.09.2009, 12:07
общий
Понимаете, проблема как раз в том, что нужно уменьшить нагрузку на сервер и не подключаться лишний раз, а удерживать сокет, который после выполнения скрипта закрывается автоматически (не знаю, возможно это или нет). При использовании сессий, как я понял, данные сохраняются, но вот с сервером приходится связываться лишний раз. Или я не прав?
Неизвестный
15.09.2009, 13:02
общий
Смирнов Павел Владимирович:
А что мешает, вместо двух запросов к пользователю(1-имя и пароль, 2-файл), сделать только один запрос(сразу вводить и имя и пароль и файл)?
Неизвестный
15.09.2009, 13:16
общий
Это, как мне сказали, противоречит эстетике...
Неизвестный
15.09.2009, 13:19
общий
У меня была идея отправлять данные о файле другому рнр-файлу, а этот рнр-файл подвешивать, пока пользователь не введет имя файла, но не уверен что это правильный выход.
Неизвестный
15.09.2009, 13:32
общий
А держать сокет открытым, дожидаясь пока пользователь соизволит(и соизволит ли?) напечатать имя файла не противоречит эстетике?
Неизвестный
15.09.2009, 13:35
общий
Ну не знаю, но задача была поставлена именно такая! Конечно, желательно чтобы он через некоторое время сам закрывался, если не соизволит.
Неизвестный
16.09.2009, 02:23
общий
[q=272049][/q]

А почему не воспользоваться технологией ajax? Более подробно здесь: http://ru.wikipedia.org/wiki/Ajax.
Неизвестный
16.09.2009, 19:47
общий
это ответ
Здравствуйте, Смирнов Павел Владимирович.

Используйте механизм сессий. Очень подробное объяснение с примерами http://www.phpfaq.ru/sessions
3
Сессии там конечно объяснены, но здесь не подходят
Неизвестный
17.09.2009, 05:58
общий
У меня была идея отправлять данные о файле другому рнр-файлу, а этот рнр-файл подвешивать, пока пользователь не введет имя файла, но не уверен что это правильный выход.

А есть другой выход? сокет открытый fsockopen - будет закрываться по завершении скрипта... если использовать pfsockopen - сокет не закроется, но вот возможно ли в следующем процессе получить к нему доступ? У меня пока не вышло...
Держать для сокета отдельный процесс - это вариант, но придется с синхронизацией помучиться...
Хотя, ИМХО, если сервер который на 92.168.0.211 не поддерживает сессии, а требует каждый раз логин и пароль, то так и надо ему отправлять..., не перетрудится..
Ну а в промежутке между вводом пароля и имени файла, хранить эти имя/пароль в $_SESSION..
ps ajax, imho, лишнее..
Неизвестный
17.09.2009, 09:20
общий
мое небольшое имхо по поводу сессий:
ведь идентификатор сессии, насколько я помню, необходимо также передавать клиенту в браузер.
храниться он будет преимущественно в cookies. большой разницы хранить там идентификатор, или имя и пароль в зашифрованном виде - нет.
запрос к базе данных на выборку одной строки по имени и паролю тоже большой нагрузки не вызовет.
на мой взгляд сессии целесообразно использовать, если приходится передавать клиенту на хранение большие объемы данных - такие как массивы и объекты.
по поводу "закрытия сокета" - так это либо время жизни сессии, либо срок хранения cookies браузером, что для механизма сессий тоже придется учитывать.
Неизвестный
17.09.2009, 11:55
общий
Rok-set:
большой разницы хранить там идентификатор, или имя и пароль в зашифрованном виде - нет.

разница - огромная... даже не в плане нагрузки, а в плане безопасности...
во-первых, алгоритм генерации идентификатора сессии, гарантирующий сложность угадывания его, гораздо проще реализовать, чем алгоритм шифрования пароля, гарантирующий сложность расшифровки...
во-вторых, даже узнав идентификатор сессии, пользу "злоумышленику" он может принести только на время жизни сессии(обычно часа 2), узнав же, даже зашифрованный пароль, у "злоумышленика" есть достаточно времени, чтобы его расшифровать..., и пользоваться сколько угодно времени...
в-третьих, сессию можно к IP компьютера пользователя привязать, с паролем же это гораздо сложнее..
и т.д. и т.п.
вообще, обычно пароль в чистом или даже зашифрованном виде нигде и никогда не храниться... зачем давать возможность его узнать? на сервере хранится только его необратимый хэш, даже взломав базу данных, пароля не узнаешь, а на клиенте есть только идентификатор сессии, который очень быстро устаревает, а угадать его нельзя...

по поводу "закрытия сокета" - так это либо время жизни сессии, либо срок хранения cookies браузером, что для механизма сессий тоже придется учитывать.

недопонял, где связь м/д "закрытием сокета" и механизмом сессий?
Неизвестный
17.09.2009, 16:37
общий
[q=]© Цитата: по поводу "закрытия сокета" - так это либо время жизни сессии, либо срок хранения cookies браузером, что для механизма сессий тоже придется учитывать.
недопонял, где связь м/д "закрытием сокета" и механизмом сессий?

[/q]
Вот мне тоже это не понятно... Сокет-то все равно закроется, а передачу в скрытых полях формы я и так могу сделать - все равно пароль пользователь вводит сам, поэтому может его просматривать в исходном коде сколько угодно. Вариант с кукиз не подойдет, т.к. пароль сказали нужно каждый раз вводить заставлять, во избежание злоупотреблений. И к серверу второй раз не дадут подключиться, т.к. это лишнее время мол, которое слишком дорого клиентам, у которых тарифы повременные. Так что придется, видимо, изучать другие языки программирования, позволяющие это реализовать....((((
Неизвестный
17.09.2009, 17:43
общий
Вы хотите в фоновом режиме загрузить файл пока пользователь проходит авторизацию? Если авторизаций пройдена файл окончательно остается на сервере?
Неизвестный
17.09.2009, 19:35
общий
Да нет, только после успешного прохождения авторизации выбирается, какой файл отправлять. Сначала - логин и пароль, потом - имя файла, и никак иначе!
Не я придумывал для себя это задание, потому изменить ничего нельзя...
Неизвестный
18.09.2009, 00:51
общий
Давайте по полочкам.
Нужно два php файла? На первом проходим авторизацию, на втором загружаем файл? При этом гдето еще должны вылезать ошибки?
Неизвестный
18.09.2009, 05:38
общий
это ответ
Здравствуйте, Смирнов Павел Владимирович.
Ну раз уж
только после успешного прохождения авторизации выбирается, какой файл отправлять.
остается только создавать отдельный процесс...
Например, очень упрощенный пример того, как это можно сделать, с синхронизацией с помощью файлов...
т.к. свободного сокета под рукой не оказалось, мой процесс держит открытым не сокет, а просто файл, но с сокетами смысл будет тот же...
файл процесса, proc.php:
Код:
<?php
set_time_limit(120);
ignore_user_abort(true);
apache_setenv('no-gzip', 1);
ini_set('zlib.output_compression', 0);
ini_set('implicit_flush', 1);

$process = @$_SERVER['argv'][0];
if (empty($process))
exit();

$prc = "{$process}.prc";
file_put_contents($prc, time());

$in = "{$process}.in";
$out = "{$process}.out";
$sock = fopen("socket.txt", "w");

file_put_contents($out, "START: " . time());

flush();
flush();
flush();

for(;;) {
$msg = @file_get_contents($in);
if (!empty($msg)) {
if ($msg == "EXIT") {
fclose($sock);
file_put_contents($out, "EXIT: " . time());
@unlink($prc);
@unlink($in);
break;
} else {
fwrite($sock, $msg);
file_put_contents($out, "MSG: " . $msg);
}
@unlink($in);
}
}

?>


и "фронт" index.php:

Код:
<pre>
<?php
if (empty($_REQUEST['process'])) {
$process = md5(time() . rand() . 'salt');
fclose(fopen("http://{$_SERVER['SERVER_NAME']}/proc.php?{$process}", "r"));
$infile = "{$process}.in";
$outfile = "{$process}.out";

$msg = @file_get_contents($outfile);
if (empty($msg)) {
echo "Could not create process!\n";
} else {
echo $msg;
?>
<form action="<?php echo $_SERVER['PHP_SELF']?>">
<input type="hidden" name="process" value="<?php echo $process ?>">
<input name="command">
<input type="submit">
</form>
<?php
}
} elseif (empty($_REQUEST['command'])) {
echo "Command is empty!\n";
?>
<form action="<?php echo $_SERVER['PHP_SELF']?>">
<input type="hidden" name="process" value="<?php echo $_REQUEST['process']?>">
<input name="command">
<input type="submit">
</form>
<?php
} else {
$process = $_REQUEST['process'];
if (!file_exists("{$process}.prc"))
die("Process not found!");
$cmd = $_REQUEST['command'];
$infile = "{$process}.in";
$outfile = "{$process}.out";
file_put_contents($infile, $cmd);
sleep(3);
$msg = @file_get_contents($outfile);
echo "Command: $cmd\nResponse: $msg\n";
if ($cmd == "EXIT")
@unlink($outfile);
?>
<form action="<?php echo $_SERVER['PHP_SELF']?>">
<input type="hidden" name="process" value="<?php echo $process ?>">
<input name="command">
<input type="submit">
</form>
<?php
}
?>
</pre>


Успехов.

зы а все эти разговоры про сессии/куки/пароли к теме не относятся...
5
Еще не успел попробовать, но, думаю, то, что нужно - спасибо!
Неизвестный
18.09.2009, 23:45
общий
Да я вот один рнр-файл использовал - отсылал сам себе из второй формы имя файла... Но дело-то не в этом. Последний ответ, думаю, правильный - хотя еще не успел применить.
Форма ответа