BrookHTTPAuthentication.pas 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. (* _ _
  2. * | |__ _ __ ___ ___ | | __
  3. * | '_ \| '__/ _ \ / _ \| |/ /
  4. * | |_) | | | (_) | (_) | <
  5. * |_.__/|_| \___/ \___/|_|\_\
  6. *
  7. * Microframework which helps to develop web Pascal applications.
  8. *
  9. * Copyright (c) 2012-2021 Silvio Clecio <[email protected]>
  10. *
  11. * Brook framework is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation; either
  14. * version 2.1 of the License, or (at your option) any later version.
  15. *
  16. * Brook framework is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with Brook framework; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *)
  25. { Contains classes for basic HTTP authentication. }
  26. unit BrookHTTPAuthentication;
  27. {$I BrookDefines.inc}
  28. interface
  29. uses
  30. SysUtils,
  31. Marshalling,
  32. libsagui,
  33. BrookHandledClasses;
  34. resourcestring
  35. { Error message @code('Invalid status code: <code>.'). }
  36. SBrookInvalidHTTPStatus = 'Invalid status code: %d.';
  37. type
  38. { Class which holds the user authentication credentials. }
  39. TBrookHTTPCredentials = class(TBrookHandledPersistent)
  40. private
  41. FUserName: string;
  42. FPassword: string;
  43. FHandle: Psg_httpauth;
  44. function GetRealm: string;
  45. procedure SetRealm(const AValue: string);
  46. protected
  47. function GetHandle: Pointer; override;
  48. published
  49. { Creates an instance of @code(TBrookHTTPCredentials).
  50. @param(AHandle[in] Authentication handle.) }
  51. constructor Create(AHandle: Pointer); virtual;
  52. { Authentication protection space (realm). }
  53. property Realm: string read GetRealm write SetRealm;
  54. { Name of the authenticated user. }
  55. property UserName: string read FUserName;
  56. { Password of the authenticated user. }
  57. property Password: string read FPassword;
  58. end;
  59. { Management class to grant, deny, cancel an authentication. }
  60. TBrookHTTPAuthentication = class(TBrookHandledPersistent)
  61. private
  62. FCredentials: TBrookHTTPCredentials;
  63. FHandle: Psg_httpauth;
  64. protected
  65. class procedure CheckStatus(AStatus: Word); static;
  66. {$IFNDEF DEBUG}inline;{$ENDIF}
  67. function GetHandle: Pointer; override;
  68. function CreateCredentials(
  69. AHandle: Pointer): TBrookHTTPCredentials; virtual;
  70. public
  71. { Creates an instance of @code(TBrookHTTPAuthentication).
  72. @param(AHandle[in] Authentication handle.) }
  73. constructor Create(AHandle: Pointer); virtual;
  74. { Destroys an instance of @code(TBrookHTTPAuthentication). }
  75. destructor Destroy; override;
  76. { Deny the authentication sending the reason to the user.
  77. @param(AReason[in] Denial reason.)
  78. @param(AContentType[in] Content type.)
  79. @param(AStatus[in] HTTP status code.) }
  80. procedure Deny(const AReason, AContentType: string;
  81. AStatus: Word); overload; virtual;
  82. { Deny the authentication sending the formatted reason to the user.
  83. @param(AFmt[in] Formatted string.)
  84. @param(AArgs[in] Arguments to compose the formatted reason.)
  85. @param(AContentType[in] Content type.)
  86. @param(AStatus[in] HTTP status code.) }
  87. procedure Deny(const AFmt: string; const AArgs: array of const;
  88. const AContentType: string; AStatus: Word); overload; virtual;
  89. { Deny the authentication sending the reason to the user.
  90. @param(AReason[in] Denial reason.)
  91. @param(AContentType[in] Content type.) }
  92. procedure Deny(const AReason, AContentType: string); overload; virtual;
  93. { Deny the authentication sending the formatted reason to the user.
  94. @param(AFmt[in] Formatted string.)
  95. @param(AArgs[in] Arguments to compose the formatted reason.)
  96. @param(AContentType[in] Content type.) }
  97. procedure Deny(const AFmt: string; const AArgs: array of const;
  98. const AContentType: string); overload; virtual;
  99. { Cancels the authentication loop while the user is trying to access
  100. the server. }
  101. procedure Cancel; virtual;
  102. { Credentials holder. }
  103. property Credentials: TBrookHTTPCredentials read FCredentials;
  104. end;
  105. implementation
  106. { TBrookHTTPCredentials }
  107. constructor TBrookHTTPCredentials.Create(AHandle: Pointer);
  108. begin
  109. inherited Create;
  110. FHandle := AHandle;
  111. FUserName := TMarshal.ToString(sg_httpauth_usr(AHandle));
  112. FPassword := TMarshal.ToString(sg_httpauth_pwd(AHandle));
  113. end;
  114. function TBrookHTTPCredentials.GetHandle: Pointer;
  115. begin
  116. Result := FHandle;
  117. end;
  118. function TBrookHTTPCredentials.GetRealm: string;
  119. begin
  120. SgLib.Check;
  121. Result := TMarshal.ToString(sg_httpauth_realm(FHandle));
  122. end;
  123. procedure TBrookHTTPCredentials.SetRealm(const AValue: string);
  124. var
  125. M: TMarshaller;
  126. begin
  127. SgLib.Check;
  128. SgLib.CheckLastError(sg_httpauth_set_realm(FHandle, M.ToCString(AValue)));
  129. end;
  130. { TBrookHTTPAuthentication }
  131. constructor TBrookHTTPAuthentication.Create(AHandle: Pointer);
  132. begin
  133. inherited Create;
  134. FHandle := AHandle;
  135. FCredentials := CreateCredentials(FHandle);
  136. end;
  137. destructor TBrookHTTPAuthentication.Destroy;
  138. begin
  139. FCredentials.Free;
  140. inherited Destroy;
  141. end;
  142. function TBrookHTTPAuthentication.CreateCredentials(
  143. AHandle: Pointer): TBrookHTTPCredentials;
  144. begin
  145. Result := TBrookHTTPCredentials.Create(AHandle);
  146. end;
  147. class procedure TBrookHTTPAuthentication.CheckStatus(AStatus: Word);
  148. begin
  149. if (AStatus < 100) or (AStatus > 599) then
  150. raise EArgumentException.CreateFmt(SBrookInvalidHTTPStatus, [AStatus]);
  151. end;
  152. function TBrookHTTPAuthentication.GetHandle: Pointer;
  153. begin
  154. Result := FHandle;
  155. end;
  156. procedure TBrookHTTPAuthentication.Deny(const AReason, AContentType: string;
  157. AStatus: Word);
  158. var
  159. M: TMarshaller;
  160. begin
  161. SgLib.Check;
  162. SgLib.CheckLastError(sg_httpauth_deny2(FHandle, M.ToCString(AReason),
  163. M.ToCString(AContentType), AStatus));
  164. end;
  165. procedure TBrookHTTPAuthentication.Deny(const AFmt: string;
  166. const AArgs: array of const; const AContentType: string; AStatus: Word);
  167. begin
  168. Deny(Format(AFmt, AArgs), AContentType, AStatus);
  169. end;
  170. procedure TBrookHTTPAuthentication.Deny(const AReason,
  171. AContentType: string);
  172. var
  173. M: TMarshaller;
  174. begin
  175. SgLib.Check;
  176. SgLib.CheckLastError(sg_httpauth_deny(FHandle, M.ToCString(AReason),
  177. M.ToCString(AContentType)));
  178. end;
  179. procedure TBrookHTTPAuthentication.Deny(const AFmt: string;
  180. const AArgs: array of const; const AContentType: string);
  181. begin
  182. Deny(Format(AFmt, AArgs), AContentType);
  183. end;
  184. procedure TBrookHTTPAuthentication.Cancel;
  185. begin
  186. SgLib.Check;
  187. SgLib.CheckLastError(sg_httpauth_cancel(FHandle));
  188. end;
  189. end.