HTTP는 무상태 프로토콜입니다(적어도 HTTP 1.1까지). 따라서 클라이언트가 파일을 요청하면 서버가 응답을 보내고 연결이 닫힙니다(연결이 즉시 닫히지 않도록 keep-alive를 활성화할 수 있지만 이는 이 문서의 범위를 벗어납니다). 세션을 사용하면 클라이언트에 대한 정보를 저장할 수 있으며, 예를 들어 클라이언트 로그인 중에 사용할 수 있습니다. 고유한 세션 ID를 사용하고 세션 목록을 검색하여 이미 존재하는지 확인한 다음, 없으면 새 세션을 생성할 수 있습니다. 세션은 비활성 기간 후 또는 클라이언트 로그아웃 후 수동으로 소멸될 수 있습니다.
TsgcWebSocketHTTPServer에는 서버 구성 요소에서 세션을 활성화/비활성화하는 일부 속성이 있습니다. 가장 중요한 것은 다음과 같습니다:
| 속성 | 설명 |
| SessionState | T이것은 Session을 사용하기 위해 활성화해야 하는 첫 번째 속성입니다. 이 속성을 활성화하지 않으면 세션이 작동하지 않습니다 |
|
SessionTimeout |
여기에 세션이 활성화될 최대 시간에 대해 0보다 큰 값(밀리초)을 설정해야 합니다. |
| AutoStartSession | 세션은 자동으로(AutoStartSession = true) 또는 수동으로(AutoStartSession = false) 생성할 수 있습니다. 세션이 자동으로 생성되면, 서버는 RemoteIP를 고유 식별자로 사용하여 저장된 활성 세션이 있는지 확인합니다. |
| SessionClass | 선택 사항. 서버가 새 세션을 생성할 때 사용하는 클래스입니다. 모든 세션 내부에 자체 데이터를 저장하려면 자체 TIdHTTPSession 자손으로 설정하십시오. 서버가 활성화되기 전에 설정해야 합니다. |
| SessionList | 활성 세션을 담고 있는 목록입니다. 코드로 세션을 검색, 생성 또는 제거하려면 이를 읽으십시오. 세션이 저장되는 위치를 완전히 제어해야 하는 경우 자체 목록을 할당할 수도 있습니다. 서버가 활성화되기 전에 할당해야 합니다. |
TsgcWebSocketHTTPServer1.SessionState := True;
TsgcWebSocketHTTPServer1.SessionTimeout := 600000;
TsgcWebSocketHTTPServer1.AutoStartSession := False;
새 세션을 생성하려면 고유한 새 session ID를 생성해야 합니다. 어떤 값이든 사용할 수 있습니다. 예: 클라이언트가 인증 중인 경우, user + password + remoteip를 session ID로 사용할 수 있습니다.
그런 다음 세션 목록을 검색하여 이미 존재하는지 확인하십시오. 존재하지 않으면 새로 생성하십시오.
새 세션이 생성되면 OnSessionStart 이벤트가 호출되고, 세션이 닫히면 OnSessionEnd 이벤트가 발생합니다.
procedure OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
var
vID: String;
oSession: TIdHTTPSession;
begin
if ARequestInfo.Document = '/' then
AResponseInfo.ServeFile(AContext, 'yourpathhere\index.html')
else
begin
// check if user is valid
if not ((ARequestInfo.AuthUsername = 'user') and (ARequestInfo.AuthPassword = 'pass')) then
AResponseInfo.AuthRealm := 'Authenticate'
else
begin
// create a new session id with authentication data
vID := ARequestInfo.AuthUsername + '_' + ARequestInfo.AuthPassword + '_' + ARequestInfo.RemoteIP;
// search session
oSession := TsgcWebSocketHTTPServer1.SessionList.GetSession(vID, ARequestInfo.RemoteIP);
// create new session if not exists
if not Assigned(oSession) then
oSession := TsgcWebSocketHTTPServer1.SessionList.CreateSession(ARequestInfo.RemoteIP, vID);
AResponseInfo.ContentText := '<html><head></head><body>Authenticated</body></html>';
AResponseInfo.ResponseNo := 200;
end;
end;
end;
세션이 존재하면, 서버는 세션 쿠키를 전달하는 모든 요청에 이를 첨부합니다. ARequestInfo.Session에서 이를 읽으십시오. 요청에 세션이 없으면 nil입니다.
procedure OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
begin
if Assigned(ARequestInfo.Session) then
begin
// Content is a TStrings you can use to store your own values
ARequestInfo.Session.Content.Values['visits'] :=
IntToStr(StrToIntDef(ARequestInfo.Session.Content.Values['visits'], 0) + 1);
AResponseInfo.ContentText := 'Session ' + ARequestInfo.Session.SessionID +
' visits: ' + ARequestInfo.Session.Content.Values['visits'];
end
else
AResponseInfo.ContentText := 'No session';
end;
Content 문자열 목록을 사용하는 대신 모든 세션 내부에 자체 필드를 유지하려면, TIdHTTPSession의 자손을 생성하고 SessionClass 속성을 통해 서버가 이를 사용하도록 지정하십시오. 서버가 활성화되기 전에 설정하십시오.
서버는 나머지 모든 것을 계속 처리합니다: 고유 세션 ID를 생성하고, 세션 쿠키를 보내고, SessionTimeout을 적용하며, 오래된 세션을 제거합니다. 세션이 생성될 때 자체 필드를 초기화하려면 가상 생성자 CreateInitialized를 재정의하십시오.
type
TMySession = class(TIdHTTPSession)
private
FUserName: String;
FLoginTime: TDateTime;
public
constructor CreateInitialized(AOwner: TIdHTTPCustomSessionList;
const SessionID, RemoteIP: string); override;
property UserName: String read FUserName write FUserName;
property LoginTime: TDateTime read FLoginTime write FLoginTime;
end;
constructor TMySession.CreateInitialized(AOwner: TIdHTTPCustomSessionList;
const SessionID, RemoteIP: string);
begin
inherited CreateInitialized(AOwner, SessionID, RemoteIP);
FLoginTime := Now;
end;
// configure the server before it starts
TsgcWebSocketHTTPServer1.SessionState := True;
TsgcWebSocketHTTPServer1.SessionTimeout := 600000;
TsgcWebSocketHTTPServer1.SessionClass := TMySession;
TsgcWebSocketHTTPServer1.Active := True;
// and read it back in any request
procedure OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
begin
if ARequestInfo.Session is TMySession then
AResponseInfo.ContentText := TMySession(ARequestInfo.Session).UserName;
end;
세션이 저장되는 방식을 완전히 제어해야 하는 경우, 예를 들어 데이터베이스에 보관하거나 여러 서버 간에 공유하는 경우, 서버가 활성화되기 전에 SessionList 속성에 자체 목록을 할당하십시오. TIdHTTPDefaultSessionList에서 상속하고 가상 CreateSession 메서드를 재정의하십시오. 서버는 CreateUniqueSession에서 이를 내부적으로 호출하므로 고유 세션 ID는 여전히 자동으로 생성됩니다.
자체 SessionList를 할당하면, 목록이 생성할 클래스를 결정하므로 SessionClass 속성은 더 이상 적용되지 않습니다.
type
TMySessionList = class(TIdHTTPDefaultSessionList)
public
function CreateSession(const RemoteIP, SessionID: string)
: TIdHTTPSession; override;
end;
function TMySessionList.CreateSession(const RemoteIP, SessionID: string)
: TIdHTTPSession;
begin
Result := TMySession.CreateInitialized(Self, SessionID, RemoteIP);
SessionList.Add(Result);
end;
// assign it before the server starts
TsgcWebSocketHTTPServer1.SessionList := TMySessionList.Create(nil);
TsgcWebSocketHTTPServer1.Active := True;
OnCreateSession 이벤트를 사용하면 세션 인스턴스를 직접 반환할 수 있지만, 여기에 세션 ID를 할당하지는 않습니다. 일반 생성자로 세션을 생성하면 세션 ID와 세션 쿠키가 비어 있어 다음 요청에서 세션을 다시 찾을 수 없습니다. 대신 SessionClass를 사용하십시오. 이것이 더 간단하며 그 모든 것을 대신 처리해 줍니다.
또한 OnCreateSession 내에서 SessionList.CreateUniqueSession을 호출하지 마십시오. 이 메서드는 이미 새 세션을 목록에 추가하며, 처리기가 반환될 때 서버가 이를 다시 추가하므로 동일한 세션이 목록에 두 번 들어가게 됩니다.