繁体   English   中英

如何在ISAPI筛选器中设置多个cookie

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM