如何设置cookie HTTPOnly标志?

时间:2010-05-19 20:50:30

标签: delphi

如何设置HTTPOnly标志? TCookie没有任何方法或属性来指定HTTPOnly标志。

2 个答案:

答案 0 :(得分:4)

如果您在HttpApp.pas中谈论TCookie,那么就没有内置属性来支持HttpOnly。

您可以在TCookie.GetHeaderValue: string;实施中查看httpApp.pas以进行验证。

然而,Cookie只是在Header中设置的东西,而TWebResponse有一个CustomHeaders 属性。您可以致电Response.CustomHeaders.Add(MyCookieValue);

以下类是TCookie的修改版本,用于支持HttpOnly,您可以使用它来正确生成cookie。

unit CookieGen;

interface
uses
 Sysutils,Classes,HttpApp;
type
  TCookieGenerator = class(TObject)
  private
    FName: string;
    FValue: string;
    FPath: string;
    FDomain: string;
    FExpires: TDateTime;
    FSecure: Boolean;
    FHttpOnly: Boolean;
  protected
    function GetHeaderValue: string;
  public
    property Name: string read FName write FName;
    property Value: string read FValue write FValue;
    property Domain: string read FDomain write FDomain;
    property Path: string read FPath write FPath;
    property Expires: TDateTime read FExpires write FExpires;
    property Secure: Boolean read FSecure write FSecure;
    property HttpOnly : Boolean read FHttpOnly write FHttpOnly;
    property HeaderValue: string read GetHeaderValue;
  end;

implementation

{ TCookieGenerator }

function TCookieGenerator.GetHeaderValue: string;
begin
  Result := Format('%s=%s; ', [HTTPEncode(FName), HTTPEncode(FValue)]);
  if Domain <> '' then
    Result := Result + Format('domain=%s; ', [Domain]);  { do not localize }
  if Path <> '' then
    Result := Result + Format('path=%s; ', [Path]);      { do not localize }
  if Expires > -1 then
    Result := Result +
      Format(FormatDateTime('"expires="' + sDateFormat + ' "GMT; "', Expires),  { do not localize }
        [DayOfWeekStr(Expires), MonthStr(Expires)]);
  if Secure then Result := Result + 'secure; ';  { do not localize }
  if HttpOnly then Result := Result + 'HttpOnly';  { do not localize }
  if Copy(Result, Length(Result) - 1, MaxInt) = '; ' then
    SetLength(Result, Length(Result) - 2);

end;

end.

答案 1 :(得分:0)

请注意,HTTPApp.pas中的原始TCookie.GetHeaderValue()方法在过期时可能会生成错误的标头&gt; -1和系统/应用程序时间分隔符不是冒号#34;:#34;。 TCookie.GetHeaderValue()方法使用常量sDateFormat进行格式化&#34; Expires&#34;领域。事实证明,sDateFormat常量被错误地定义为:

const 
  sDateFormat = '"%s", dd "%s" yyyy hh:nn:ss';

如果用户将应用程序TimeSeparator变量更改为结肠符号&#34;:&#34;以外的其他值,则过期时间将使用另一个字符格式化,而不是&#34;:&#34;如RFC 1123中所述(格式为“Wdy,DD Mon YYYY HH:MM:SS GMT”)。谷歌浏览器25+拒绝使用除冒号之外的时间分隔符的cookie,导致使用它的Web应用程序完全失败。所以正确的GetHeaderValue()方法应该是:

function TCookieGenerator.GetHeaderValue: string;
const
  _DateFormat = '"%s", dd "%s" yyyy hh":"nn":"ss'; // this is the correct constant. HTTPApp.pas wrongly declares it as sDateFormat = '"%s", dd "%s" yyyy hh:nn:ss';
begin
  Result := Format('%s=%s; ', [HTTPEncode(FName), HTTPEncode(FValue)]);
  if Domain <> '' then
    Result := Result + Format('domain=%s; ', [Domain]);  { do not localize }
  if Path <> '' then
    Result := Result + Format('path=%s; ', [Path]);      { do not localize }
  if Expires > -1 then
    Result := Result +
      Format(FormatDateTime('"expires="' + _DateFormat + ' "GMT; "', Expires),  { do not localize }
        [DayOfWeekStr(Expires), MonthStr(Expires)]);
  if Secure then Result := Result + 'secure; ';  { do not localize }
  if HttpOnly then Result := Result + 'HttpOnly';  { do not localize }
  if Copy(Result, Length(Result) - 1, MaxInt) = '; ' then
    SetLength(Result, Length(Result) - 2);
end;

我已经提交了关于此的QC#113139。