Форум: "Прочее";
Текущий архив: 2009.05.31;
Скачать: [xml.tar.bz2];
ВнизWeb Server Application +CGI + Cookie Найти похожие ветки
← →
Dennis I. Komarov © (2009-03-02 12:00) [0]Пусть имеем простое cgi-приложение на базе WSA.
Вопрос собственно такой, как научить его работать с куками, ведь операции с ними на уровне HTTP?
У кого есть хороший мануал по этому поводу...
← →
Ega23 © (2009-03-02 12:17) [1]RFC 2616 :)
← →
Dennis I. Komarov © (2009-03-02 12:22) [2]
> Ega23 © (02.03.09 12:17) [1]
2965 если не ошибаюсь... ;)
← →
Dennis I. Komarov © (2009-03-03 13:16) [3]Ну все же кто работал с cgi и куками?
Пусть будем делать простейший механизм авторизации:
форма, которая пересылает нам (POST) логин и пароль; получив эти данные на валидность и если все тип-топ мы должны передать ответ клиенту в котором послать что-то вроде:
HTTP/1.1 200 OK
... {bla-bla-bla}
Set-Cookie: sessionID=678893467800; path=/; domain=.mydomain.com
...
Но сие деяние должно быть отправлено не моим cgi, а http-сервером(в частности Apache);
Вопрос: как мое cgi должно сказать ему об этом?
← →
Ega23 © (2009-03-03 13:27) [4]
> Но сие деяние должно быть отправлено не моим cgi, а http-
> сервером(в частности Apache);
>
> Вопрос: как мое cgi должно сказать ему об этом?
>
Да ну? Это как раз cgi должно отправить.
В голом виде примерно так:
program CgiVars;
{$APPTYPE CONSOLE}
uses
Windows;
const
VarList: array [1..17] of string [30] =
("SERVER_NAME", "SERVER_PROTOCOL",
"SERVER_PORT", "SERVER_SOFTWARE",
"GATEWAY_INTERFACE", "REQUEST_METHOD",
"PATH_TRANSLATED", "HTTP_REFERER",
"SCRIPT_NAME", "PATH_INFO",
"QUERY_STRING", "HTTP_ACCEPT",
"REMOTE_HOST", "REMOTE_USER",
"REMOTE_ADDR", "REMOTE_IDENT",
"HTTP_USER_AGENT");
var
I: Integer;
ReqVar: string;
VarValue: array [0..200] of Char;
begin
writeln("Content type: text/html");
writeln;
writeln("<HTML><HEAD>");
writeln("<TITLE>CGI Variables</TITLE>");
writeln("</HEAD><BODY>");
writeln("<H1>CGI Variables</H1>");
writeln("<HR><PRE>");
for I := Low (VarList) to High (VarList) do
begin
ReqVar := VarList[I];
if (GetEnvironmentVariable (PChar(ReqVar),
VarValue, 200) > 0) then
else
VarValue := "";
writeln (VarList[I] + " = " + VarValue);
end;
writeln("</PRE></BODY></HTML>");
end.
Вот и пихаешь туда своё Set-Cookie
← →
Dennis I. Komarov © (2009-03-03 13:52) [5]Ну и скажи после этого, что ответ (http) генерирует цги а не сервак ;)
только в какую переменную пихать - не понял :(
← →
Ega23 © (2009-03-03 14:07) [6]
> Ну и скажи после этого, что ответ (http) генерирует цги
> а не сервак ;)
CGI его генерирует. Убери из негоwriteln("Content type: text/html");
- и всё. Приплыли.
В случае голого CGI, сервак выступает исключительно транслятором:
1. Получил от браузера HttpRequest
2. Распарсил его.
3. Если такой cgi нет - ответил ошибку (404, ЕМНИП)
4. То, что пришло как GET - запихнул в переменные окружения для cgi
5. Запустил cgi
6. То, что пришло как POST - запихнул в StdIn для cgi
7. Дождался окончания выполнения cgi, вычитал всё из StdOut (или StdErr)
8. Если не дождался - ответил ошибку (по тайм-ауту, код не помню)
9. Если дождался - ответил ровно то, что в StdOut (StdErr) было.
10. Если ответ неправильный (заголовок кривой, данные фиговые и т.п.) - браузер выдаёт ошибку запрашиваемой страницы.
← →
забылпароль (2009-03-03 14:08) [7]Response: TWebResponse ?
← →
Ega23 © (2009-03-03 14:09) [8]Дальше уже могут быть нюансы. Например, работа с cgi "обвязана" надстройкой в виде PHP. Но тут уже другая карусель.
← →
забылпароль (2009-03-03 14:17) [9]или я что-то не догоняю..
new- wsa - cgi
webmodule1 - newaction
WebActionItem1 - onaction
procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
Handled := False; { adding a cookie does not handle the request }
with Response.Cookies.Add do
begin
Name := "LastPassword";
{ Set the LastPassword cookie to the current authorization }
{ Or, if no authorization was supplied this time, carry over }
{ the authorization from the LastPassword cookie of the request }
Value := Request.Authorization;
if Value = "" then
Value := Request.CookieFields.Values("LastPassword");
Secure := True; { be sure to use a secure connection!!!!}
Expires := Now + 1; { this cookie expires in one day }
end;
← →
Ega23 © (2009-03-03 14:27) [10]
> забылпароль (03.03.09 14:17) [9]
>
> или я что-то не догоняю..
>
Ну это уже Delphi-обёртка. Если ты этот Responce перед отправкой в строку развернёшь, то увидишь как раз что-то типа
Content-type: text/html;
({reqStatus:1,loginData:{lb_login:"Пользователь",lb_pwd:"Пароль",btn_loginOK:"Вх од"},langInfo:{lngData:[{sn:"EN",fn:"English",lid:2},{sn:"RU",fn:"Russian",lid:1 }],currLID:1}})
← →
Ega23 © (2009-03-03 14:29) [11]Это... На ответ не пугайтесь, это в JSON-формате на AJAX-запрос.
← →
Dennis I. Komarov © (2009-03-03 14:31) [12]ладно, сойдемся на том, что
Content type: text/html
- будет частью http header полученного от cgi :) который всеже отправит http-сервер клиенту ;) ?
← →
Ega23 © (2009-03-03 14:35) [13]
> ладно, сойдемся на том, что Content type: text/html - будет
> частью http header полученного от cgi :) который всеже отправит
> http-сервер клиенту ;) ?
Отправит. А теперь добавь туда своё Set-Cookie - и всё.
← →
Dennis I. Komarov © (2009-03-03 16:27) [14]Олег, спасибо за помощь! Ты откуда такую инфу познал?
← →
Ega23 © (2009-03-03 16:33) [15]
> Олег, спасибо за помощь! Ты откуда такую инфу познал?
Долгая история. Если вкратце, то нечто подобное сейчас в проекте используется. Только вместо CGI там FastCGI крутится.
А так - гугл, RFC, всякая документация и эксперименты, эксперименты, эксперименты... :)
З.Ы. Не забывай после HttpResponceHeader-а два #10 вставлять. Что-то типаfunction CreateJSONHeader : string;
begin
Result := "Content-type: text/html;"+#10#10;
end;
или
function CreateXMLHeader: string;
begin
Result := "Content-type: text/xml"+#10#10 +"<?xml version="1.0" encoding="UTF-8"?>";
end;
Ну и за кодировкой внимательно следи - где win-1251, где utf-8
← →
Dennis I. Komarov © (2009-03-03 16:58) [16]
> З.Ы. Не забывай после HttpResponceHeader-а два #10 вставлять.
> Что-то типа
Ну логично - заголовок от тела отделяется пустой строкой ;)
← →
Ega23 © (2009-03-03 17:09) [17]
> Ну логично - заголовок от тела отделяется пустой строкой
> ;)
>
Двумя. :)
Просто я как-то пол-дня убил - забыл второй #10 поставить. Или лишний запихнул? Не помню уже, почти год наза было.
← →
Dennis I. Komarov © (2009-03-04 17:31) [18]Еще вопрос немного в другой огород:
Что правильней хранить в куках для авторизации?
← →
Ega23 © (2009-03-04 17:38) [19]
> Что правильней хранить в куках для авторизации?
1. Куки могут быть отключены.
2. Если не отключены - храни SessionID. Как его будешь создавать - это уже другой вопрос.
← →
Dennis I. Komarov © (2009-03-04 17:52) [20]Мануальчика нет на эту тему?
← →
Ega23 © (2009-03-04 18:13) [21]
> Мануальчика нет на эту тему?
Нету.
Суть такая.
1. Любое соединение браузера с сервером - одноразовое. Установил соединение, послал запрос, обязательно дождался ответа, если не дождался - убился по таймауту.
2. Соответственно, некий SID (Session ID) ты можешь передать браузеру либо посредством куки (может быть что угодно. Например GUID. Или ещё какая-нибудь псевдоуникальная фигня), либо в виде параметра URL (типа,localhost/fcgi-bin/fcgisrv.exe?SID={3E3ED74A-4BDC-4255-887D-A4CAF36306E2}
)
3. Далее тебе нужно его "присовокуплять" к твоим действиям. Я, например, запускаю таймер с интервалом в 20 сек., который шлёт через AJAX серверу данный SID. Тот в свою очередь, отслеживает, какой SID когда пришёл. Если больше минуты прошло - сессия убивается.
PHP, к примеру, при настройках по-умолчанию, раздаёт тоже некий SID (по-моему md5(от чего-то-там)). Дальше он его либо в куки пихает, либо автоматом добавляет во все ссылки-формы. Если в течении 24 минут ничего от того браузера не пришло - сессия считается убитой.
В общем, как-то так.
← →
Dennis I. Komarov © (2009-03-05 09:17) [22]У меня мылся такая:
- Зашли по HTTP, залогинились, на серваке содали запись а-ля SID, RemoteIP, LoginDateTime, Username, ... (возможно еще чего придет в голову); Соответственно отослали куку на SID, UserName
- При любом следующем запросе чего либо читаем Куку, ищем по ней запись по SID, проверяем совпадение IP и Username, проверяем разницу Now - LoginDateTime (некий таймаут); дальше если все хорошо, обновляем LoginDateTime, если не - отправляем на авторизацию...
Вот вроде так... где какие дыры?
← →
Ega23 © (2009-03-05 09:51) [23]
> где какие дыры?
У юзверя могут быть отключены куки. По каким-то своим сакральным соображениям. И ты приплыл.
← →
Dennis I. Komarov © (2009-03-05 11:34) [24]
> И ты приплыл
Почему? Считаем если куки выключены - при запросе куков нету => SID - нету => отправляем на авторизацию
З.Ы. если куков (SID) нету то поля авторизации показывать при попытке чего либо туда запостить. Простые просмотры без авторизации...
← →
Ega23 © (2009-03-05 11:40) [25]
> Почему? Считаем если куки выключены - при запросе куков
> нету => SID - нету => отправляем на авторизацию
Ага, и так каждый раз?
Про PHP почитай, он в этом плане интересно делает. Как-то определяет, есть куки или нет (как- не помню). Если есть - ставит куку, если нет - добавляет этот SID во все GET-запросы, и, ЕМНИП, как Hidden-поле во все формы.
А почему тебя так смущает передавать SID в качестве параметра URL?
← →
Dennis I. Komarov © (2009-03-05 11:52) [26]Интересно, а откуда он узнает этот SID, если куков нету и хранить его негде?
← →
Ega23 © (2009-03-05 12:08) [27]
> Интересно, а откуда он узнает этот SID, если куков нету
> и хранить его негде?
Это ты про PHP? Ну он его у себя где-то в списке хранит, если инклуд нужный в скрипте выставить, и этот список мониторит по таймауту.
У меня несколько другая система - fastcgi-сервер.
Можно в базе хранить и на уровне базы мониторить.
В общем способов много. Мне изначально была поставлена задача про куки - забыть. Нету их и всё. Поэтому я свой механизм сессий изобрёл.
← →
Dennis I. Komarov © (2009-03-05 12:43) [28]не-не я про сторону клиента, он откуда возмет SID чтобы его передать в URL-е или в hidden input?
Вообще как я мыслю:
- Есть кука - передавай SID через него
- нету кука (ну съели аборигены)- авторизируйся при каждом желании чего-нить отправить
← →
Ega23 © (2009-03-05 12:51) [29]
> не-не я про сторону клиента, он откуда возмет SID чтобы
> его передать в URL-е или в hidden input?
Например, тебя после авторизации должны отправить на страницу//localhost/cgi-bin/something.cgi
Т.е., фактически, браузер получает то, что сгенерила программа something.cgi
Так вот. При авторизации (успешной) ты его отсылаешь не на//localhost/cgi-bin/something.cgi
, а на//localhost/cgi-bin/something.cgi?SID={14395DAB-03F6-40ED-B894-46A978A521FF}
Теперь клиент всегда сможет вытащить SID из URL, что-то типа
function GetLocationParam(name) {
var params = window.location.search.substr(1).split("&");
for(i=0;i<params.length;i++) {
var param=params[i].split("=");
if (param[0]==name) {
return param[1];
}
}
return "";
}
function GetCurrSID() {
var SID = GetLocationParam("SID");
return SID;
}
и как-то использовать его.
Также, при направлении со страницы авторизации на//localhost/cgi-bin/something.cgi?SID={14395DAB-03F6-40ED-B894-46A978A521FF}
твоя something.cgi получит этот параметр через переменные окружения.
← →
Anatoly Podgoretsky © (2009-03-05 12:52) [30]> Dennis I. Komarov (05.03.2009 11:52:26) [26]
А зачем, почему бы не быть просто произвольному идентификатору?
И куки вообще не нужны, передавать как параметр и принимать как параметр, а хранить на сервере, понятие keep-alive
← →
Anatoly Podgoretsky © (2009-03-05 12:53) [31]> Dennis I. Komarov (05.03.2009 12:43:28) [28]
Глупо и непрофессионально.
← →
Ega23 © (2009-03-05 12:55) [32]
> - нету кука (ну съели аборигены)- авторизируйся при каждом
> желании чего-нить отправить
Почитай, как реализован механизм сессий в PHP. Станет всё понятно.
← →
Dennis I. Komarov © (2009-03-05 13:33) [33]
> Anatoly Podgoretsky © (05.03.09 12:52) [30]
Не совсем понял механизм... Закрыл - открыл браузер - и все по новой?
> Anatoly Podgoretsky © (05.03.09 12:53) [31]
А разве delphimaster не так работает, с той лишь разницей, что кроме всего запостить может и не зарегеный юзер
> Ega23 © (05.03.09 12:55) [32]
Да все поиски приводят к phpBB, туды его.
← →
Ega23 © (2009-03-05 13:44) [34]
> Закрыл - открыл браузер - и все по новой?
Ну вообще-то - да. Или зарегился, перешёл на страницу и ущёл обедать. Вернулся - а сессия уже тю-тю.
Всё неудобство при отключенных куках должно именно к этому сводиться.
← →
имя (2009-03-26 12:08) [35]Удалено модератором
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2009.05.31;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.007 c