【问题标题】:Classic Asp cookie expires date does not always get set经典 Asp cookie 过期日期并不总是设置
【发布时间】:2020-02-13 20:07:29
【问题描述】:

我正在尝试在 Classic Asp 中使用 addheader 方法设置 cookie,这是将 HttpOnly 和 Secure 标志添加到 cookie 中的唯一方法。所有代码都可以使用下面的代码 - 但有一个例外,它是到期日期/时间。

<%
Response.AddHeader "Set-Cookie", "testCookie=2000; path=/;HttpOnly;Secure;expires=" & dateAdd("d", 365, Now()) & ";samesite=Strict;HostOnly"
%>

但是,这似乎是与浏览器相关的问题。在 Firefox 中,我可以在开发人员工具的“存储”选项卡中看到设置了过期时间。但在 Chrome 中,它始终保持默认设置,即会话结束时到期。 Edge 也存在同样的问题。

有人遇到过这个问题吗?

【问题讨论】:

  • 你能包括这个的实际输出吗? dateAdd("d", 365, Now()) 返回什么格式?这可能是您的问题。
  • 它返回以下格式:2/13/2021 10:08:31 PM。这有帮助吗?
  • 是否有一些特定的到期日期/时间格式让 Chrome 能够理解它? - 我尝试改变格式但没有成功。

标签: vbscript asp-classic


【解决方案1】:

预计日期格式记录在here。您需要以这种方式生成到期日期。

在经典 ASP 中,您可以使用服务器端 JavaScript 轻松生成此类日期。

<!--#include file="HTTPDate.asp"-->
<%
Response.AddHeader "Set-Cookie", "testCookie=2000; path=/;HttpOnly;Secure;expires=" & HTTPDate(DateAdd("d", 365, Now())) & ";samesite=Strict;HostOnly"
%>

HTTPDate.asp

<script language="javascript" runat="server">
function HTTPDate(vbsDate){
    return (new Date(vbsDate)).toGMTString().replace(/UTC/, "GMT");
}
</script>

编辑:添加了纯 VBScript 解决方案。

<%
Function CurrentTZO()
    With CreateObject("WScript.Shell") 
        CurrentTZO = .RegRead( _ 
        "HKLM\System\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias")
    End With
End Function

Function Pad(text)
    Pad = Right("00" & text, 2)
End Function

Function HTTPDate(ByVal localDate)
    localDate = DateAdd("n", CurrentTZO(), localDate)

    ' WeekdayName and MonthName functions relies on locale
    ' need to produce day and month name abbreviations in en-US locale
    Dim locale : locale = SetLocale("en-US")

    Dim out(5)
    out(0) = WeekdayName(Weekday(localDate), True) & ","
    out(1) = Pad(Day(localDate))
    out(2) = MonthName(Month(localDate), True)
    out(3) = Year(localDate)
    out(4) = Join(Array(Pad(Hour(localDate)), Pad(Minute(localDate)), Pad(Second(localDate))), ":")
    out(5) = "GMT"

    SetLocale locale ' set original locale back 

    HTTPDate = Join(out, " ")
End Function

Response.AddHeader "Set-Cookie", "testCookie=2000; path=/;HttpOnly;Secure;expires=" & HTTPDate(DateAdd("d", 365, Now())) & ";samesite=Strict;HostOnly"
%>

【讨论】:

  • Kul-Tigin,是的,你解决了,现在 Crome 和 Edge 中也设置了 cookie 过期,干得好!
  • @M.Y.我添加了一个纯 VBScript 解决方案。
  • 是的,你确实做到了——很好的实现。然而,通过使用“max-age”而不是“expires”,原始问题又回来了——即 cookie 以会话结束的默认值过期。
  • @M.Y.谢谢。这是我的错,他们一定是expires。已更新。
【解决方案2】:

除了公认的 Kul-Tigin 解决方案之外,我还想为那些也缺少该解决方案的人添加一个 vbscript 解决方案。

<%
Response.AddHeader "Set-Cookie", "testCookie=2000; path=/;HttpOnly;Secure;expires=" & (New UTC).toUTCString(500,"d") & ";samesite=Strict;HostOnly;"


Class UTC

    Public Function toUTCString(ByVal offSet, ByVal offsetType)
        ' ***********************************
        ' Converts vbScript datetime format to 
        ' Universal datetime string format:
        ' Tue, 16 Feb 2021 13:39:24 GMT
        '************************************

        Dim dt: dt = dateAdd(offsetType, offSet, UTCDate(Now()))
        Dim tdParts: tdParts = Split(dt, " ")
        Dim tPart: tPart = CDate(tdParts(1) & " " & tdParts(2))
        Dim dPart: dPart = CDate(tdParts(0))

        Dim timeTo24: timeTo24 = _
        Right("0" & Hour(tPart), 2) & ":" & _
        Right("0" & Minute(tPart), 2) & ":" & _
        Right("0" & Second(tPart), 2)

        toUTCString = WeekdayName(Weekday(dPart), True) & ", " & _
                      Day(dPart) & " " & _
                      MonthName(Month(dPart), True) & " " & _
                      Year(dPart) & " " & _
                      timeTo24 & " GMT"

    End Function


    Public Function UTCDate(ByVal dtDate)
        If Not IsDate(dtDate) Then Err.Raise 5
        dtDate = CDate(dtDate)
        Dim ZoneBias: ZoneBias = TimeZoneBias()
        If IsPDT(Now) <> IsPDT(dtDate) Then
            ZoneBias = ZoneBias - 60
        End If
        UTCDate = DateAdd("n", ZoneBias, dtDate)
    End Function

    Private Function IsPDT(ByVal dtDate)
        If Not IsDate(dtDate) Then Err.Raise 5
        dtDate = CDate(dtDate)
        Dim pdtLow, pdtUpr, nDaysBack

        pdtLow = DateSerial(Year(dtDate),  3, 31)
        pdtUpr = DateSerial(Year(dtDate), 10, 31)
        pdtLow = DateAdd("h", 2, pdtLow)
        pdtUpr = DateAdd("h", 2, pdtUpr)

        nDaysBack = Weekday(pdtLow) - 1
        If nDaysBack <> 0 Then
            pdtLow = DateAdd("d", -nDaysBack, pdtLow)
        End If

        nDaysBack = Weekday(pdtUpr) - 1
        If nDaysBack <> 0 Then
            pdtUpr = DateAdd("d", -nDaysBack, pdtUpr)
        End If

        IsPDT = (dtDate >= pdtLow And dtDate <= pdtUpr)
    End Function

    Private Function TimeZoneBias()
        Dim LTZone
        With GetObject("winmgmts:" & _
                "{impersonationLevel=impersonate}!\\.\root\cimv2")
            For Each LTZone In .ExecQuery(_
                    "Select * From Win32_ComputerSystem")
                TimeZoneBias = LTZone.CurrentTimeZone
            Next
        End With
        TimeZoneBias = TimeZoneBias * -1
    End Function

End Class

%>

【讨论】:

  • 这种方法缺少一个关键点:时区。除格式外,生产日期必须为 GMT 格式。您需要先将本地时间(在此示例中为Now())转换为 GMT,然后才能按预期工作。
  • 感谢您指出错误 - 我会根据您的建议在时间允许的情况下尝试修复它。
  • 现在我已经尝试通过使用和采用讨论结束部分中给出的类来修复它(参见我的代码中的编辑):stackoverflow.com/questions/14949706/…。这就是现在解决您遇到的问题的方法吗?
  • 不适用于我计算机的语言环境配置。 en-GB 例如。在脚本顶部放置 SetLocale "en-GB" 行以重现该问题。除此之外,它似乎正在工作。
  • 每当我在脚本开头使用任何语言环境值的 SetLocale 时,我也会收到错误(来自服务器日志:|27|800a0009|Subscript_out_of_range:_'[number:_2]' HTTP/1.1) .错误发生在 Dim dt 行:dt = dateAdd(offsetType, offSet, UTCDate(Now())))。请注意,我在生产环境中运行代码,而不是在我的 PC 的本地主机上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-19
相关资源
最近更新 更多