ASP.NET 2.0配置文件 - 如何防止为不接受cookie的用户创建记录?

时间:2010-10-08 20:12:33

标签: asp.net cookies asp.net-profiles

我正在使用带有allowAnonymous =“true”的ASP.NET配置文件。我不使用ASP.NET成员资格。我最近仔细研究了aspnetdb数据库并注意到虽然我的网站每天有600-800个唯一访问者,但数据库中仍有4000-5000个“用户”。

显然,这里发生的事情是禁用cookie的用户最终会为每个请求创建一条记录。

我的问题:如果客户端不支持cookie或禁用cookie,我如何防止创建用户和配置文件数据库记录?

1 个答案:

答案 0 :(得分:1)

经过大量的研究和反复试验,我发现了这个问题的解决方案。但是,此解决方案不适用于用户发出的第一个请求,因为无法确定用户是否仅支持来自一个请求的cookie。

我想出了一个聪明的解决方案,它使用AJAX向服务器发出第二个(不可见的)请求,以便在第一个请求时将设置写入配置文件,但前提是启用了cookie和JavaScript。当然,如果您没有在初始请求中存储任何配置文件设置,则无需使用它。有关详细信息,请参阅我的other post

Imports System.Web.Configuration

Public MustInherit Class AnonymousProfile
    Inherits ProfileBase

    Public Shared ReadOnly Property AnonymousCookieName() As String
        Get
            Dim anon As AnonymousIdentificationSection = CType(ConfigurationManager.GetSection("system.web/anonymousIdentification"), AnonymousIdentificationSection)
            Return anon.CookieName
        End Get
    End Property

    Public Shared ReadOnly Property IsAnonymousCookieStored() As Boolean
        Get
            Dim cookies As String = HttpContext.Current.Request.Headers("Cookie")
            Return Not String.IsNullOrEmpty(cookies) AndAlso cookies.IndexOf(AnonymousCookieName) > -1
        End Get
    End Property

    Private ReadOnly Property IsWritable() As Boolean
        Get
            Return IsAnonymous = False OrElse IsAnonymous AndAlso IsAnonymousCookieStored
        End Get
    End Property

    Private Function IsObjectMatch(ByVal obj1 As Object, ByVal obj2 As Object) As Boolean
        If Not obj1 Is Nothing Then
            Return obj1.Equals(obj2)
        Else
            If obj2 Is Nothing Then
                Return True
            Else
                Return False
            End If
        End If
    End Function

    Public Overloads Sub SetPropertyValue(ByVal propertyName As String, ByVal propertyValue As Object)
        If (Not IsObjectMatch(Me.GetPropertyValue(propertyName), propertyValue)) AndAlso IsWritable Then
            MyBase.SetPropertyValue(propertyName, propertyValue)
        End If
    End Sub

    Public Overrides Sub Save()
        If IsWritable Then
            MyBase.Save()
        End If
    End Sub

End Class

简单地说,如果配置文件是匿名的并且尚未从浏览器收到匿名cookie,则此类会阻止编写或保存配置文件。

要使用此类,请将其放入App_Code目录并将“inherits”属性添加到web.config文件中的profile元素,如下所示:

<profile defaultProvider="SqlProvider" inherits="AnonymousProfile">

然后,ASP.NET将在自动生成时从此继承ProfileCommon类。

请注意,AnonymousCookieName和IsAnonymousCookieStored属性已公开共享,因此可以在项目中的任何其他位置使用它们,如下所示:

If AnonymousProfile.IsAnonymousCookieStored Then
   'It is safe to write to the profile here
End If

如果用户拒绝匿名cookie,这可以节省执行不需要运行的代码的一些CPU周期,但并不是必需的,因为新的配置文件类无论如何都会检查。

此示例中还包含另一个错误修复 - 如果将属性设置为已包含的相同值,则原始配置文件类将为“Dirty”,这将导致它更新数据库,即使没有任何更改。在重载的SetPropertyValue方法中检查了这个条件,它解决了这个问题。

Public Overloads Sub SetPropertyValue(ByVal propertyName As String, ByVal propertyValue As Object)
    If (Not IsObjectMatch(Me.GetPropertyValue(propertyName), propertyValue)) AndAlso IsWritable Then
        MyBase.SetPropertyValue(propertyName, propertyValue)
    End If
End Sub

参考:ProfileBase Class (MSDN)