2011-05-24 20 views
6

Estoy trabajando en una aplicación ASP.Net Mvc 3 usando FormsAuthentication con un MembershipProvider personalizado (así que tengo cierto control sobre lo que devuelve el proveedor).Autenticación de 2 pasos en ASP.Net MVC

Los requisitos exigen un proceso de autenticación de 2 pasos (nombre de usuario y contraseña seguidos de una pregunta secreta). Un usuario no debería poder acceder a ninguna de las secciones "seguras" del sitio sin pasar ambos pasos. Por favor, no mencione si esto es seguridad multifactorial o no, ya lo sé.

Proporcione una recomendación sobre cómo realizar mejor esta tarea.

He aquí algunas consideraciones:

  • me permite (arquitectura) para utilizar la sesión - preferiría no hacerlo.
  • Preferiría utilizar el [Authorize]ActionFilter para Controladores que proporcionan contenido seguro.
  • A las personas a cargo les gustaría que la url para los 2 pasos sea la misma: es decir, www.contoso.com/login/. Al menos en mis intentos, esto ha causado algunos problemas menores, pero no insignificantes, cuando los usuarios ingresan una respuesta incorrecta en el segundo paso (no están oficialmente registrados, pero necesito asegurarme de que todavía estoy trabajando contra la mitad). pregunta/respuesta secreta del usuario autenticado).

Gracias.

Respuesta

4

Utilice un modelo de vista personalizado junto con campos de formulario ocultos. Solo asegúrate de que todo esté hecho sobre https.

modelo de vista

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; } 
} 

métodos de acción

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); 
} 

Ver

<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> 

Si no estás contento con enviar volver a ingresar el nombre de usuario y la contraseña a la vista en campos ocultos para volver a autenticarse y asegurarse de que no estén haciendo trampa ... podría crear un HMAC o algo así para probar.

Por cierto, esta pregunta parece ser un par de preguntas en una ... así que simplemente respondí cómo hacer la autenticación en dos pasos con un método de vista/acción.

+0

lo siento si era más de 1 pregunta, solo quería proporcionar el mayor detalle alrededor de las restricciones. Esto definitivamente resuelve mi problema, ¡gracias! –

0

Probablemente haga algo en el primer paso que les haga ingresar un nombre de usuario y contraseña. Verifíquelo, si es bueno, muévalos a una vista autorizada marcada que les pide que ingresen la respuesta a la pregunta. Si fracasan, apúntalos, arráncalos, lo que sea. No creo que esto sea posible en una vista, a menos que visualice una vista parcial y si se van sin terminar el proceso de autenticación, las firman y borran su cookie.

---- EDIT ----- Pensándolo bien, podría hacer una vista parcial, pero no los firme hasta que completen la segunda parte de la vista parcial. Algunos código de psuedo:

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

Entiendo que esto es un seudocódigo, pero no me es posible hacer una vista parcial y luego verificar si es válido en el mismo flujo. Además, ¿el nombre de usuario y la contraseña existen necesariamente en el formulario? (sí, si es el paso 1, pero ¿qué pasa con el paso 2?). Finalmente, entiendo que el método declara un retorno de 'ActionResult', pero ¿qué significa para esto devolver tanto un' ViewResult' que representa el nombre de usuario/contraseña como un 'PartialResult' para la pregunta de seguridad? –

+0

buen punto - mira aquí: http://stackoverflow.com/questions/5437745/two-step-authentication-in-mvc es posible que pueda aprovechar esa – Fourth

Cuestiones relacionadas