在网站开发中,保护用户数据的安全至关重要。本文将介绍一种简单的方法,用于自动加密隐藏表单字段,以防止用户篡改或查看这些字段的值。将使用HtmlHelper扩展、自定义ModelBinder以及Rijndael加密算法来实现这一功能。
在内容管理系统(CMS)中,希望用户只能编辑他们自己创建的帖子。例如,如果用户尝试编辑不属于他们的帖子,那么在后端应该有一个检查机制来确保用户有权限编辑该帖子。如果没有这样的检查,用户可能会恶意地编辑其他人的数据。
将使用Rijndael算法来处理加密。这不是唯一的加密方法,可以根据需要选择任何加密算法。在开始之前,请确保项目中有一个合适的加密类。
首先,需要创建一个处理加密的部分。希望简单地将"HiddenFor()"替换为"EncryptedFor()"。为此,需要创建一个接受目标字段的Linq表达式的HtmlHelper扩展。
' 创建一个加密版本的字段
_
Public Function EncryptedFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), _
expression As Expression(Of Func(Of TModel, TProperty))) As MvcHtmlString
Dim name As String
If TypeOf expression.Body Is MemberExpression Then
name = DirectCast(expression.Body, MemberExpression).Member.Name
Else
Dim op = CType(expression.Body, UnaryExpression).Operand
name = DirectCast(op, MemberExpression).Member.Name
End If
' 获取值并加密
Dim value = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData)
Dim encvalue = RijndaelSimple.Encrypt(value.Model, HttpContext.Current.User.Identity.Name)
Return New MvcHtmlString( _
"")
End Function
现在,如果回到表单,应该能够切换到EncryptedFor,它将生成隐藏字段:
如所见,字段名已经附加了"-encrypted",并且值是加密的字符串。
接下来,需要处理解密和设置值。MVC模型绑定器显然不知道字段"DatabaseID-encrypted"实际上是为了字段"DatabaseID"。需要创建一个自定义模型绑定器,它在Request.Form中查找字段,解密它,然后设置属性。
Public Class EncryptedModelBinder
Inherits DefaultModelBinder
Protected Overrides Sub BindProperty(controllerContext As ControllerContext, _
bindingContext As ModelBindingContext, _
propertyDescriptor As System.ComponentModel.PropertyDescriptor)
If controllerContext.HttpContext.Request.Form(propertyDescriptor.Name & "-encrypted") IsNot Nothing Then
Dim decvalue = controllerContext.HttpContext.Request.Form(propertyDescriptor.Name & "-encrypted")
decvalue = RijndaelSimple.Decrypt(decvalue, "Some unique key")
propertyDescriptor.SetValue(bindingContext.Model, _
If(IsNumeric(decvalue), CInt(decvalue), decvalue))
End If
MyBase.BindProperty(controllerContext, bindingContext, propertyDescriptor)
End Sub
End Class
需要在Global.asax.vb文件中注册这个:
ModelBinders.Binders.DefaultBinder = New EncryptedModelBinder
就是这样!
创建了一个简单的方法,用于从回发中转储request.form的内容,并输出字段的值。如所见,加密的值被传回,但属性已正确设置!
request.form的内容:
DatabaseID-encrypted: SVwvHJ8kzCeIjIN4VZeJLw==
模型上的DatabaseID设置为:2012