2011-05-24 63 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