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链接?
答案 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的表单提交。