开发者

How do I set the cookie HTTPOnly flag?

开发者 https://www.devze.com 2022-12-31 03:15 出处:网络
How do I set the开发者_C百科 HTTPOnly flag? the TCookie does not have any method or property to specify the HTTPOnly flag.If you talking about TCookie in HttpApp.pas then there is no built in propert

How do I set the开发者_C百科 HTTPOnly flag? the TCookie does not have any method or property to specify the HTTPOnly flag.


If you talking about TCookie in HttpApp.pas then there is no built in property to support HttpOnly.

You can look at httpApp.pas at the TCookie.GetHeaderValue: string; implementation to verify.

However a Cookie is just something set in the Header and TWebResponse has a CustomHeaders property. Where you could Call Response.CustomHeaders.Add(MyCookieValue);

The following class is a modified version of TCookie to support HttpOnly that you can use to generate the cookie correctly.

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.


Please note that original TCookie.GetHeaderValue() method in HTTPApp.pas may generate an incorrect header when expires > -1 and the system/application time separator is other than the colon sign ":". TCookie.GetHeaderValue() method uses the constant sDateFormat for formatting "Expires" field. Turns out that sDateFormat constant is wrongly defined as:

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

If the user changes the application TimeSeparator variable to something other than the colon sign ":", then the expires time will be formated using another character, and not ":" as specified in RFC 1123 (format “Wdy, DD Mon YYYY HH:MM:SS GMT”). Google Chrome 25+ rejects cookies with time separator other than the colon sign, causing complete failure of web applications using it. So the correct GetHeaderValue() method should be:

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;

I've submited QC #113139 about this.

0

精彩评论

暂无评论...
验证码 换一张
取 消