Table of Contents

认证

TKWF 使用 Challenge-Response 认证协议,在不传输密码明文的前提下验证用户身份。


Challenge-Response 流程

客户端                          服务器
  │                               │
  │  1. 请求 Challenge            │
  │─────────────────────────────→ │
  │                               │
  │  2. 返回 Challenge (随机数)   │
  │←───────────────────────────── │
  │                               │
  │  3. 提交 Response (Hash(密码 + Challenge)) │
  │─────────────────────────────→ │
  │                               │
  │  4. 验证通过 → 返回 Session   │
  │←───────────────────────────── │

安全特性

  • 密码永不着地 — 网络传输的只有 Hash 结果,不包含密码原文
  • 防重放攻击 — 每次 Challenge 不同,即使截获也无法重放
  • 防中间人 — 服务器验证 Hash 时结合 Challenge 和服务器端存储的密码哈希

配置认证

// Program.cs
builder.ConfigWebAppDomain<AppUserInfo, AppDomainInitializer>(options =>
{
    options.Authentication.ChallengeExpiration = TimeSpan.FromMinutes(5);
    options.Authentication.SessionExpiration = TimeSpan.FromHours(8);
});

客户端调用

获取 Challenge

var challenge = await authClient.GetChallengeAsync("username");
// 返回: { Challenge: "abc123...", Salt: "xyz..." }

提交 Response

var response = ComputeHash(password + challenge.Salt + challenge.Challenge);
var session = await authClient.AuthenticateAsync("username", response);
// 返回: { SessionId: "ses_...", Token: "eyJ..." }

自定义认证

实现 IAuthenticationHandler<TUserInfo> 接口自定义认证逻辑:

public class CustomAuthHandler : IAuthenticationHandler<AppUserInfo>
{
    public async Task<AuthenticationResult> AuthenticateAsync(
        string username, byte[] response, ChallengeContext context)
    {
        // 验证 Response
        // 返回 AuthenticationResult(成功/失败 + 用户信息)
    }
}

参考