对于最常见的场景 — Web 页面中的 JavaScript 访问同一站点上的 Web API 服务,讨论 ASP.NET Web API 的安全性几乎是多余的。如果对用户执行身份验证和授权对 Web 窗体/视图(包含使用服务的 JavaScript)的访问均已设置,则服务可能已具备其所需的所有安全性了。这要归因于 ASP.NET,它会将其用 于验证页面请求的 Cookie 和身份验证信息作为对服务方法的任意客户端 JavaScript 请求的一部分进行发送 。但有一个非常重要的例外: ASP.NET 无法自动防御跨站点请求伪造 (CSRF/XSRF) 攻击(稍后详述)。
除 CSRF 以外,还有两个值得探讨 Web API 服务保护的场景。第一个场景是当服务的使用方为客户端,而 非与 ApiControllers 处于同一个站点上的页面时。这些客户端可能未经过窗体身份验证的审核,也可能未获 取 ASP.NET 用于控制服务访问的 Cookie 和令牌。
第二个场景是需要为服务添加超出 ASP.NET 安全功能范围的身份验证时。ASP.NET 提供的默认身份验证基 于在身份验证期间 ASP.NET 分配给请求的标识。您可能希望扩展该标识,以授权进行基于标识名称或角色以 外条件的访问。
Web API 提供了多种选择,以应对这两种场景。事实上,我将讨论的是接受 Web API 请求上下文的安全性 ,但由于 Web API 与 Web 窗体和 MVC 均以 ASP.NET 为基础,因而了解 Web 窗体或 MVC 安全性的读者一定 会非常熟悉本文中介绍的工具。
有一点需要特别注意: 虽然 Web API 提供了多种身份验证和授权选项,但安全始于主机(IIS 或进行自 托管时创建的主机)。例如,如果需要确保 Web API 服务与客户端之间通信的隐秘性,则至少应开启 SSL。 但这是站点管理员而非开发者的职责。在本文中,我将忽略主机方面的内容,专注于开发者能够/应该为确保 Web API 服务的安全而进行的工作(无论 SSL 开启与否,我讨论的这些工具都能正常工作)。
抵御跨站点请求伪造攻击
当用户访问使用窗体身份验证的 ASP.NET 网站时,ASP.NET 会生成一个 Cookie,表明该用户已经过身份 验证。浏览器会在每次向该站点发出后续请求时发送该 Cookie,而不管请求来自何处。只要会导致浏览器自 动发送之前收到的身份验证信息的任意身份验证方案存在,您的站点就有可能成为 CSRF 的攻击目标。在站点 向浏览器提供安全 Cookie 后,如果用户访问了某个恶意站点,该站点即可向您的服务发送请求,利用浏览器 之前收到的身份验证 Cookie 发动攻击。
为抵御 CSRF 攻击,需要在服务器端生成防伪令牌,并将之嵌入到要在客户端调用中使用的页面中。 Microsoft 提供了 AntiForgery 类及一个 GetToken 方法(可生成特定于发出请求的用户的令牌,当然,此 处的用户可以为匿名用户)。下面的代码生成了两个令牌,并将之嵌入至可在 View 中使用的 ASP.NET MVC ViewBag:
[Authorize(Roles="manager")] public ActionResult Index() { string cookieToken; string formToken; AntiForgery.GetTokens(null, out cookieToken, out formToken); ViewBag.cookieToken = cookieToken; ViewBag.formToken = formToken; return View("Index"); }
针对服务器的任意 JavaScript 调用都需要将该令牌作为请求的一部分予以返回(CSRF 站点没有 此类令牌,也就无法返回它们)。下面的代码(位于 View 中)将动态生成一个将令牌加入请求标题中的 JavaScript 调用:
$.ajax("http://phvis.com/api/Customers",{ type: "get", contentType: "application/json", headers: { 'formToken': '@ViewBag.formToken', 'cookieToken': '@ViewBag.cookieToken' }});
一个稍微复杂点的解决方案是将令牌嵌入至 View 中的隐藏字段,使得这段 JavaScript 代码不会太引人注目。该过程的第一步是将令牌添加到 ViewData 字典 中:
ViewData["cookieToken"] = cookieToken; ViewData["formToken"] = formToken;
接下来,在 View 中将数据嵌入至隐藏字段。使用 HtmlHelper 的 Hidden 方法时,只需传递 ViewDate 中的某个键值,以生成正确的输入标记:
@Html.Hidden("formToken")
生成的输入标记将使用 ViewData 键作为标记的名称和 ID 属性 ,并将从 ViewData 字典检索到的数据放入标记的值属性中。之前代码生成的输入标记将如下所示:
<input id="formToken" name="formToken" type="hidden" value="...token..." />
之后,即可用 JavaScript 代码(跟 View 保存在不同的文件中)从输入标记中检索值并在 ajax 调用中使用 它们:
$.ajax("http://localhost:49226/api/Customers", { type: "get", contentType: "application/json", headers: { 'formToken': $("#formToken").val(), 'cookieToken': $("#cookieToken").val()}});
在 ASP.NET Web 窗体中,通过使用 ClientScriptManager 对象(可从 Page 的 ClientScript 属性检索)的 RegisterClientScriptBlock 方法 插入包含嵌入式令牌的 JavaScript 代码,也可达到同一目的。
string CodeString = "function CallService(){" + "$.ajax('http://phvis.com/api/Customers',{" + "type: 'get', contentType: 'application/json'," + "headers: {'formToken': '" & formToken & "',” + "'cookieToken': '" & cookieToken & "'}});}" this.ClientScript.RegisterClientScriptBlock( typeOf(this), "loadCustid", CodeString, true);
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索javascript
, web api
, 验证
, 请求api
, 窗体
, 令牌
, 服务
, viewbag
, 身份
, asp net mvc 跨控制器
, api asp.net MVC
, asp.net web api
启用Csrf
,以便于您获取更多的相关知识。