Auth

TsgcHTMLAuth: sesje po stronie serwera, stan logowania i ochrona CSRF dla aplikacji sgcHTML, w Delphi, C++ Builder i .NET.

TsgcHTMLAuth

Komponent niewizualny, który zarządza ciasteczkiem sesji, zalogowanym użytkownikiem i tokenem CSRF każdego żądania. Przypisz magazyn sesji, obsłuż OnAuthenticate, aby sprawdzić hasło, ustaw właściwość Auth silnika HTMX i oznacz trasy za pomocą RequireLogin. Jest częścią sgcHTML, który jest sprzedawany niezależnie jako samodzielny pakiet.

Klasa komponentu

TsgcHTMLAuth z TsgcHTMLSessionStore_Memory, TsgcHTMLSessionStore_File i TsgcHTMLSession (jednostki sgcHTML_Auth i sgcHTML_Session)

Renderuje

Bez znaczników: ciasteczka sesji, tokeny CSRF i przekierowania do logowania

Języki

Delphi, C++ Builder, .NET

Utwórz magazyn, utwórz Auth, zabezpiecz trasę

Przypisz magazyn sesji, obsłuż OnAuthenticate, ustaw Auth w silniku i oznacz trasy do zabezpieczenia. Od tego momentu silnik odczytuje sesję każdego żądania, sprawdza token CSRF i przekierowuje anonimowych użytkowników do 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");

Kluczowe właściwości i metody

Składniki, po które sięgasz najczęściej.

Ciasteczko sesji

CookieName (domyślnie sgcsid), CookiePath i CookieDomain kształtują ciasteczko. CookieSecure i CookieHttpOnly domyślnie mają wartość True, a CookieSameSite to hssLax; pozostałe wartości to hssStrict i hssNone, przy czym hssNone zawsze dodaje Secure.

Limity czasu

IdleTimeout (1800 sekund) kończy sesję, która nie była używana, a AbsoluteTimeout (43200 sekund) kończy ją po tym czasie od zalogowania, niezależnie od aktywności. 0 wyłącza każdą z tych kontroli. CurrentSession sprawdza obie i odświeża sesję przy każdym żądaniu.

Tokeny CSRF

CSRFProtection jest domyślnie włączone. Każda sesja dostaje losowy token: IssueCSRF(session) go zwraca, a ValidateCSRF(session, token) porównuje go w stałym czasie. Silnik odczytuje token z nagłówka CSRFHeaderName (X-CSRF-Token) lub z pola CSRFFieldName (csrf_token) i odpowiada 403 na żądanie zmieniające stan, które go nie ma.

CSRF z htmx

Strona wyrenderowana dla zalogowanej sesji zawiera w sekcji head <meta name="csrf-token"> i <meta name="csrf-header">, a dołączony skrypt htmx wysyła token w tym nagłówku przy każdym żądaniu innym niż GET, HEAD lub OPTIONS. hx-post i hx-delete nie wymagają dodatkowych znaczników.

Zapamiętaj mnie

RememberMeDays (0 oznacza wyłączone, maksymalnie 3650) włącza tę funkcję, a RememberCookieName nadaje nazwę ciasteczku (sgcrem). Gdy żądanie nie ma ważnej sesji, ale ma ważny token, OnLoadUser ładuje użytkownika ponownie, wystawiana jest nowa sesja, a token jest rotowany. Magazyn przechowuje tylko skrót weryfikatora.

Limit prób logowania

LoginRateLimit to TsgcHTMLAuthRateLimit_Options. Nieudane logowania są liczone osobno dla każdego adresu IP klienta i dla każdej nazwy użytkownika w ciągu WindowSeconds (300); osiągnięcie MaxAttempts (5) blokuje ten adres IP lub użytkownika na LockoutSeconds (900), a OnAuthenticate nie jest wywoływane, dopóki blokada trwa. MaxAttempts = 0 wyłącza limit, a IsLoginLocked(ip, user) zgłasza blokadę.

Hasła

sgcHTMLPasswordHash(password, iterations) zwraca pbkdf2-sha256$iterations$salt$hash z losową 16-bajtową solą i domyślnie 210000 iteracji. sgcHTMLPasswordVerify(password, hash) sprawdza hasło w stałym czasie i zwraca False dla niepoprawnie zbudowanego skrótu.

Magazyny sesji

TsgcHTMLSessionStore_Memory przechowuje sesje w procesie, z SweepInterval dla czyszczenia w tle; ustaw jego IdleTimeout i AbsoluteTimeout równe tym z Auth. TsgcHTMLSessionStore_File zapisuje jeden plik JSON na sesję w Folder, więc może być współdzielony przez kilka procesów, i przepisuje plik co najwyżej co TouchInterval sekund (60). Oba są bezpieczne wątkowo.

Sesja

TsgcHTMLSession zawiera ID, UserID, DisplayName, Roles, dowolne Values (name=value), CSRFToken, CreatedAt, LastSeen, RemoteIP i UserAgentHash, a do tego HasRole. Trasa odczytuje ją jako TsgcHTMXRequest.Session, nil dla użytkownika anonimowego. Magazyny wydają kopie, więc wywołaj SessionStore.Put, aby zachować zmianę.

Logowanie i wylogowanie

Authenticate stosuje limit prób i wywołuje OnAuthenticate. SignIn zawsze tworzy nowy identyfikator sesji, usuwa stary i wystawia nowy token CSRF, co chroni przed atakiem typu session fixation. SignOut kończy jedną sesję, a SignOutEverywhere(userID) kończy każdą sesję i token zapamiętania logowania użytkownika. Poza silnikiem wywołaj CurrentSession(cookieHeader, remoteIP, userAgent, setCookies) samodzielnie, tak jak robi to demo Admin CRUD.

Zabezpieczanie tras

Oznacz TsgcHTMX_Route za pomocą RequireLogin lub RequireRoles (rozdzielone przecinkami, wystarczy jedno dopasowanie). Anonimowe żądanie jest przekierowywane do LoginPath?next= kodem 302 albo dostaje 401 plus HX-Redirect, gdy wysłał je htmx; sesja bez roli dostaje 403. Silnik odpowiada też na POST do LoginPath i LogoutPath, a następnie przechodzi do AfterLoginPath.

Połączenia WebSocket

Wiadomość jest wykonywana z sesją ciasteczek wysłanych podczas handshake WebSocket, o ile ten handshake pochodził z tego samego origin; każda inna wiadomość jest anonimowa, a odrzucona wiadomość nie dostaje odpowiedzi. TsgcHTMX_Engine_Server.MessageSession(aConnection) zwraca sesję stojącą za połączeniem dla hosta, który sam odpowiada na OnHTMXMessage, a wywołujący musi ją zwolnić.

Poznawaj dalej

Pomoc onlinePełna dokumentacja API i przewodnik użytkowania tego komponentu.
Przewodnik po sesjach i uwierzytelnianiuCiasteczka, CSRF, zabezpieczanie tras, zapamiętanie logowania i limit prób logowania, krok po kroku.
Wszystkie komponenty sgcHTMLPrzejrzyj pełną matrycę funkcji 80+ komponentów.
Pobierz bezpłatną wersję próbną30-dniowa wersja próbna zawiera projekty demonstracyjne 60.HTML, w tym 02.AdminCRUD, który loguje użytkowników przez TsgcHTMLAuth.
CennikLicencje Single, Team i Site z pełnym kodem źródłowym.
Najkorzystniejsza oferta: All-AccessWszystkie produkty eSeGeCe, ze wsparciem Premium w cenie, już od €1,059 rocznie.
Zobacz cennik All-Access

Gotowy, aby zacząć?

Pobierz bezpłatną wersję próbną i zacznij budować interfejsy webowe w Delphi, C++ Builder i .NET.