2011-02-26 15 views
11

So che ci sono altre domande a riguardo, ma sono obsolete e non riesco a trovare la risposta che sarebbe affidabile ovunque.Quale soluzione OpenID è realmente utilizzata da Stack Overflow?

Cosa viene realmente utilizzato da Stack   Overflow per autentificare gli utenti? Il sito DotNetOpenAuth afferma di esserlo. Ma per me l'aspetto più (visivamente) simile è OAuth C# Library.

Quindi cosa serve veramente? O come posso imitare la stessa interfaccia utente?

Voglio creare la stessa autenticazione OpenID utilizzando ASP.NET MVC.

+0

Ritengo che questa domanda abbia bisogno di un tipo speciale di commento. Da quando è stato chiesto, è stato chiesto che si spostasse su StackOverflow meta, quindi di nuovo su StackOverflow principale, su meta di nuovo e di nuovo su main. Sembra che appartenga a entrambi i siti o forse no? Credo che appartenga a StackOverflow main, dove l'ho postato in origine. Questo perché non ho chiesto per curiosità riguardo al sito SO, ma perché volevo usare la stessa soluzione, la stessa tecnologia. Perciò la risposta di Lirick è una grande risposta alla mia domanda, ma una risposta del genere non ha nulla a che fare con la meta (troppo tecnica) e così resta qui. – drasto

risposta

17

StackOverflow utilizza DotNetOpenAuth.

Dal blog:

ma per fortuna abbiamo un ottimo dialogo con Andrew Arnott, l'autore principale del DotNetOpenAuth libreria open source che usiamo

15

sono stato in grado di ottenere l'autenticazione OpenID con DotNetOpenAuth sul mio sito web (www.mydevarmy.com) in un tempo abbastanza breve (notare che sono un totale di noob in ASP.NET, MVC, DotNetOpenAuth, ecc.).

DotNetOpenAuth viene fornito con vari campioni e hanno anche un campione ASP.NET MVC, ma solo fornire una vista e controller in quel campione e in realtà non hanno un modello che è la M in MVC :) . Successivamente ho chiesto alla seguente domanda su SO:

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

Così come sarebbe un MOLTO SEMPLICE OpenID aspetto login come in MVC? Bene, diamo uno sguardo ...

1. Avrete bisogno di un modello:

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. Avrete bisogno di un controller:

[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. Avrai bisogno di 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> 

Nota che non ti ho fornito la vista Profile, ma che dovrebbe essere abbastanza semplice da capire.

+0

Grazie per questo! Questa è un'ottima risposta!Ci proverò e se funziona dovresti scrivere questo sul tuo blog se ne hai qualcuno. Spero che questo sia stato votato di più. Devo accettare Oded's andwer perché l'ho già promesso. – drasto

+0

@drasto, nessun problema ... Non sono così interessato a ottenere punti su meta e Oded ha più voti positivi. Spero solo che questo sia utile :) – Kiril

+1

@drasto, ho creato un post sul blog su questo: http://codesprout.blogspot.com/2011/03/using-dotnetopenauth-to-create-simple.html – Kiril

Problemi correlati