Auth

TsgcHTMLAuth: sessões no servidor, estado de login e proteção CSRF para uma aplicação sgcHTML, em Delphi, C++ Builder e .NET.

TsgcHTMLAuth

Um componente não visual que é dono do cookie de sessão, do usuário autenticado e do token CSRF de cada requisição. Atribua um armazenamento de sessões, trate OnAuthenticate para verificar a senha, defina a propriedade Auth do engine HTMX e marque as rotas com RequireLogin. Faz parte do sgcHTML, que é vendido de forma independente como um pacote autônomo.

Classe do componente

TsgcHTMLAuth com TsgcHTMLSessionStore_Memory, TsgcHTMLSessionStore_File e TsgcHTMLSession (units sgcHTML_Auth e sgcHTML_Session)

Renderiza

Sem markup: cookies de sessão, tokens CSRF e redirecionamentos de login

Família

Autenticação

Linguagens

Delphi, C++ Builder, .NET

Crie um armazenamento, crie o Auth, proteja uma rota

Atribua um armazenamento de sessões, trate OnAuthenticate, defina Auth no engine e marque as rotas a proteger. A partir daí o engine lê a sessão de cada requisição, verifica o token CSRF e redireciona usuários anônimos para 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");

Principais propriedades & métodos

Os membros que você usa com mais frequência.

CookieName (padrão sgcsid), CookiePath e CookieDomain definem o formato do cookie. CookieSecure e CookieHttpOnly são True por padrão e CookieSameSite é hssLax; hssStrict e hssNone são os outros valores, e hssNone sempre acrescenta Secure.

Timeouts

IdleTimeout (1800 segundos) encerra uma sessão que não foi usada, AbsoluteTimeout (43200 segundos) a encerra esse tempo depois do login, seja qual for a atividade. 0 desativa qualquer uma das verificações. CurrentSession valida as duas e atualiza a sessão a cada requisição.

Tokens CSRF

CSRFProtection vem ativada por padrão. Cada sessão recebe um token aleatório: IssueCSRF(session) o devolve e ValidateCSRF(session, token) o compara em tempo constante. O engine lê o token do cabeçalho CSRFHeaderName (X-CSRF-Token) ou do campo CSRFFieldName (csrf_token) e responde 403 a uma requisição que altera estado e não o traz.

CSRF com htmx

Uma página renderizada para uma sessão autenticada traz <meta name="csrf-token"> e <meta name="csrf-header"> no head, e o script do htmx incluído envia o token nesse cabeçalho em toda requisição que não seja GET, HEAD ou OPTIONS. hx-post e hx-delete não precisam de nenhum markup extra.

Lembrar-me

RememberMeDays (0 significa desligado, no máximo 3650) o ativa e RememberCookieName dá nome ao cookie (sgcrem). Quando uma requisição não tem sessão válida, mas tem um token válido, OnLoadUser recarrega o usuário, uma nova sessão é emitida e o token é rotacionado. O armazenamento guarda apenas um hash do verificador.

Limite de taxa de login

LoginRateLimit é um TsgcHTMLAuthRateLimit_Options. Os logins com falha são contados por IP do cliente e por nome de usuário dentro de WindowSeconds (300); ao atingir MaxAttempts (5), esse IP ou usuário fica bloqueado por LockoutSeconds (900), e OnAuthenticate não é chamado enquanto houver bloqueio. MaxAttempts = 0 desativa o limite e IsLoginLocked(ip, user) informa um bloqueio.

Senhas

sgcHTMLPasswordHash(password, iterations) devolve pbkdf2-sha256$iterations$salt$hash com um salt aleatório de 16 bytes e 210000 iterações por padrão. sgcHTMLPasswordVerify(password, hash) confere uma senha em tempo constante e devolve False para um hash malformado.

Armazenamentos de sessão

TsgcHTMLSessionStore_Memory guarda as sessões no processo, com SweepInterval para uma varredura em segundo plano; mantenha o IdleTimeout e o AbsoluteTimeout dele iguais aos do Auth. TsgcHTMLSessionStore_File grava um arquivo JSON por sessão em Folder, de modo que vários processos possam compartilhá-lo, e regrava um arquivo no máximo a cada TouchInterval segundos (60). Ambos são thread-safe.

A sessão

TsgcHTMLSession guarda ID, UserID, DisplayName, Roles, Values livres (nome=valor), CSRFToken, CreatedAt, LastSeen, RemoteIP e UserAgentHash, além de HasRole. Uma rota a lê como TsgcHTMXRequest.Session, nil quando anônima. Os armazenamentos entregam cópias, então chame SessionStore.Put para manter uma alteração.

Entrar e sair

Authenticate aplica o limite de taxa e dispara OnAuthenticate. SignIn sempre cria um novo id de sessão, apaga o antigo e emite um novo token CSRF, o que protege contra a fixação de sessão. SignOut encerra uma sessão e SignOutEverywhere(userID) encerra todas as sessões e tokens de lembrar-me de um usuário. Fora do engine, chame você mesmo CurrentSession(cookieHeader, remoteIP, userAgent, setCookies), como faz a demonstração Admin CRUD.

Guardas de rota

Marque um TsgcHTMX_Route com RequireLogin ou RequireRoles (separados por vírgula, basta uma correspondência). Uma requisição anônima é redirecionada para LoginPath?next= com um 302, ou recebe 401 mais HX-Redirect quando foi o htmx que a enviou; uma sessão sem o papel recebe 403. O engine também responde ao POST em LoginPath e LogoutPath, e então vai para AfterLoginPath.

Conexões WebSocket

Uma mensagem é executada com a sessão dos cookies enviados no handshake do WebSocket, desde que esse handshake tenha vindo da mesma origem; qualquer outra mensagem é anônima, e uma mensagem negada não recebe resposta. TsgcHTMX_Engine_Server.MessageSession(aConnection) devolve a sessão por trás de uma conexão para um host que responde OnHTMXMessage por conta própria, e quem chama é responsável por liberá-la.

Continue explorando

Ajuda onlineReferência completa da API e guia de uso para este componente.
Guia de sessões e autenticaçãoCookies, CSRF, guardas de rota, lembrar-me e o limite de taxa de login, passo a passo.
Todos os Componentes sgcHTMLExplore a matriz completa de recursos com mais de 80 componentes.
Baixar Versão de Avaliação GratuitaA avaliação de 30 dias inclui os projetos de demonstração 60.HTML, entre eles o 02.AdminCRUD, que faz login por meio do TsgcHTMLAuth.
PreçosLicenças Single, Team e Site com código-fonte completo.
Melhor custo-benefício: All-AccessTodos os produtos da eSeGeCe, com Suporte Premium incluído, a partir de €1,059/ano.
Ver preços do All-Access

Pronto para Começar?

Baixe a versão de avaliação gratuita e comece a construir UIs web em Delphi, C++ Builder e .NET.