Я столкнулся с проблемой установки нескольких файлов cookie в фильтре ISAPI. Я хочу добавить HttpOnly
флаг во все куки.
Итак, в моей первой попытке я разделил значение куки и добавил HttpOnly
флаг, затем я объединяю их в одну строку, вызывать pResponse->SetHeader(pfc, "Set-Cookie:", szNewValue)
в конце концов, браузер получает только первое значение cookie.
Код 1-й попытки:
cbValue = sizeof(szValue) / sizeof(szValue[0]);
if (pResponse->GetHeader(pfc, "Set-Cookie:", szValue, &cbValue))
{
char szNewValue[MAX_URI_SIZE] = "";
char* token = NULL;
char* context = NULL;
char delim[] = ",";
// szValue format like
// "Language=en; expires=Sat, 15-Jul-2113 02:46:27 GMT; path=/; HttpOnly,Language=en; expires=Sat, 15-Jul-2113 02:46:27 GMT; path=/; HttpOnly"// After first split
// token = "Language=en; expires=Sat"// context = " 15-Jul-2113 02:46:27 GMT; path=/; HttpOnly,Language=en; expires=Sat, 15-Jul-2113 02:46:27 GMT; path=/; HttpOnly"token = strtok_s(szValue, delim, &context);
while (token != NULL)
{
strcat_s(szNewValue, token);
if (NULL != context)
{
if (' ' != context[0] && !strstr(token, "HttpOnly"))
{
strcat_s(szNewValue, "; HttpOnly");
}
// context[0] = ' ' means it split the one whole cookie, not an entire cookie, we need append ","// context[0] != '\0' means other cookies after, we need append delimiter ","if (' ' == context[0] || '\0' != context[0])
{
strcat_s(szNewValue, ",");
}
}
// NULL, function just re-uses the context after the first read.
token = strtok_s(NULL, delim, &context);
}
if (!pResponse->SetHeader(pfc, "Set-Cookie:", szNewValue))
{
// Fail securely - send no cookie!
pResponse->SetHeader(pfc,"Set-Cookie:","");
}
Во второй попытке я разделяю значение cookie и вызываю pResponse->SetHeader(pfc, "Set-Cookie:", szNewValue)
для каждого куки, но браузер получает только последний куки в этом случае.
Код 2-й попытки:
cbValue = sizeof(szValue) / sizeof(szValue[0]);
if (pResponse->GetHeader(pfc, "Set-Cookie:", szValue, &cbValue))
{
char szNewValue[MAX_URI_SIZE] = "";
char* token = NULL;
char* context = NULL;
char delim[] = ",";
// szValue format like
// "Language=en; expires=Sat, 15-Jul-2113 02:46:27 GMT; path=/; HttpOnly,Language=en; expires=Sat, 15-Jul-2113 02:46:27 GMT; path=/; HttpOnly"// After first split
// token = "Language=en; expires=Sat"// context = " 15-Jul-2113 02:46:27 GMT; path=/; HttpOnly,Language=en; expires=Sat, 15-Jul-2113 02:46:27 GMT; path=/; HttpOnly"token = strtok_s(szValue, delim, &context);
while (token != NULL)
{
strcat_s(szNewValue, token);
if (NULL != context)
{
if (' ' != context[0] && !strstr(token, "HttpOnly"))
{
strcat_s(szNewValue, "; HttpOnly");
}
// context[0] = ' ' means it split the one whole cookie, not an entire cookie, we need append ","// context[0] != '\0' means other cookies after, we need append delimiter ","if (' ' == context[0])// || '\0' != context[0])
{
strcat_s(szNewValue, ",");
}
if (' ' != context[0])
{
pResponse->SetHeader(pfc, "Set-Cookie:", szNewValue);
strcpy(szNewValue, "");
}
}
// NULL, function just re-uses the context after the first read.
token = strtok_s(NULL, delim, &context);
}
Я делаю это в IE10 + Win2008 R2. В обоих случаях результирующие строки cookie имеют правильный формат. У кого-нибудь есть подсказки по этому поводу?
Эта проблема существует в основном потому, что когда вы вызываете GetHeader
, вы получаете все куки в одной строке с разделителями-запятыми. Какой будет лучший способ использовать SetHeader
способ установить все куки обратно на ответ?
Я искал решение этой проблемы и нашел много неправильных ответов.
Этот пост был тем, что привело меня к решению.
Исходное опубликованное решение не сработало, поскольку оно использовало SetHeader для каждого файла cookie. SetHeader заменяет заголовок «Set-Cookie:» каждый раз, когда он вызывается, поэтому был установлен только последний Cookie. Вместо того, чтобы использовать SetHeader, я использовал AddHeader для каждого файла cookie. Но перед первым использованием AddHeader я использовал SetHeader с «», чтобы «очистить» заголовок «Set-Cookie:».
Это работало для меня, используя IIS5.1 и IIS7.0
Это решение работает и для куки-файла ASP Session Id.
Я знаю, что Classic ASP — старая технология, но она все еще используется, и нам нужны подобные решения.
Вот мой полный код:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <httpfilt.h>
BOOL WINAPI __stdcall GetFilterVersion(HTTP_FILTER_VERSION *pVer)
{
pVer->dwFlags = SF_NOTIFY_SEND_RESPONSE | SF_NOTIFY_ORDER_HIGH | SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT;
pVer->dwFilterVersion = HTTP_FILTER_REVISION;
strcpy_s(pVer->lpszFilterDesc, sizeof(pVer->lpszFilterDesc), "httpOnly Filter, Version 1.0. JCGalvezV.");
return TRUE;
}
DWORD WINAPI __stdcall HttpFilterProc(HTTP_FILTER_CONTEXT *pfc, DWORD NotificationType, VOID *pvData)
{
DWORD cbBuffer;
char lszBuffer[2000], lszNewBuffer[2000];
HTTP_FILTER_PREPROC_HEADERS *pFPH = (HTTP_FILTER_PREPROC_HEADERS *)pvData;
switch (NotificationType)
{
case SF_NOTIFY_SEND_RESPONSE :
cbBuffer = sizeof(lszBuffer);
if (pFPH->GetHeader(pfc, "Set-Cookie:", lszBuffer, &cbBuffer))
{
char* token = NULL;
char* context = NULL;
char delim[] = ",";
// Delete previous cookies
pFPH->SetHeader(pfc, "Set-Cookie:", "");
token = strtok_s(lszBuffer, delim, &context);
while (token != NULL)
{
strcpy_s(lszNewBuffer, sizeof(lszNewBuffer), token);
if (!strstr(token, "httpOnly"))
strcat_s(lszNewBuffer, sizeof(lszNewBuffer), "; httpOnly");
// AddHeader instead of SetHeader.
pFPH->AddHeader(pfc, "Set-Cookie:", lszNewBuffer);
// next token
token = strtok_s(NULL, delim, &context);
}
}
break;
default :
break;
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
У меня была такая же проблема, и мне нужно было связаться с Microsoft, чтобы решить эту проблему. Когда вы получаете несколько файлов cookie, вы получите полную строку со всеми файлами cookie, разделенными запятыми.
Работа состоит в том, чтобы отделить каждый файл cookie, а затем вызвать метод SetHeader для каждого отдельно.
Важно то, что каждый файл cookie должен иметь уникальную пару имя-значение (http://www.quirksmode.org/js/cookies.html) поэтому каждое изменение может быть правильно отображено.
Решение в псевдокоде
pResponse->GetHeader(pfc, "Set-Cookie:", szValue, &cbValue)
// split cookies here
foreach separated cookie
pResponse->SetHeader(pfc, "Set-Cookie:", oneCookie)
Таким образом, вам не нужно очищать все куки, чтобы добавить их снова.
Ваша первая попытка лучше, чем вторая, потому что вы должны установить заголовок только один раз. Я думаю, что ваш алгоритм разбора строк немного не работает. Я бы попытался упростить это. Сначала разделите заголовок на строки для каждого файла cookie. Затем измените файл cookie, добавив атрибут http only, а затем объедините файлы cookie в один заголовок.