以下是该场景:当新用户注册到我们的网站时,我们希望发送电子邮件以验证用户是否拥有该电子邮件地址。在电子邮件中有一个指向要进行验证的页面的链接,如下所示:
http://www.mysite.com/account/verify/token
验证方法如下所示:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Verify(Nullable<Guid> id)
{
// tries to get the user based on the verification code
if (ValidId(id))
{
// if the id is correct, update user data in the model and redirect
return RedirectToAction("Index", "Dashboard");
}
else
{
// redirects the user to the verify view
return View("Verify");
}
}
“验证”视图只是一个带有按钮的文本框,因此用户可以手动输入验证码(用户可以从站点访问此页面,并且可能更喜欢复制粘贴代码)。当用户点击按钮时,我想做我的 GET 方法所做的事情;所以我最终得到了这样的东西:
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult Verify(Nullable<Guid> id) { ... }
我对此代码有两个问题(可行,但......):
由于
答案 0 :(得分:1)
我正在使用GET方法修改数据......这是一个很大的NO NO
我不会说它总是一个大不,不。 HTTP说GET方法“应该”是“安全的”,也就是除了信息检索之外它应该没有任何效果。在这种情况下,我认为将“安全”的定义扩展为没有任何有害的副作用是合理的,事实上,您的验证链接可能产生的唯一可能的副作用是理想的。
GET方法应该具有的另一个属性是幂等性:如果用户多次点击验证链接,那就像他们只点击一次一样。希望您拥有此属性,因为使用一次性代码生成验证链接。
答案 1 :(得分:1)
我个人不会打扰AcceptVerbs
属性。 (**见下面的注释)然后,您可以将其合并为一个动作,可以根据需要进行响应。 (在下面显示一些未经测试的代码。)我添加答案而不仅仅是注释的原因是我想建议你再添加一个分支到你的逻辑,以处理失败的代码(即,提出错误消息)
public ActionResult Verify(Nullable<Guid> id)
{
if (!id.HasValue)
{
// nothing was submitted
ViewData["message"] = "Please enter your ID and press Submit";
return View("Verify");
}
if (!ValidId(id))
{
// something was submitted, but wasn't valid
ViewData["message"] = "ID is invalid or incomplete. Pleaes check your speeling";
return View("Verify");
}
// must be valid
return RedirectToAction("Index", "Dashboard");
}
然后,您当然可以在验证视图中显示<%=ViewData["message"]%>
。这当然只是一个简单的例子。
**好的,这是我的笔记RE:没有打扰AcceptVerbs
属性:
在您的方案中,您也可以选择制作表单的方法GET
而不是POST
。因为您已经“采取行动”并在用户点击的便捷链接上修改状态,所以我不会看到任何差异。我只是提到这是彻底的,即使我个人选择我以前的建议。
答案 2 :(得分:0)
我不得不说很难找到一个如此关注使用正确的HTTP动词的人。我不相信HTTP规范的初衷是将所有数据编辑提交限制为POST以及将所有检索限制为GET。我觉得你做的很好。
答案 3 :(得分:-1)
如果你担心它,那么这有什么问题?
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Verify()
{
return View("Verify");
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Verify(Guid? id)
{
if (ValidId(id))
{
return RedirectToAction("Index", "Dashboard");
}
return View("Verify");
}