为什么ASP.NET身份中的Logout使用POST而不是GET?

时间:2014-09-07 13:40:21

标签: asp.net asp.net-mvc asp.net-identity

sample Identity project使用此功能注销:

@if (Request.IsAuthenticated) {
  using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })) {
    @Html.AntiForgeryToken()
    <ul class="nav navbar-nav navbar-right">
       <li>@Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })</li>
       <li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
    </ul>
  }
}

AccountController.LogOff()操作方法有一个[HttpPost]

我可以想到使用POST而不是GET的唯一原因是[ValidateAntiForgeryToken]。我没有看到目的,我们所做的就是退出。

当然这有点矫枉过正?为什么不使用常规的GET链接?

3 个答案:

答案 0 :(得分:11)

原因很简单,影响用户会话状态的任何事情都不应该是get动作。获取操作应仅用于idempotent操作(即,多次调用具有相同的效果,并且不会更改状态)。

如果你考虑一下,原因应该是显而易见的。浏览器可以自由缓存,甚至可以预取获取URL(许多现代浏览器都可以这样做)。您不希望浏览器意外地将您注销,因为它预先获取了一个获取链接。

现在,这不是给定代码的问题,因为我认为浏览器不会预先获取与JavaScript相关联的链接(尽管我可能错了)。

更大的问题是,如果您的注销是获取操作,那么任何未经过滤的用户发布数据都可能导致注销。例如,假设您的网站上有一个论坛,并且您允许发布图像。假设某人发布了src="http://url-to-log-off-the-site"的图片,这可能会造成很大的破坏,因为如果没有它让您退出,您甚至无法查看该页面以将其删除。

此外,在给定的示例中,Anti-Forgery令牌有一个表单字段,它将被编码到GET中的URL中。您不希望这样做。

您认为使用防伪令牌过度是因为您不了解防伪令牌的用途。它们旨在防止攻击者接管您的会话......并且您不希望攻击者将您注销(不要太天真地认为您的网站不够重要攻击,自动漫游器漫游互联网并不关心您的网站有多重要。)

答案 1 :(得分:1)

可能原因是默认情况下POST请求没有缓存(如果他们没有特定的标题),所以当你尝试注销时,你不会得到缓存的响应。< / p>

  

我们正在做的就是退出。

我不认为注销并不重要 - 假设您正在从某些公共电脑访问您的银行帐户 - 我认为您希望100%确定在执行注销时您实际上会被注销。

答案 2 :(得分:1)

为什么一种HTTP方法与另一种方法相比过度?注销会影响服务器状态,因此客户端会将其发布。

查看HTTP method definitions,有security implications推荐POST超过GET:

  

使用HTTP协议的服务的作者不应该使用GET   基于提交敏感数据的表格,因为这样做   导致此数据在Request-URI中编码。许多存在   服务器,代理和用户代理将在某些情况下记录请求URI   第三方可见的地方。服务器可以使用   而是基于POST的表单提交。