65.9K
CodeProject 正在变化。 阅读更多。
Home

ViewState 序列化器、压缩器与加密器

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.75/5 (9投票s)

2007年6月27日

CPOL

4分钟阅读

viewsIcon

37640

downloadIcon

633

这是一个非常完整且健壮的 ViewState 处理程序,它允许:选择序列化方式、压缩和可选的加密。

引言

当人们看到表单中的 ViewState 变得巨大,并且在填充了样式、控件、Grid 后消耗了惊人的带宽时,他们会感到沮丧,这会导致客户端的提交时间非常长。这里有许多解决方案,从简单的压缩器到存储在 Session/Cache 中。

这段代码可以轻松完成工作,但它适用于一个特殊形式:它使用一个特殊的序列化器来处理二进制数据。

一个会让你感兴趣的点是 ViewState 中安全系统范围的缺陷。虽然可以使用服务器密钥进行加密,但有文档指出,在同一服务器上的两个在线商店中,加密的 ViewState 可用于在产品销售中造成欺诈。这种具有易于理解代码的特殊方法可以生成一个难以破解的、每个会话唯一的密钥。

背景

这部分轻量级代码基于一个简单的 ViewState 压缩器:ViewStateCompression

压缩引擎使用了 ICSharpCode SharpZipLib。

这段代码仅在 VB 7.1 (VS2003) 中进行过测试,未在 VS2005 平台中进行测试。

Using the Code

由于时间关系,我不会详细介绍该类(我会的),但会解释其使用条件:(通过查看演示,可以神奇地了解代码是如何工作的;))

该类有两种使用模式:继承和类声明。我推荐使用继承模式,因为它最简单。

继承模式很简单,替换

Public Class formTest1
    Inherits System.Web.UI.Page
    ... 

Public Class formTest1
    Inherits ViewStateSerializer 
    ...

然后在 Page_Load 中配置

SetViewStateValues(EnCrypt As Boolean, Optimize As Boolean)
  • EnCrypt:如果为 True,则启用加密算法,将为每个会话创建随机种子和密钥。
  • Optimize:如果为 True,则启用二进制序列化算法,比其他选项要大,但你可以添加一个大的 DataTable,例如放入 ViewState 中。标准的 .NET 反序列化器在处理大型 DataTable 时会使服务器崩溃,但这个不会 :D
    Private Sub Page_Load(ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles MyBase.Load

        Response.Expires = -1 'important ?!

        If Not IsPostBack Then
             SetViewStateValues(True, False) 'Configuration HERE ! 
         ...
        End If 
    ...
    End Sub 

第二种方法是将代码简单地放置在 Form 类的任何位置。构造函数格式与 SetViewStateValues 相同。

#Region "Overrides Page: Compression / ViewState Cryptography"

    Dim SerialX As New TurboSerializer(True, False)

    Protected Overrides Function LoadPageStateFromPersistenceMedium() As Object
        Try
            Dim viewState As String = Request.Form("__VSTATE")
            Return SerialX.DeSerialize(viewState)
        Catch
            ...
            Return Nothing
        End Try

    End Function

    Protected Overrides Sub SavePageStateToPersistenceMedium(ByVal viewState As Object)
        Try
            RegisterHiddenField("__VSTATE", SerialX.Serialize(viewState))
        Catch
            ...
            RegisterHiddenField("__VSTATE", String.Empty)
        End Try
    End Sub

#End Region

关注点

你可以在表单中使用不同的配置,但是,请在 Init 中使用常量参数进行配置,以防止浏览器缓存失败(Response.Expires = -1)。

现在我写一个表格来帮助你根据需要选择一个 ViewState 模式。

序列化 反序列化 压缩 要使用的数据量 安全 适用场景
普通 ViewState Good 差(二进制) 使用少量数据 低功耗 控件少、分页的 Grid 的表单
普通序列化器 Good 差(二进制) Good 中等 ViewState 开启的 Grid(无分页)
优化序列化器 常规 常规 常规 大量数据(DataTable) 带有 DataTable 和分页 Grid 的 ViewState,或无 ViewState 的 Grid

关于 Sharp VS2005 版本说明

此版本使用 VS2005 的原生压缩(无需 SharpZipLib)。

加密现在使用两个级别的安全性,生成两种类型的密钥(低模式每天使用三次伪随机生成所有会话可更新的密钥,高模式是旧模式)。

此版本的 V1.1 与 Microsoft Ajax 和 Microsoft Ajax Control Toolkit 兼容(仅此一个?)。

注意:这使用了许多 hack 来实现。为了使其正常工作,请查看覆盖部分对代码的调用与 VB 7.x 版本有何不同。

优化模式经过了严格测试。我没有检查它在所有情况下的正确性。

关于 V1.3

这个新版本使用了一个新的选项来选择 MachineKey 加密。不再需要设置 ViewStateEncryptionMode="Never"CompressPage() 现在可以在 Ajax 中工作,并且具有更优化的反序列化/序列化。

关于 V1.2

这个新版本使用了一个新的 API 来管理 ViewState 的加载和保存。现在它与 FW 2.0 和 Ajax 更兼容;请参阅 V1.2 的注释代码以获取更多信息和用法!

请记住,在此版本中,您必须检查是否将 ViewStateEncryptionMode="Never" 设置为能够压缩 ViewState 数据的引擎(加密会生成引擎无法压缩的随机数据!)。
如果您使用该代码压缩所有页面,请注意,在 Microsoft Ajax 中,response.filter 方法(异步回发)不起作用。

历史

  • 2009/09/26:发布了 V1.3 公共 Sharp VS2005 版本(现在使用了一个新的选项来选择 MachineKey 加密;使用更多反射来访问 .NET Serialization API,这一点比旧版本更优化)。
  • 2008/07/28:发布了 V1.2 公共 Sharp VS2005 版本(现在使用 PageStatePersister:更简单、更兼容,并且可以使用 PageAdapter)。
  • 2008/01/12:发布了 V1.1 公共 Sharp VS2005 版本(Microsoft Ajax 支持)。
  • 2007/08/30:发布了 V1.0 公共 Sharp VS2005 版本。
  • 2007/06/27:发布了 V1.0 公共版本。
© . All rights reserved.