[英]How to set multiple cookies in ISAPI filter
我遇到了在ISAPI过滤器中设置多个cookie的问题。 我想在所有cookie中添加HttpOnly
标志。
所以,在我的第一次尝试中,我分割了cookie值并添加了HttpOnly
标志,然后我将它们组合成一个字符串,最后调用pResponse->SetHeader(pfc, "Set-Cookie:", szNewValue)
,仅限浏览器获得第一个cookie值。
第一次尝试代码:
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值,并为每个cookie调用pResponse->SetHeader(pfc, "Set-Cookie:", szNewValue)
,但浏览器在这种情况下只获取最后一个cookie。
第二次尝试代码:
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
,您将在一个逗号分隔的字符串中接收所有cookie。 使用SetHeader
方法将所有cookie设置回响应的最佳方法是什么?
我正在寻找这个问题的解决方案,并发现了很多不正确的答案。
这篇文章让我得到了解决方案。
原始发布的解决方案无效,因为它为每个cookie使用SetHeader。 每次调用时,SetHeader都会替换“Set-Cookie:”标题,因此只设置了最后一个Cookie。 我没有使用SetHeader,而是为每个cookie使用AddHeader。 但是,在第一次使用AddHeader之前,我使用SetHeader和“”清空“Set-Cookie:”标题。
这对我来说使用IIS5.1和IIS7.0
此解决方案也适用于ASP Session Id cookie。
我知道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;
}
我有同样的问题,我需要联系微软来解决这个问题。 当您收到多个cookie时,您将收到一个完整的字符串,其中所有的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的字符串。 然后修改cookie以根据需要添加http only属性,然后将cookie组合回单个标头。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.