Delphi:如何为基于DelphiMVCFramework的RESTful服务器创建有状态连接
DelphiMVCFramework 3.2.1 会话式登录认证实现方案
你当前每次请求携带Basic认证信息的方式存在重复传参、凭证多次传输的问题,DMVC 3.2.1版本本身就内置了完全匹配你诉求的整套认证机制,不需要从零开发。
核心机制匹配度
这套内置的Token会话认证流程完全覆盖你的需求:
- 提供独立的登录入口,用户一次性提交用户名密码完成校验
- 校验通过后服务端生成临时有效Token返回,后续业务请求仅需携带该Token,无需重复传递用户名密码
- 支持主动调用登出接口立即作废Token
- 内置超时机制,到设定无操作时长后Token自动失效,不需要客户端主动处理
服务端配置步骤
DMVC内置的TMVCClientTokenAuth中间件已经封装了Token生成、校验、失效全流程,只需要按以下步骤挂载即可:
- 在Web模块初始化阶段创建中间件实例,自定义用户名密码校验逻辑、设置超时时间
uses MVCFramework.Auth, MVCFramework.TokenAuth; procedure TServerWebModule.WebModuleInit(Sender: TObject); begin // 初始化Token认证中间件 FMVCClientTokenAuth := TMVCClientTokenAuth.Create( // 自定义凭证校验逻辑,可替换为数据库查询逻辑 function(AContext: TWebContext; const AUsername, APassword: string; var AUser: TPeerUser): Boolean begin Result := (AUsername = '合法用户名') and (APassword = '合法密码'); if Result then AUser.UserName := AUsername; end, // 设置会话超时时间:单位秒,30分钟无操作自动失效 30 * 60 ); // 挂载路由白名单:登录接口允许匿名访问,其余业务接口必须携带合法Token Middleware.Add( procedure(AContext: TWebContext; const ANext: TProc) begin if AContext.Request.PathInfo = '/api/login' then ANext() else FMVCClientTokenAuth.ProcessRequest(AContext, ANext); end ); end; - 在控制器中实现对应的登录、登出接口,直接调用中间件内置方法即可,不需要手写Token生成逻辑
[Path('/api')] TAuthController = class(TMVCController) public [HttpPost, Path('/login'), AllowAnonymous] procedure Login; [HttpGet, Path('/logout')] procedure Logout; end; procedure TAuthController.Login; var Username, Password, GeneratedToken: string; begin Username := Context.Request.Params['username']; Password := Context.Request.Params['password']; GeneratedToken := FMVCClientTokenAuth.GenerateToken(Username, Password); Render( TJSONObject.Create( 'token', GeneratedToken, 'expires_in', FMVCClientTokenAuth.DefaultSessionTimeout ) ); end; procedure TAuthController.Logout; var CurrentToken: string; begin CurrentToken := Context.Request.Headers['X-Auth-Token']; FMVCClientTokenAuth.InvalidateToken(CurrentToken); Render(TJSONObject.Create('message', '登出成功')); end;
客户端(TIdHTTP)改造
只需要对现有请求逻辑做最小修改,不需要改动原有业务代码结构:
- 应用启动后首次调用
/api/login接口,将返回的Token存在本地模块(如你现有DM模块的私有变量中) - 后续所有业务请求,删除原有的Basic认证、用户名密码设置代码,仅需在自定义请求头中携带存储的Token即可
改造后的原getGroupsFromServer方法示例:procedure TDM.getGroupsFromServer; var Http: TIdHTTP; ReqStr: string; begin try Http := TIdHTTP.Create(nil); Http.ReadTimeout := 10000; Http.Request.ContentType := 'application/json'; Http.Request.CharSet := 'utf-8'; Http.Request.Accept := '*/*'; // 替换原有的Basic认证配置,携带本地存储的Token Http.Request.CustomHeaders.AddValue('X-Auth-Token', Self.StoredLoginToken); ReqStr := Http.Get('http://' + SERVER_IP + ':8080/api/groups'); groupsJSON := ReqStr; dsGroups.LoadFromJSONArrayString(ReqStr); dsGroups.First; finally Http.Free; end; end; - 用户主动登出时,携带本地存储的Token调用
/api/logout接口,服务端就会立即作废对应Token
注意事项
- Token默认通过
X-Auth-Token请求头传递,不需要再使用Basic认证头,避免凭证多次暴露 - 超时时间可以根据业务场景调整,高安全场景可缩短到15分钟,普通场景30分钟即可
- 服务端默认将会话Token存在内存中,重启服务端后所有已生成的Token都会自动失效,不会出现残留会话风险
内容的提问来源于stack exchange,提问作者user2005049
相关产品推荐
相关产品推荐

