Auth

TsgcHTMLAuth: sgcHTML アプリケーション向けの、サーバーサイドのセッション、ログイン状態、CSRF 保護を、Delphi、C++ Builder、.NET で提供します。

TsgcHTMLAuth

すべてのリクエストについて、セッション Cookie、サインイン中のユーザー、CSRF トークンを管理する非ビジュアルコンポーネントです。セッションストアを割り当て、OnAuthenticate を処理してパスワードを確認し、HTMX エンジンの Auth プロパティを設定して、ルートに RequireLogin を指定します。sgcHTML の一部で、sgcHTML はスタンドアロンのパックとして独立して販売されています。

コンポーネントクラス

TsgcHTMLAuthTsgcHTMLSessionStore_MemoryTsgcHTMLSessionStore_FileTsgcHTMLSession(ユニットは sgcHTML_AuthsgcHTML_Session

レンダリング内容

マークアップなし: セッション Cookie、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)、CookiePathCookieDomain で Cookie の内容を決めます。CookieSecureCookieHttpOnly は既定で TrueCookieSameSitehssLax で、ほかの値は 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 に追加のマークアップは不要です。

ログイン状態の保持(Remember me)

RememberMeDays(0 はオフ、最大 3650)で有効になり、RememberCookieName は Cookie の名前(sgcrem)です。リクエストに有効なセッションがなく、有効なトークンがある場合、OnLoadUser がユーザーを再読み込みし、新しいセッションが発行され、トークンはローテーションされます。ストアが保持するのは検証子のハッシュだけです。

ログインのレート制限

LoginRateLimitTsgcHTMLAuthRateLimit_Options です。失敗したログインは、WindowSeconds(300)の間、クライアント IP とユーザー名ごとに数えられ、MaxAttempts(5)に達するとその IP またはユーザーが LockoutSeconds(900)の間ロックされ、ロック中は OnAuthenticate が呼び出されません。MaxAttempts = 0 でレート制限は無効になり、IsLoginLocked(ip, user) はロックの有無を返します。

パスワード

sgcHTMLPasswordHash(password, iterations) は、pbkdf2-sha256$iterations$salt$hash を返します。ソルトはランダムな 16 バイト、反復回数の既定値は 210000 です。sgcHTMLPasswordVerify(password, hash) はパスワードを定数時間で確認し、形式が正しくないハッシュには False を返します。

セッションストア

TsgcHTMLSessionStore_Memory はセッションをプロセス内に保持し、SweepInterval でバックグラウンドの掃除を行います。その IdleTimeoutAbsoluteTimeout は Auth の値と同じにしてください。TsgcHTMLSessionStore_File はセッションごとに 1 つの JSON ファイルを Folder に書き込むため、複数のプロセスで共有でき、ファイルの書き換えは TouchInterval 秒(60)に 1 回までです。どちらもスレッドセーフです。

セッション

TsgcHTMLSessionIDUserIDDisplayNameRoles、自由な Values(name=value)、CSRFTokenCreatedAtLastSeenRemoteIPUserAgentHash を保持し、HasRole も備えます。ルートは TsgcHTMXRequest.Session としてこれを読み取り、匿名の場合は nil です。ストアはコピーを渡すため、変更を保持するには SessionStore.Put を呼び出してください。

サインインとサインアウト

Authenticate はレート制限を適用して OnAuthenticate を発生させます。SignIn は常に新しいセッション ID を作成し、古いものを削除して新しい CSRF トークンを発行するため、セッション固定攻撃を防げます。SignOut は 1 つのセッションを終了し、SignOutEverywhere(userID) はユーザーのすべてのセッションとログイン状態保持のトークンを終了します。エンジンの外では、Admin CRUD デモのように、CurrentSession(cookieHeader, remoteIP, userAgent, setCookies) を自分で呼び出します。

ルートのゲート

TsgcHTMX_RouteRequireLogin または RequireRoles(カンマ区切りで、1 つ一致すれば十分)を指定します。匿名のリクエストは 302 で LoginPath?next= にリダイレクトされ、htmx が送信した場合は 401 と HX-Redirect が返ります。ロールを持たないセッションには 403 が返ります。エンジンは LoginPathLogoutPath への POST にも応答し、その後 AfterLoginPath に移動します。

WebSocket 接続

メッセージは、WebSocket ハンドシェイクで送信された Cookie のセッションで実行されます。ただし、そのハンドシェイクが同一オリジンから来たものである場合に限ります。それ以外のメッセージは匿名で、拒否されたメッセージには応答がありません。TsgcHTMX_Engine_Server.MessageSession(aConnection) は、OnHTMXMessage に自分で応答するホスト向けに、接続の背後にあるセッションを返し、呼び出し側が解放します。

さらに詳しく

オンラインヘルプこのコンポーネントの完全な API リファレンスと使用ガイドです。
セッションと認証のガイドCookie、CSRF、ルートのゲート、ログイン状態の保持、ログインのレート制限を、順を追って解説します。
すべての sgcHTML コンポーネント80 以上のコンポーネントの全機能マトリックスを閲覧できます。
無料体験版のダウンロード30 日間の体験版には 60.HTML デモプロジェクトが付属し、TsgcHTMLAuth でサインインする 02.AdminCRUD も含まれます。
価格完全なソースコード付きの Single、Team、Site ライセンス。
最もお得な選択: All-AccesseSeGeCe の全製品にプレミアムサポートが付いて、年間 €1,059 からご利用いただけます。
All-Access の価格を見る

始める準備はできましたか?

無料体験版をダウンロードして、Delphi、C++ Builder、.NET で Web UI の構築を始めましょう。