我正在开发一个完全由ajax驱动的应用程序,其中所有请求都通过一个基本上等于一个主控制器的主控制器,该主控制器看起来像这样:
if(strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { fetch($page); }
这通常足以防止跨站点请求伪造吗?
当没有随每个请求刷新整个页面时,具有旋转令牌是很不方便的。
我想我可以在每次请求时都将唯一令牌作为全局javascript变量传递和更新-但是以某种方式感到笨拙并且似乎本质上不安全。
编辑-也许像用户的UUID这样的静态令牌总比没有好?
编辑#2-正如 The Rook 指出的那样,这可能是一个令人毛骨悚然的问题。我已经阅读了两种方式的猜测,并听到了关于低版本Flash可用于这种恶作剧的遥远的耳语。由于我对此一无所知,因此我向所有可以解释这是CSRF风险的人悬赏。否则,我会将其交给 Artefacto 。谢谢。
我会说就足够了。如果允许跨域请求,那么您将注定要失败,因为攻击者可能会使用Javascript来获取CSRF令牌并将其用于伪造的请求中。
静态令牌不是一个好主意。每个会话至少应生成一次令牌。
EDIT2 Mike毕竟不对,抱歉。我没有正确阅读链接到的页面。它说:
一个简单的跨站点请求是这样的:[…]不使用HTTP请求设置自定义标头(例如X-Modified等)。
因此,如果您设置了X-Requested- With,则该请求必须是预先执行的,除非您响应OPTIONS授权跨站点请求的飞行前请求,否则该请求将无法通过。
X-Requested- With
OPTIONS
编辑 Mike是正确的,从Firefox 3.5开始,允许跨站点XMLHttpRequests 。因此,您还必须检查Origin标题(如果存在)是否与您的站点匹配。
Origin
if (array_key_exists('HTTP_ORIGIN', $_SERVER)) { if (preg_match('#^https?://myserver.com$#', $_SERVER['HTTP_ORIGIN']) doStuff(); } elseif (array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) && (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')) doStuff();