2011-02-26 13 views
11

Sé que hay otras preguntas sobre esto, pero están desactualizadas, y no puedo encontrar la respuesta que sería confiable en ninguna parte.¿Qué solución OpenID realmente usa Stack Overflow?

¿Qué es realmente utilizado por Stack   Overflow para autentificar a los usuarios? El sitio DotNetOpenAuth dice que sí. Pero para mí la apariencia más (visual) similar es OAuth C# Library.

Entonces, ¿qué es lo que realmente usa? ¿O cómo puedo imitar la misma interfaz de usuario?

Quiero crear la misma autenticación OpenID usando ASP.NET MVC.

+0

Siento que esta pregunta necesita un tipo especial de comentario. Desde que se le preguntó se le preguntó si se había movido a StackOverflow meta, luego de vuelta a StackOverflow principal, a meta otra vez y de regreso a main. ¿Se siente como si perteneciera a ambos sitios o fuera de ellos tal vez? Creo que pertenece a StackOverflow main, donde lo publiqué originalmente. Eso es porque no pregunté por curiosidad sobre el sitio SO en sí, sino porque quería utilizar la misma solución, la misma tecnología. Por lo tanto, la respuesta de Lirick es una gran respuesta a mi pregunta, pero esa respuesta no tiene nada que ver con el meta (demasiado técnico) y por eso se queda aquí. – drasto

Respuesta

17

StackOverflow utiliza DotNetOpenAuth.

Desde el blog:

pero afortunadamente tenemos un excelente diálogo con Andrew Arnott, el autor principal de la biblioteca DotNetOpenAuth de código abierto que utilizamos

15

que era capaz de conseguir la autenticación OpenID con DotNetOpenAuth en mi sitio web (www.mydevarmy.com) en un tiempo bastante corto (tenga en cuenta que soy un total de noob a ASP.NET, MVC, DotNetOpenAuth, etc.).

DotNetOpenAuth viene con varias muestras y que incluso tienen una muestra de ASP.NET MVC, pero sólo proporcionan una vista y controlador en esa muestra y que en realidad no tienen un modelo que es el M en MVC :) . Posteriormente me hizo la siguiente pregunta en SO:

What are the responsibilities of the components in an MVC pattern for a simple login

Entonces, ¿cómo sería una manera muy sencilla OpenID mirada entrada como en la MVC? Bueno, vamos a echar un vistazo ...

1. Se necesita un modelo:

public class User 
{ 
    [DisplayName("User ID")] 
    public int UserID{ get; set; } 

    [Required] 
    [DisplayName("OpenID")] 
    public string OpenID { get; set; } 
} 

public class FormsAuthenticationService : IFormsAuthenticationService 
{ 
    public void SignIn(string openID, bool createPersistentCookie) 
    { 
     if (String.IsNullOrEmpty(openID)) throw new ArgumentException("OpenID cannot be null or empty.", "OpenID"); 

     FormsAuthentication.SetAuthCookie(openID, createPersistentCookie); 
    } 

    public void SignOut() 
    { 
     FormsAuthentication.SignOut(); 
    } 
} 

2. Usted necesitará un controlador:

[HandleError] 
public class UserController : Controller 
{ 
    private static OpenIdRelyingParty openid = new OpenIdRelyingParty(); 
    public IFormsAuthenticationService FormsService { get; set; } 

    protected override void Initialize(RequestContext requestContext) 
    { 
     if (FormsService == null) 
     { 
      FormsService = new FormsAuthenticationService(); 
     } 

     base.Initialize(requestContext); 
    } 

    // ************************************** 
    // URL: /User/LogIn 
    // ************************************** 
    public ActionResult LogIn() 
    { 
     if (User.Identity.IsAuthenticated) 
     { 
      return RedirectToAction("Profile", "User"); 
     } 

     Identifier openID; 
     if (Identifier.TryParse(Request.QueryString["dnoa.userSuppliedIdentifier"], out openID)) 
     { 
      return LogIn(new User { OpenID = openID }, Request.QueryString["ReturnUrl"]); 
     } 
     else 
     { 
      return View(); 
     } 
    } 

    [HttpPost] 
    public ActionResult LogIn(User model, string returnUrl) 
    { 
     string openID = ModelState.IsValid?model.OpenID:Request.Form["openid_identifier"]; 

     if (User.Identity.IsAuthenticated) 
     { 
      return RedirectToAction("Profile", "User"); 
     } 
     else if (!string.IsNullOrEmpty(openID)) 
     { 
      return Authenticate(openID, returnUrl); 
     } 
     else if(ModelState.IsValid) 
     { 
      ModelState.AddModelError("error", "The OpenID field is required."); 
     } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 

    // ************************************** 
    // URL: /User/LogOut 
    // ************************************** 
    public ActionResult LogOut() 
    { 
     if (User.Identity.IsAuthenticated) 
     { 
      FormsService.SignOut(); 
     } 

     return RedirectToAction("Index", "Home"); 
    } 

    // ************************************** 
    // URL: /User/Profile 
    // ************************************** 
    [Authorize] 
    public ActionResult Profile(User model) 
    { 
     if (User.Identity.IsAuthenticated) 
     { 
      // ------- YOU CAN SKIP THIS SECTION ---------------- 
      model = /*some code to get the user from the repository*/; 

      // If the user wasn't located in the database 
      // then add the user to our database of users 
      if (model == null) 
      { 
       model = RegisterNewUser(User.Identity.Name); 
      } 
      // -------------------------------------------------- 

      return View(model); 
     } 
     else 
     { 
      return RedirectToAction("LogIn"); 
     } 
    } 

    private User RegisterNewUser(string openID) 
    { 
     User user = new User{OpenID = openID}; 

     // Create a new user model 

     // Submit the user to the database repository 

     // Update the user model in order to get the UserID, 
     // which is automatically generated from the DB. 
     // (you can use LINQ-to-SQL to map your model to the DB) 

     return user; 
    } 

    [ValidateInput(false)] 
    private ActionResult Authenticate(string openID, string returnUrl) 
    { 
     var response = openid.GetResponse(); 
     if (response == null) 
     { 
      // Stage 2: user submitting Identifier 
      Identifier id; 
      if (Identifier.TryParse(openID, out id)) 
      { 
       try 
       { 
        return openid.CreateRequest(openID).RedirectingResponse.AsActionResult(); 
       } 
       catch (ProtocolException ex) 
       { 
        ModelState.AddModelError("error", "Invalid OpenID."); 

        ModelState.AddModelError("error", ex.Message); 
        return View("LogIn"); 
       } 
      } 
      else 
      { 
       ModelState.AddModelError("error", "Invalid OpenID."); 
       return View("LogIn"); 
      } 
     } 
     else 
     { 
      // Stage 3: OpenID Provider sending assertion response 
      switch (response.Status) 
      { 
       case AuthenticationStatus.Authenticated: 
        Session["FriendlyIdentifier"] = response.FriendlyIdentifierForDisplay; 
        FormsAuthentication.SetAuthCookie(response.FriendlyIdentifierForDisplay, true); 
        if (!string.IsNullOrEmpty(returnUrl)) 
        { 
         return Redirect(returnUrl); 
        } 
        else 
        { 
         return RedirectToAction("Profile", "User"); 
        } 
       case AuthenticationStatus.Canceled: 
        ModelState.AddModelError("error", "Authentication canceled at provider."); 
        return View("LogIn"); 
       case AuthenticationStatus.Failed: 
        ModelState.AddModelError("error", "Authentication failed: " + response.Exception.Message); 
        return View("LogIn"); 
      } 
     } 
     return new EmptyResult(); 
    } 
} 

3. Necesitará una vista:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<YourProject.Models.User>" %> 

<asp:Content ID="loginTitle" ContentPlaceHolderID="TitleContent" runat="server"> 
    Log in - YourWebSiteName 
</asp:Content> 
<asp:Content ID="loginContent" ContentPlaceHolderID="MainContent" runat="server"> 
     <p> 
      <%--- If you have a domain, then you should sign up for an affiliate id with MyOpenID or something like that ---%> 
      Please log in with your OpenID or <a href="https://www.myopenid.com/signup?affiliate_id=????">create an 
       OpenID with myOpenID</a> if you don't have one. 
     </p> 
     <% 
     string returnURL = HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"]); 
     if (returnURL == null) 
     { 
      returnURL = string.Empty; 
     } 

     using (Html.BeginForm("LogIn", "User", returnURL)) 
     {%> 
      <%= Html.LabelFor(m => m.OpenID)%>: 
      <%= Html.TextBoxFor(m => m.OpenID)%> 
      <input type="submit" value="Log in" /> 
     <% 
     } %> 

     <%--- Display Errors ---%> 
     <%= Html.ValidationSummary()%> 
</asp:Content> 

Tenga en cuenta que no le he proporcionado la vista Profile, pero eso debería ser lo suficientemente simple como para averiguarlo.

+0

¡Gracias por esto! ¡Esta es una muy buena respuesta!Lo intentaré y, si funciona, deberías escribir esto en tu blog si es que tienes alguno. Espero que esto haya sido votado más. Tengo que aceptar a Oded's andwer porque ya lo he prometido. – drasto

+0

@drasto, no hay problema ... No estoy tan interesado en obtener puntos en meta y Oded tiene más votos de todos modos. Espero que esto sea útil :) – Kiril

+1

@drasto, creé una publicación de blog sobre esto: http://codesprout.blogspot.com/2011/03/using-dotnetopenauth-to-create-simple.html – Kiril

Cuestiones relacionadas