ASP.Net MVC 5 高级编程 第7章 成员资格、授权和安全性

时间:2021-05-04 23:13:11

第7章 成员资格、授权和安全性

7.1 安全性

ASP.NET MVC 提供了许多内置的保护机制(默认利用 HTML 辅助方法和Razor 语法进行 HTML编码以及请求验证等功能特性,以及通过基架构建的控制器白名单表单元素来防止重复提交攻击)

永远不要相信用户提交的任何数据。

实际的例子

  • 每次渲染用户提交的数据的时候对其进行编码。
  • 考虑好网站哪些部分允许用户匿名访问,哪些部分需要认证访问。
  • 不要试图自己净化用户的HTML 输入,否则就会失败。
  • 在不需要通过客户端脚本访问cookie时,使用HTTP-only cookie
  • 请记住外部输入不只是显式的表单域。
  • 建议使用AntiXSS 编码器。

黑客、解密高手、垃圾邮件发送者、病毒、恶意软件——它们都想进入计算读查看里面的数据。在阅读本段内容时,我们的电子邮箱很可能已经转发了很多封电子邮件。我们的端口遭到了扫描,而一个自动化的蠕虫病毒很有可能正在尝试通过多种操作系统漏洞找到进入PC的途径。由于这些攻击都是自动的,因此它们在不断地探索,寻找一个开放的系统。

应用程序的构建基于这样一种假设,即只有特定用户才能执行某些操作,而其它用户则不能执行这些操作。

7.2 使用Authorize 特性登录

保护应用程序安全的第一步,同时也是最简单的一步,就是要求用户只有登录系统才能访问应用程序的特定部分。         Authorize Attribute 是ASP.NET MVC 自带的默认授权过滤器,可用来限制用户对操作方法的访问。

Tips:身份验证和授权

身份验证是指通过某种形式的登录机制(包括用户名/密码、OpenID、OAuth 等说明自已身份的项)来核实用户身份。

授权验证是用来核实登录站点的用户是否在他们的权限内执行操作。这通常使用一些基于声明的系统来实现。

Authorize 特性不带任何参数,只要求用户以某种角色登录网站。它禁止匿名访问。

7.2.1 保护控制器操作

实现安全性的一个好方法是,始终使安全性检查尽可能的贴近要保护的对象。可能有其它更高层的检查,但始终都要确保实际资源的安全。

7.2.2 Authorize 特性在表单身份验证和AccountController 控制器中的用法

基本验证信息

        IPrincipal user=httpContext.User;
if(!user.Identity.IsAuthenticated)
{return false;} if(_usersSplit.Length>0&&!_usersSplit.Contains(user.Identity.Name,StringComparer.OrdinalIgnoreCase))
{return false;} if(_rolesSplit.Length>0&&!_rolesSplit.Any(user.IsInRole))
{return false;}
return true;

如果用户身份验证失败,就会返回一个HttpUnauthorizedResult 操作结果,它产生了一个 HTTP 401(未授权)的状态码。

7.2.3 Windows Authentication

为使用Intranet 验证选项,我们需要启用Windows 验证,禁用 Anonymous 验证。

使用全局授权过滤器保障整个应用程序安全

MVC 4中新添加了AllowAnonymous 特性。如果把AuthorizeAttribute 注册为全局过滤器,并且有些方法需要外部访问,那么这些方法只需要使用4中新添加了AllowAnonymous 特性装饰即可。AllowAnonymous 仅对标准的AuthorizeAttribute 有效;对于自定义的授权过滤器,则不一定起作用。全局授权仅对MVC 是全局的

7.3 要求角色成员使用Authorize 特性

Authorize 特性允许指定角色和用户。

Roles 参数可以有多个角色,我们用‘,’分割:

7.4 扩展用户身份

7.4.1 存储用户额外的信息

Code First 模式下只需要在用户类中添加属性。

7.5 通过OAuth 和 OpenID 的外部登录

OAuth 和 OpenID 是开放的标准。这些协议允许用户使用他们已有的账户登录我们的网站。

配置网站以支持OAuth 和 OpenID是非常难以实现的,协议复杂,*提供器对这两种协议的实现方式不一样。MVC 通过在使用Individual User Accounts 身份验证的项目模板中内置支持OAuth 和 OpenID 极大的简化了这一点。

7.5.1 注册外部登录提供器

使用OAuth 提供器的网站要求我们把网站注册为一个应用程序。这样它们会提供给我们一个客户端id 和一个口令。我们利用OAuth 提供器根据这些信息就可以进行验证。

7.5.2 配置OpenID提供器

因为不用注册,不用填写参数,配置OAuth 提供器是非常简单的。

7.5.3 配置OAuth提供器

7.5.4 外部登录的安全性

1,可信的外部登录器

2,要求SSL 登录

从外部提供器到我们网站的回调中包含拥有用户信息的安全令牌,这些令牌允许访问我们的网站。当令牌在Internet 中传递时,使用HTTPS 传输是非常重要的,因为这样可以访问信息拦截。

为访问AccountController 的Login Get 方法并执行HTTPS,支持外部登录的应用程序应该使用 RequireHttps 特性来使用HTTPS

        //
//GET:/Account/login [RequireHttps]
[AllowAnonymous]
pulic ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl=returnUrl;
return View();
}

7.6 Web 应用程序中安全向量

因为Web 应用程序运行在标准的、基于文本的协议(像HTTP和HTML)之上,所以它们特别容易受到自动攻击的伤害。

7.6.1 威胁:跨站脚本(XSS)

1,威胁概述

有两种方法可以实现XSS,一种方法是通过用户将恶意脚本输入到网站中,而这些网站又可以接收“不干净”(unsanitized)的用户输入。另一种方法是通过直接在页面上显示用户的输入。第一种情况被称为“被动注入”(Passive Injection)。用户把“不干净的”的        内容输入到文本框,并把这些数据保存在数据库中,以后再重新在页面上显示。第二种方法称为“主动注入”,涉及用户直接把“不干净”的内容输入到文本框中,这些输入的内容会立刻被显示出来。

2,被动注入

eg:

        "></a><script src="hackScript.js"></script><a href="

3,主动注入

eg:

      http://www.meishizouqi.com?Search=<form action=""><input type="text" name="name" /><input type="password" name="password" /><input type="submit" value="登录" />

4,阻止 XSS

1)对所有内容进行HTML 编码

页面上每一个输出都应该是经过HTML 编码或HTML 特性编码。

2)Html.AttributeEncode 和 Url.Encode

谨记:永远不要信任用户能够接触到或者使用的一切数据,其中包括所有的表单值、URL、cookie或来自第三方源(如OpenID)的个人信息。此外网站所访问的数据库或服务可能没有经过编码,所以不要轻易相信输入应用程序的任何数据,要尽可能的对其编码。

3)JavaScript 编码

黑客可以很随意的利用十六进制转义码随意的向输入内容中插入JavaScript 脚本代码

4)将AntiXSS 库作为ASP.NET 的默认编码器

  • AntiXSS 使用的是一个信任字符的白名单,ASP.NET 默认实现一个有限的不信任字符的黑名单。
  • AntiXSS 的重点是阻止应用程序的漏洞,ASP.NET 关注的是防止HTML 页面显示不被破坏。

在.NET 4.5及更高版本包含 MicroSoft WPL(Web Protection Library)的AntiXSS 编码器。要使用AntiXSS 库需要在 Web.config 的 httpRunTime 中添加以下代码:< httpRuntime ... encoderType="System.Web.Security.AntiXss.AntiXssEncoder,System.Web,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d59a3a"/>

7.6.2 威胁:跨站请求伪造

跨站请求伪造(Cross-Site Request Forgery,CSRF,有时也写作XSRF 表示)要比简单的跨站脚本攻击更具有危险性。

1,威胁概述

eg:

用户退出登录方法为:/account/Logout

用户将评论中提交这样一个标签<img src="/account/Logout">

浏览器将自动向该地址发送Get 请求。

2,阻止 CSRF 攻击

ASP.NET MVC 提供了阻止 CSRF 攻击的方法。

1)令牌验证

Html.AntiForgeryToken 辅助方法会生成一个加密值作为隐藏的输入元素。

该值会与作为会话cookie 存储在用户浏览器的另一个值相匹配。在提交表单时,ActionFilter 会验证这两个值是否相匹配。这种方法可以阻止大部分的CSRF 攻击。

2)幂等的GET 请求

一个幂等操作的特点是执行一次和执行多次的效果是一样的。

一般来说,仅通过POST 修改数据库中或网站上的内容可以有效防御全部的CSRF 攻击。

3) HttpReferrer 验证

HttpReferrer 验证通过使用ActionFilter 处理。这种情况下可以查看提交表单值的客户段是否在目标站点上。

7.6.3 威胁:cookie 盗窃

如果能够窃取某人在一个网站上的身份验证Cookie,就可以在该网站上冒充他,执行他权限内的所有操作。这种攻击依赖于 XSS 漏洞。攻击者需要在目标站点上注入一些脚本,才能窃取 Cookie

*.com 允许在评论中包含提交一定数量的HTML 标记

可以停止脚本对站点中cookie 的访问,需要设置一个简单的标志:HttpOnly

可以在 web.config 文件中对所有的Cookie 设置,也可以为编写的每个Cookie 单独设置。

7.6.4 威胁:重复提交

重复提交:恶意用户向查询字符串或提交的表单添加超出用户最终操作权限的值。

防御重复提交最简单的一个方法是使用[Bind] 特性显式的控制需要由模型绑定器绑定的属性。也可以用 UpdateModel 或 TryUpdateModel 方法的一个重载版本接受一个绑定列表。

7.6.5 威胁:开放重定向

1.威胁概述

那些通过请求(如查询字符串和表单数据)指向重定向URL 的WEB 应用程序可能被篡改,而把用户重定向到外部的恶意URL。这种篡改就被称为开放重定向攻击(open redirection attack)。

可以调用 IsLocalUrl()方法对 returnUrl 参数进行验证。

7.7 适当的错误报告和堆栈跟踪

customErrors 模式有3 个可选设置项,分别是:

  • On:服务器开发最安全选项,因为它总是隐藏错误提示消息。
  • RemoteOnly:向大多数用户展示一般的错误信息,但向拥有服务器访问权限的用户展示完整的错误提示消息。
  • Off:最容易受到攻击的选项,它向每一个网站的访问者展示详细的错误处理。

7.7.1 使用配置转换

使用RemoteOnly 模式替换掉customError 模式。

7.7.2 在生产环境下使用Retail 部署配置

部署配置的是服务器环境下一的 machine.config 文件中的一个简单开关,用来标识ASP.Net 是否在Retail 部署模式下运行。

将deployment/retail 设置为true ,将影响以下几项设置

  • 设置为On,就是最安全的设置
  • 禁用跟踪输出
  • 禁用调试

这些设置可以覆盖Web.config 文件中所有应用程序级别的设置

7.9 小结

Web 应用程序中安全问题总是可以归结为开发人员一方的简单问题:不当的假设、错误信息及缺乏训练等。