Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 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.005 c
4-1188989858
Cj
2007-09-05 14:57
2009.05.31
Как получить путь к файлу...


4-1210438911
Тимохов
2008-05-10 21:01
2009.05.31
Как правильно отрисовать в WM_PAINT?


2-1239880524
mefodiy
2009-04-16 15:15
2009.05.31
"Белая форма"


4-1210534264
Игорь
2008-05-11 23:31
2009.05.31
Как в Windows Vista программно уменьшить громкость


8-1194545729
NaRuTo
2007-11-08 21:15
2009.05.31
Как сделать так чтобы моя диаграмма скакала под бит музыки.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский