一个常见的用例的WebAPI将有由MVC控制器,它包含的JavaScript,然后打你的API来访问数据呈现的外壳意见。
但是,假设你有一些昂贵的API操作,你不希望别人远程访问这些端点 - 你只需要你的MVC的意见,您的应用程序交付,来访问它们。 你怎么能去保护他们?
在这种情况下Request.IsLocal
不起作用,因为JavaScript是从客户的其计算机上的浏览器调用它。 即使没有工作,你需要挖掘才能获得真正HttpContext
,以便找到这个属性-和解决方案无法在自托管的WebAPI工作。
对于需要有效的API端点IPrincipal
,你可以和保护他们[Authorize]
属性。 但对于API端点您想您的应用程序能够访问为匿名用户?
我已经尝试了解决方案,将分别张贴作为一个答案,因为我不知道这是否是最好的(甚至是好)的办法。
如果你的MVC站点使用的认证,你可以使窗体身份验证为您的Web API方法。 你可以写一个自定义[Authorize]
属性,该属性将检查窗体身份验证cookie的存在将来自AJAX调用,如果目前结构的主要发送。
另一种可能的解决方案是保护您的API tokens
这是一种更RESTful的风格。 这里的想法是,当用户在你的MVC网站进行身份验证您可以生成并传递一个令牌将发送Ajax请求的Web API,它反过来将验证令牌及其签名的有效性时可以使用的视图。
如果在另一方面你的网站不使用身份验证,那么事情就会因为你无法知道,因为你是使用JavaScript调用您的API方法的请求是否来自受信任的客户端的方式变得非常复杂。
你去重弹有关之前“你尝试过什么”,这里是我都试过了。 有用。 只是不知道是否有更好的办法。
创建一个MVC行为过滤器并将其添加为在一个全球性的过滤器Application_Start
。
创建一个HTTP(的WebAPI)动作过滤器并使用它应该拒绝远程请求的动作。
全球MVC过滤器是这样的:
会在请求一个特定的cookie。 如果cookie是存在的,它的价值被解密。 解密的值应该是一个字符串表示DateTime
,所以使用DateTime.TryParse
把它弄出来。 如果该值被正确解析到一个DateTime
,而DateTime
不到一天老了,停在这儿,别的什么也不做。
如果cookie不存在,或者无法解密/解析,或者是超过一天老,写一个新的cookie的浏览器。 使用当前DateTime.UtcNow.ToString()
作为值,对其进行加密,并将其与写入HttpOnly = false
。
该的WebAPI过滤器是这种:
会在请求一个特定的cookie。 如果cookie是存在的,解密它的价值,并尝试分析它作为一个DateTime
。
如果该值是一个有效的DateTime
和不到2天,停在这儿,别的什么也不做。
否则,抛出一个403禁止例外。
一对夫妇约我目前执行本笔记。 首先,我使用AES加密与共享密钥和盐。 共享秘密被存储为appSetting
web.config中。 对于盐,我启用了匿名鉴定和使用Request.AnonymousID
的盐。 我不完全喜欢的盐,因为它的小技巧就得到在一个控制器的WebAPI,但不是不可能的,只要它不是自托管。