Auth

TsgcHTMLAuth: Delphi, C++ Builder 및 .NET에서 sgcHTML 애플리케이션을 위한 서버 측 세션, 로그인 상태 및 CSRF 보호를 제공합니다.

TsgcHTMLAuth

모든 요청의 세션 쿠키, 로그인한 사용자, CSRF 토큰을 소유하는 비시각 컴포넌트입니다. 세션 저장소를 지정하고, 비밀번호를 확인하도록 OnAuthenticate를 처리하고, HTMX 엔진의 Auth 속성을 설정한 다음 RequireLogin으로 라우트를 표시합니다. sgcHTML의 일부이며, sgcHTML은 단독 팩으로 별도 판매됩니다.

컴포넌트 클래스

TsgcHTMLAuth, TsgcHTMLSessionStore_Memory, TsgcHTMLSessionStore_File, TsgcHTMLSession(유닛 sgcHTML_AuthsgcHTML_Session)

렌더링

마크업 없음: 세션 쿠키, CSRF 토큰, 로그인 리디렉션

패밀리

인증

언어

Delphi, C++ Builder, .NET

저장소와 Auth를 생성하고, 라우트를 보호하기

세션 저장소를 지정하고, OnAuthenticate를 처리하고, 엔진에 Auth를 설정한 다음 보호할 라우트를 표시합니다. 그 이후 엔진은 모든 요청의 세션을 읽고, CSRF 토큰을 검사하며, 익명 사용자를 LoginPath로 리디렉션합니다.

uses
  sgcHTML_Session, sgcHTML_Auth, sgcHTMX_Router, sgcHTMX_Engine_Server;

// oHTMX is a TsgcHTMX_Engine_Server, oRouter is a TsgcHTMX_Router
var
  oStore: TsgcHTMLSessionStore_Memory;
  oAuth: TsgcHTMLAuth;
  oRoute: TsgcHTMX_Route;
begin
  oStore := TsgcHTMLSessionStore_Memory.Create(Self);
  oStore.SweepInterval := 60;

  oAuth := TsgcHTMLAuth.Create(Self);
  oAuth.SessionStore := oStore;
  oAuth.IdleTimeout := 1800;       // seconds without a request
  oAuth.AbsoluteTimeout := 43200;  // seconds since sign-in
  oAuth.LoginRateLimit.MaxAttempts := 5;
  oAuth.OnAuthenticate := AuthAuthenticate;
  oHTMX.Auth := oAuth;

  // only a signed-in user reaches /orders
  oRoute := oRouter.Routes.Add;
  oRoute.Path := '/orders';
  oRoute.RequireLogin := True;
  oRoute.OnRoute := OrdersRoute;

  // only a session with one of these roles reaches /admin
  oRoute := oRouter.Routes.Add;
  oRoute.Path := '/admin';
  oRoute.RequireRoles := 'admin,manager';
  oRoute.OnRoute := AdminRoute;
end;

procedure TForm1.AuthAuthenticate(Sender: TObject;
  const aUser, aPassword: string; var aAccept: Boolean;
  var aUserID, aDisplayName: string; const aRoles: TStrings);
begin
  // LoadPasswordHash reads the value stored when the user was created
  aAccept := sgcHTMLPasswordVerify(aPassword, LoadPasswordHash(aUser));
  if aAccept then
  begin
    aUserID := aUser;
    aDisplayName := aUser;
    aRoles.Add('admin');
  end;
end;

// when you create a user, store this hash, never the password
vHash := sgcHTMLPasswordHash('secret');
// includes: sgcHTML_Session.hpp, sgcHTML_Auth.hpp, sgcHTMX_Router.hpp, sgcHTMX_Engine_Server.hpp
// oHTMX is a TsgcHTMX_Engine_Server, oRouter is a TsgcHTMX_Router

TsgcHTMLSessionStore_Memory *oStore = new TsgcHTMLSessionStore_Memory(this);
oStore->SweepInterval = 60;

TsgcHTMLAuth *oAuth = new TsgcHTMLAuth(this);
oAuth->SessionStore = oStore;
oAuth->IdleTimeout = 1800;       // seconds without a request
oAuth->AbsoluteTimeout = 43200;  // seconds since sign-in
oAuth->LoginRateLimit->MaxAttempts = 5;
oAuth->OnAuthenticate = AuthAuthenticate;
oHTMX->Auth = oAuth;

// only a signed-in user reaches /orders
TsgcHTMX_Route *oRoute = oRouter->Routes->Add();
oRoute->Path = "/orders";
oRoute->RequireLogin = true;
oRoute->OnRoute = OrdersRoute;

// only a session with one of these roles reaches /admin
oRoute = oRouter->Routes->Add();
oRoute->Path = "/admin";
oRoute->RequireRoles = "admin,manager";
oRoute->OnRoute = AdminRoute;

void __fastcall TForm1::AuthAuthenticate(TObject *Sender,
  const UnicodeString aUser, const UnicodeString aPassword, bool &aAccept,
  UnicodeString &aUserID, UnicodeString &aDisplayName, TStrings *const aRoles)
{
  // LoadPasswordHash reads the value stored when the user was created
  aAccept = sgcHTMLPasswordVerify(aPassword, LoadPasswordHash(aUser));
  if (aAccept)
  {
    aUserID = aUser;
    aDisplayName = aUser;
    aRoles->Add("admin");
  }
}

// when you create a user, store this hash, never the password
String hash = sgcHTMLPasswordHash("secret");
using esegece.sgcWebSockets;

// htmx is a TsgcHTMX_Engine_Server, router is a TsgcHTMX_Router
var store = new TsgcHTMLSessionStore_Memory();
store.SweepInterval = 60;

var auth = new TsgcHTMLAuth();
auth.SessionStore = store;
auth.IdleTimeout = 1800;       // seconds without a request
auth.AbsoluteTimeout = 43200;  // seconds since sign-in
auth.LoginRateLimit.MaxAttempts = 5;
auth.OnAuthenticate += AuthAuthenticate;
htmx.Auth = auth;

// only a signed-in user reaches /orders
var route = router.Routes.Add();
route.Path = "/orders";
route.RequireLogin = true;
route.OnRoute += OrdersRoute;

// only a session with one of these roles reaches /admin
route = router.Routes.Add();
route.Path = "/admin";
route.RequireRoles = "admin,manager";
route.OnRoute += AdminRoute;

void AuthAuthenticate(object sender, string aUser, string aPassword,
    ref bool aAccept, ref string aUserID, ref string aDisplayName,
    List<string> aRoles)
{
    // LoadPasswordHash reads the value stored when the user was created
    aAccept = sgcHTMLAuthHelpers.sgcHTMLPasswordVerify(aPassword, LoadPasswordHash(aUser));
    if (aAccept)
    {
        aUserID = aUser;
        aDisplayName = aUser;
        aRoles.Add("admin");
    }
}

// when you create a user, store this hash, never the password
string hash = sgcHTMLAuthHelpers.sgcHTMLPasswordHash("secret");

주요 속성 및 메서드

가장 자주 사용하게 되는 멤버.

세션 쿠키

CookieName(기본값 sgcsid), CookiePath, CookieDomain이 쿠키의 형태를 정합니다. CookieSecureCookieHttpOnly는 기본적으로 True이고 CookieSameSitehssLax이며, 다른 값은 hssStricthssNone입니다. hssNone은 항상 Secure를 추가합니다.

타임아웃

IdleTimeout(1800초)은 사용하지 않은 세션을 종료하고, AbsoluteTimeout(43200초)은 활동과 관계없이 로그인 후 그 시간이 지나면 세션을 종료합니다. 0으로 설정하면 해당 검사가 꺼집니다. CurrentSession은 두 가지를 모두 검증하고 모든 요청에서 세션을 갱신합니다.

CSRF 토큰

CSRFProtection은 기본적으로 켜져 있습니다. 모든 세션은 무작위 토큰을 받습니다. IssueCSRF(session)은 이를 반환하고 ValidateCSRF(session, token)은 상수 시간으로 비교합니다. 엔진은 CSRFHeaderName 헤더(X-CSRF-Token) 또는 CSRFFieldName 필드(csrf_token)에서 토큰을 읽고, 토큰이 없는 상태 변경 요청에는 403으로 응답합니다.

htmx와 CSRF

로그인한 세션으로 렌더링된 페이지는 head에 <meta name="csrf-token"><meta name="csrf-header">를 담고 있으며, 함께 제공되는 htmx 스크립트는 GET, HEAD, OPTIONS가 아닌 모든 요청에서 그 헤더로 토큰을 보냅니다. hx-posthx-delete에는 추가 마크업이 필요하지 않습니다.

로그인 유지

RememberMeDays(0은 꺼짐, 최대 3650)가 이를 켜고, RememberCookieName이 쿠키의 이름(sgcrem)을 정합니다. 요청에 유효한 세션은 없지만 유효한 토큰이 있으면 OnLoadUser가 사용자를 다시 불러오고, 새 세션이 발급되며, 토큰이 교체됩니다. 저장소는 검증자의 해시만 보관합니다.

로그인 속도 제한

LoginRateLimitTsgcHTMLAuthRateLimit_Options입니다. 실패한 로그인은 WindowSeconds(300) 동안 클라이언트 IP별, 사용자 이름별로 집계되며, MaxAttempts(5)에 도달하면 해당 IP 또는 사용자가 LockoutSeconds(900) 동안 잠기고, 잠겨 있는 동안에는 OnAuthenticate가 호출되지 않습니다. MaxAttempts = 0은 제한을 끄며 IsLoginLocked(ip, user)는 잠금 여부를 보고합니다.

비밀번호

sgcHTMLPasswordHash(password, iterations)는 무작위 16바이트 솔트와 기본 210000회 반복으로 pbkdf2-sha256$iterations$salt$hash를 반환합니다. sgcHTMLPasswordVerify(password, hash)는 상수 시간으로 비밀번호를 검사하며, 형식이 잘못된 해시에는 False를 반환합니다.

세션 저장소

TsgcHTMLSessionStore_Memory는 세션을 프로세스 안에 보관하며, 백그라운드 정리에는 SweepInterval을 사용합니다. 이 저장소의 IdleTimeoutAbsoluteTimeout은 Auth의 값과 같게 유지하십시오. TsgcHTMLSessionStore_File은 세션마다 JSON 파일 하나를 Folder에 기록하므로 여러 프로세스가 공유할 수 있으며, 파일은 최대 TouchInterval초(60)마다 한 번만 다시 기록합니다. 둘 다 스레드 안전합니다.

세션

TsgcHTMLSessionID, UserID, DisplayName, Roles, 자유 형식의 Values(name=value), CSRFToken, CreatedAt, LastSeen, RemoteIP, UserAgentHash, 그리고 HasRole을 갖습니다. 라우트는 이를 TsgcHTMXRequest.Session으로 읽으며, 익명이면 nil입니다. 저장소는 복사본을 넘겨주므로 변경 사항을 유지하려면 SessionStore.Put을 호출하십시오.

로그인과 로그아웃

Authenticate는 속도 제한을 적용하고 OnAuthenticate를 발생시킵니다. SignIn은 항상 새 세션 ID를 만들고 이전 ID를 삭제하며 새 CSRF 토큰을 발급하여 세션 고정을 방어합니다. SignOut은 하나의 세션을 종료하고 SignOutEverywhere(userID)는 사용자의 모든 세션과 로그인 유지 토큰을 종료합니다. 엔진 밖에서는 Admin CRUD 데모처럼 CurrentSession(cookieHeader, remoteIP, userAgent, setCookies)를 직접 호출하십시오.

라우트 게이트

TsgcHTMX_RouteRequireLogin 또는 RequireRoles(쉼표로 구분하며, 하나만 일치하면 충분합니다)로 표시합니다. 익명 요청은 302로 LoginPath?next=로 리디렉션되며, htmx가 보낸 요청이면 401과 HX-Redirect를 받습니다. 역할이 없는 세션은 403을 받습니다. 엔진은 LoginPathLogoutPath에 대한 POST에도 응답한 다음 AfterLoginPath로 이동합니다.

WebSocket 연결

메시지는 WebSocket 핸드셰이크에서 전송된 쿠키의 세션으로 실행되며, 이는 그 핸드셰이크가 같은 출처에서 온 경우에 한합니다. 그 밖의 메시지는 모두 익명이며, 거부된 메시지에는 응답이 없습니다. TsgcHTMX_Engine_Server.MessageSession(aConnection)OnHTMXMessage에 직접 응답하는 호스트를 위해 연결 뒤의 세션을 반환하며, 호출자가 이를 해제합니다.

계속 살펴보기

온라인 도움말이 찱포넌트의 전체 API 참조 및 사용 가이드입니다.
세션 및 인증 가이드쿠키, CSRF, 라우트 게이트, 로그인 유지, 로그인 속도 제한을 단계별로 설명합니다.
모든 sgcHTML 컴포넌트80개 이상의 컴포넌트 전체 기능 매트릭스를 둘러보십시오.
무료 체험판 다운로드30일 체험판은 60.HTML 데모 프로젝트를 포함하며, 그중 02.AdminCRUD는 TsgcHTMLAuth를 통해 로그인합니다.
가격전체 소스 코드가 포함된 Single, Team 및 Site 라이선스.
최고의 가성비: All-Access모든 eSeGeCe 제품과 프리미엄 지원이 포함되어 연 €1,059부터 이용할 수 있어요.
All-Access 가격 보기

시작할 준비가 되셨습니까?

무료 체험판을 다운로드하고 Delphi, C++ Builder 및 .NET에서 웹 UI를 구축하기 시작하십시오.