ASP.NET MVC 不像 ASP.NET WEB FORMS 那样提供了很多自动保护机制来保护页面不受恶意用户的攻击,更明确的说,后者是致力于使应用程序免受攻击:
- 服务器组件对显示的值和特性进行 HTML 编码,以帮助阻止 XSS 攻击。
- 加密和验证试图状态,从而帮助阻止篡改提交的表单。
- 请求验证(%@page validaterequest="true"%)截获看起来是恶意的数据,并给出警告(也是 ASP.NET MVC 框架默认开启的保护)。
- 事件验证帮助组织注入攻击和提交无效值。
ASP.NET MVC 对标记和程序的运行提供了更多控制,这意味着程序员要承担更多的责任。
之所以应用程序存在安全隐患,主要是因为开发人员缺乏足够的信息或理解。另外,人无完人,难免有疏忽的时候,鉴于此,下面是本章的关键总结:
- 永远不要相信用户提供的数据。
- 每当渲染作为用户输入而引入的数据时,要进行 HTML 编码;如果数据作为特性值显示,要进行 HTML 特性编码(HTML-attribute-encode)。
- 考虑网站哪些部分允许匿名访问,哪些部分要求认证访问。
- 在不需要通过客户端脚本(大部分情况下)访问 cookie 时,使用 HTTP-only cookie。
- 记住,外部输入不是显式的表单域,因为它包括 URL 查询字符串、隐藏表单域、Ajax 请求以及我们使用的外部 Web 服务结果等。
- 强烈建议使用 AntiXSS 库(www.codeplex.com/AntiXSS)。
黑客、解密高手、垃圾邮件发送者、病毒、恶意软件,它们都想进入计算机并查看或破坏里面的数据!
使用 Authorize 特性登录
保护应用程序的第一步,也是最简单的一步,就是要求登录系统的用户访问那些由应用程序指定的 URL。我们可以通过控制器上或控制器内部特定操作上的 Authorize 操作过滤器来实现。
Authorize 特性是 ASP.NET MVC 自带的默认授权过滤器,可限制用户对操作方法的访问,若该特性运用于控制器,则会应用于控制器内部所有操作方法。
有时会对用户身份验证和用户授权之间的区别感到困惑,这两个词也比较相似!
- 身份验证:指通过使用登录机制的一些表单(包含用户名 / 密码、OpenID 等)核实用户的身份,即知道他是谁。
- 授权验证:指用来核实该用户是否在他的权限内进行操作,即他能做什么,不能做什么。
授权特性不带任何参数,只要求用户以某种角色身份登录网站,换句话说,禁止匿名访问!
保护控制器操作
现在根据一个非常简单的购物应用需求,创建音乐商店的应用程序。程序中的 StoreController 控制器仅包含 2 个操作,Index 和 Buy:
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using MvcMusicStore.Models;
namespace MvcMusicStore.Controllers
{
public class StoreManagerController : Controller
{
public ActionResult Index()
{
var albums = GetAlbums();
return View(albums);
}
[Authorize]
public ActionResult Buy(int id)
{
var album = GetAlbums().Single(e => e.AlbumId == id);
return View(album);
}
private static List<Album> GetAlbums()
{
var albums = new List<Album> {
new Album {AlbumId = 1, Title = "The Fall of Math", Price = 8.99M},
new Album {AlbumId = 2, Title = "The Blue Notebooks", Price = 8.99M},
new Album {AlbumId = 3, Title = "Lost in Translation", Price = 9.99M},
new Album {AlbumId = 4, Title = "Permutation", Price = 10.99M}
};
return albums;
}
}
}