ViewState 序列化器、压缩器与加密器
这是一个非常完整且健壮的 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 公共版本。