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

h b*_*bob 8 asp.net asp.net-mvc asp.net-identity

示例标识项目使用该注销:

@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>
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Eri*_*sch 11

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

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

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

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

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

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