参见英文答案 >
Logout: GET or POST?9个
sample Identity project使用此注销:
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链接?
解决方法
原因很简单,影响用户会话状态的任何事情都不应该是get动作.获取操作应仅用于
idempotent操作(即,多次调用具有相同的效果,并且不会更改状态).
如果你考虑一下,原因应该是显而易见的.浏览器可以自由缓存,甚至可以预取获取URL(许多现代浏览器也可以这样做).您不希望浏览器意外地将您注销,因为它预先获取了一个获取链接.
现在,这不是给定代码的问题,因为我认为浏览器不会预先获取与JavaScript相关联的链接(尽管我可能是错的).
更大的问题是,如果您的注销是get操作,那么任何未经过滤的用户发布数据都可能导致注销.例如,假设您的网站上有一个论坛,并且您允许发布图像.假设有人发布了src =“http:// url-to-log-off-the-site”的图片,这可能会造成很大的破坏,因为你甚至无法查看页面以删除它把你带走
另外,在给定的示例中,Anti-Forgery令牌有一个表单字段,它将被编码到GET中的URL中.您不希望这样做.
您认为使用防伪令牌有点过分是因为您不了解防伪令牌的用途.它们旨在防止攻击者接管您的会话……并且您不希望攻击者将您注销(不要太天真地认为您的站点不够重要,无法攻击,自动漫游器漫游互联网,不关心你的网站有多重要).