Какое решение OpenID используется Stack Overflow?

Я знаю, что есть другие вопросы об этом, но они устарели, и я не могу найти ответ, который был бы надежным где угодно.

Что действительно используется Qaru для авторизации пользователей? Сайт DotNetOpenAuth утверждает, что это так. Но для меня наиболее (визуально) похоже выглядит OAuth С# Library.

Так что же он действительно использует? Или как я могу имитировать один и тот же интерфейс?

Я хочу создать ту же аутентификацию OpenID с помощью ASP.NET MVC.

Ответ 1

StackOverflow использует DotNetOpenAuth.

Из blog:

но, к счастью, у нас отличный диалог с Эндрю Арноттом, основным автором библиотеки DotNetOpenAuth с открытым исходным кодом, которую мы используем

Ответ 2

Мне удалось получить аутентификацию OpenID с DotNetOpenAuth на моем веб-сайте (www.mydevarmy.com) за довольно короткое время (примечание что я полный noob для ASP.NET, MVC, DotNetOpenAuth и т.д.).

DotNetOpenAuth поставляется с различными образцами, и у них даже есть образец ASP.NET MVC, но они предоставляют только представление и контроллер в этом образце, и на самом деле у них нет модели, которая является M в MVC:). Впоследствии я задал следующий вопрос о SO:

Каковы обязанности компонентов в шаблоне MVC для простого входа в систему.

Итак, как в MVC будет выглядеть VERY SIMPLE OpenID-login? Ну, давайте посмотрим...

1. Вам понадобится модель:

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. Вам понадобится контроллер:

[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. Вам понадобится представление:

<%@ 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="#" onclick="location.href='https://www.myopenid.com/signup?affiliate_id=????'; return false;">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>

Обратите внимание, что я не предоставил вам представление Profile, но это должно быть достаточно простым, чтобы понять.