2011-05-24 60 views
6

我正在使用FormsAuthentication与自定义MembershipProvider(所以我确实可以控制提供程序返回的内容)使用ASP.Net Mvc 3应用程序。ASP.Net中的两步验证MVC

该要求强制执行两个步骤的认证过程(用户名和密码,然后是秘密问题)。用户不应该能够访问网站的任何“安全”部分,而无需通过这两个步骤。我不知道这是否是多因素安全,我已经知道了。

请提供有关如何最好地完成此任务的建议。

这里有一些注意事项:

  • 允许我(架构)来使用会话 - 宁愿不要。
  • 对于提供安全内容的控制器,我宁愿使用开箱即用的[Authorize]ActionFilter
  • 负责人希望这两个步骤的URL相同:即www.contoso.com/login/。至少在我的尝试中,当用户在第二步输入一个不正确的答案(他们没有正式登录时,但是我需要确保我仍然在对付半数的问题时,会造成一些微不足道的问题)认证用户的秘密问题/答案)。

谢谢。

回答

4

将自定义视图模型与隐藏表单域结合使用。只要确保它全部通过https完成。

视图模型

public LoginForm 
{ 
    public string UserName { get; set; } 
    public string Password { get; set; } 

    public int SecretQuestionId { get; set; } 
    public string SecretQuestion { get; set; } 
    public string SecretQuestionAnswer { get; set; } 
} 

操作方法

public ActionResult Login() 
{ 
    var form = new LoginForm(); 
    return View(form); 
} 

[HttpPost] 
public ActionResult Login(LoginForm form) 
{ 
    if (form.SecretQuestionId == 0) 
    { 
     //This means that they've posted the first half - Username and Password 
     var user = AccountRepository.GetUser(form.UserName, form.Password); 
     if (user != null) 
     { 
      //Get a new secret question 
      var secretQuestion = AccountRepository.GetRandomSecretQuestion(user.Id); 
      form.SecretQuestionId = secretQuestion.Id; 
      form.SecretQuestion = secretQuestion.QuestionText; 
     } 
    } 
    else 
    { 
     //This means that they've posted from the second half - Secret Question 
     //Re-authenticate with the hidden field values 
     var user = AccountRepository.GetUser(form.UserName, form.Password); 
     if (user != null) 
     { 
      if (AccountService.CheckSecretQuestion(form.SecretQuestionId, form.SecretQuestionAnswer)) 
      { 
       //This means they should be authenticated and logged in 
       //Do a redirect here (after logging them in) 
      } 
     } 
    } 

    return View(form); 
} 

查看

<form> 
    @if (Model.SecretQuestionId == 0) { 
     //Display input for @Model.UserName 
     //Display input for @Model.Password 
    } 
    else { 
     //Display hidden input for @Model.UserName 
     //Display hidden input for @Model.Password 
     //Display hidden input for @Model.SecretQuestionId 
     //Display @Model.SecretQuestion as text 
     //Display input for @Model.SecretQuestionAnswer 
    } 
</form> 

如果你不快乐与发送将用户名和密码返回到隐藏字段中的视图以重新进行身份验证,并确保它们不是作弊......您可以创建一个HMAC或类似的测试项目。

顺便说一句,这个问题似乎像一个问题汇集到一个...所以刚刚回答了如何做一个视图/操作方法的两步验证。

+0

对不起,如果它是多个问题,我只是想提供围绕约束的最大细节。这绝对解决了我的问题,谢谢! – 2011-05-24 19:51:09

0

我可能会做一些事情,第一步让他们输入用户名和密码。检查它是否合适,将它们移到授权标记的视图中,要求它们提出问题的答案。如果他们失败了,就把它们签出来,然后把它们引出来。我不认为这是可能的,除非你呈现局部视图,如果他们离开而没有完成认证过程,你可以签出并清除他们的cookie。

----编辑----- 第二个想法,你可以做一个局部视图,只是不要formauth在他们完成第二部分视图的签名。一些伪代码:

public ActionResult Login(){ 
    get username and password off the view 
    if its valid 
    render a partial view that asks for the secret answer 
    if thats valid 
     forms auth login 
    else 
     try again, get booted, or whatever 
    else 
     get booted, try again, whatever 
} 
+0

我明白这是伪代码,但我不能渲染partialview,然后检查它是否在同一个流中有效。另外,用户名和密码是否必须存在于表单上? (是的,如果它的第一步,但在第二步呢?)。最后,我明白这个方法声明了'ActionResult'的返回,但是这对于安全问题返回一个表示用户名/密码的'ViewResult'和一个'PartialResult'是什么意思? – 2011-05-24 19:18:25

+0

好点 - 看这里:http://stackoverflow.com/questions/5437745/two-step-authentication-in-mvc你可能能够利用, – Fourth 2011-05-24 19:23:20