13

WebAPI 的一个常见用例是让 MVC 控制器呈现 shell 视图,其中包含然后命中您的 API 以访问数据的 javascript。

但是,假设您有一些昂贵的 API 操作,并且您不希望人们远程访问这些端点——您只希望由您的应用程序提供的 MVC 视图访问它们。你怎么能保护他们?

在这种情况下Request.IsLocal不起作用,因为 javascript 正在从他们机器上的客户端浏览器调用它。即使它确实有效,您也需要深入挖掘HttpContext才能找到此属性——而该解决方案在自托管 WebAPI 中不起作用。

对于需要有效的 API 端点,您可以使用属性IPrincipal保护它们。[Authorize]但是,您希望您的应用程序能够为匿名用户访问的 API 端点呢?

我已经尝试了一个解决方案,并将其作为答案单独发布,因为我不确定它是否是最好的(甚至是好的)方法。

4

2 回答 2

2

如果您的 MVC 站点使用身份验证,您可以为您的 Web API 方法启用表单身份验证。您可以编写一个自定义[Authorize]属性,该属性将检查表单身份验证 cookie 是否存在,该 cookie 将从 AJAX 调用发送,如果存在则构造主体。

另一种可能的解决方案是保护您的 API,tokens它是一种更 RESTful 风格的。这里的想法是,当用户在您的 MVC 网站上进行身份验证时,您可以生成令牌并将其传递给视图,该令牌将在向 Web API 发送 AJAX 请求时使用,这反过来将验证令牌及其签名的有效性。

另一方面,如果您的站点不使用身份验证,那么事情将变得非常复杂,因为您无法知道请求是否来自受信任的客户端,因为您使用 javascript 来调用您的 API 方法。

于 2013-03-12T16:21:01.410 回答
2

在您谈论“您尝试过什么”之前,这是我尝试过的。有用。只是不确定是否有更好的方法。

  1. 创建一个 MVC 操作过滤器并将其添加为Application_Start.

  2. 创建一个 Http (WebAPI) 操作过滤器并将其用于应拒绝远程请求的操作。

全局 MVC 过滤器执行以下操作:

  1. 在请求中查找特定的 cookie。如果 cookie 在那里,它的值被解密。解密后的值应该是 a 的字符串表示形式DateTime,因此请使用DateTime.TryParse它来获取。如果该值被正确解析为 a DateTime,并且DateTime还不到一天,请在此处停止并且不执行任何其他操作。

  2. 如果 cookie 不存在,或者无法解密/解析,或者超过一天,则将新的 cookie 写入浏览器。使用当前DateTime.UtcNow.ToString()作为值,对其进行加密,并用HttpOnly = false.

WebAPI 过滤器执行以下操作:

  1. 在请求中查找特定的 cookie。如果 cookie 存在,请解密其值并尝试将其解析为DateTime.

  2. 如果该值是有效的DateTime并且小于 2 天,请在此处停止并且不执行任何其他操作。

  3. 否则,抛出 403 Forbidden 异常。

关于我当前的实现的一些注意事项。首先,我使用带有共享密钥和盐的 AES 加密。共享密钥存储为appSettingweb.config 中的一个。对于盐,我启用了匿名识别并用作Request.AnonymousID盐。我并不完全喜欢 salt,因为在 WebAPI 控制器中使用它会比较棘手,但只要它不是自托管的,也不是不可能的。

于 2013-03-12T16:23:01.567 回答