Какое решение OpenID действительно используется переполнением стека? - PullRequest
11 голосов
/ 26 февраля 2011

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

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

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

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

Ответы [ 2 ]

17 голосов
/ 26 февраля 2011

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

Из блога :

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

15 голосов
/ 26 февраля 2011

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

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

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

Так как бы ОЧЕНЬSIMPLE Вход в OpenID похож на MVC?Что ж, давайте посмотрим ...

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

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

...