- Получение OpenID аккаунта.
- Установка API DotNetOpenAuth.
- Создание тестового проекта на ASP.NET MVC.
- Запуск и тестирование.
Шаг первый, подготовительный. Для работы Вам будет необходим OpenID-аккаунт, поэтому идем на сайт любого провайдера OpenID (например www.myopenid.com) и заводим там аккаунт, например handcode. Если такое все прошло удачно, то например, Ваш OpenID будет иметь следующий вид http://handcode.myopenid.com.
Шаг второй, завязка. Чтобы не писать свою библиотеку, реализующую протокол OpenID заходим на страницу для разработчиков http://openid.net/developers/libraries на которой перечислен список доступных библиотек. Выбираем, интересующую нас, библиотеку под .NET: DotNetOpenAuth. Скачиваем и устанавливаем последнюю версию себе на диск. Кстати, с данным API идет несколько интересных примеров. Именно с примера OpenIdRelyingPartyMvc я и начинал свое изучение.
Шаг третий, аппогей. Открываем Visual Studio, создаем новый ASP.NET MVC проект, назовем его MainSite. Удаляем "мусорный" AccountController и все что с ним связано, оставив только HomeController. Добавим reference на OpenID библиотеку DotNetOpenAuth.dll. Приступаем к программированию. Добавим в проект новый контроллер UserController: using System; using System.Web; using System.Web.Security; using System.Web.Mvc; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OpenId; using DotNetOpenAuth.OpenId.RelyingParty; namespace MainSite.Controllers { public class UserController : Controller { /// <summary> /// DotNetOpenAuth /// </summary> private static OpenIdRelyingParty openIdProvider = new OpenIdRelyingParty(); public ActionResult Index() { // Если пользователь аутентифицирован, то // покажем ему "закрытую" страницу. if (User.Identity.IsAuthenticated) { return View("Index"); } return View("Login"); } /// <summary> /// Завершение сеанса. /// </summary> /// <returns></returns> public ActionResult Logout() { // Обнулим cookies, и выйдем на главную. FormsAuthentication.SignOut(); return RedirectToAction("Index", "Home"); } /// <summary> /// Отобразим форму логина /// </summary> /// <returns></returns> public ActionResult Login() { return View("Login"); } /// <summary> /// Аутентифицирует клиента с userOpenId, делая редирект /// на сайт провайдера OpenID. /// </summary> /// <param name="userOpenId">OpenID клиента</param> /// <returns>Результат аутентификации</returns> public ActionResult Authenticate(string userOpenId) { // Ответ с сайта провайдера. IAuthenticationResponse response = openIdProvider.GetResponse(); // response равен null, если запроса на OpenID провайдер мы не делали. if (response == null) { Identifier id; // Пытаемся распарсить OpenID клиента. if (Identifier.TryParse(userOpenId, out id)) { try { // Делаем редирект на сайт провайдера OpenID return openIdProvider .CreateRequest(userOpenId) .RedirectingResponse .AsActionResult(); // Расширение для MVC } catch (ProtocolException ex) { ViewData["Message"] = ex.Message; } } else { // Не корректный OpenID клиента ViewData["Message"] = "Invalid identifier"; } return View("Login"); } else { // Ответ с сайта провайдера OpenID switch (response.Status) { // Успешная аутентификация case AuthenticationStatus.Authenticated: { Session["FriendlyIdentifier"] = response.FriendlyIdentifierForDisplay; // Аутентифицированы по cookies. FormsAuthentication.SetAuthCookie(response.ClaimedIdentifier, false); return RedirectToAction("Index", "Home"); } // Аутентификация была отменена пользователем case AuthenticationStatus.Canceled: { ViewData["Message"] = "Canceled at provider"; return View("Login"); } // Аутентификация не удалась из за ошибки. case AuthenticationStatus.Failed: { ViewData["Message"] = response.Exception.Message; return View("Login"); } // При прочих, делаем редирект на главную. default: { return RedirectToAction("Index", "Home"); } } } } } } <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Index </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h1>Этот раздел только для аутентифицированных пользователей</h1> <p>Ваш OpenID подтвержден: <%=Session["FriendlyIdentifier"] %></p> <p> <%=Html.ActionLink("Logout", "logout") %> </p> </asp:Content> <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Login </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <!-- Сообщение об ошибке будем выводить красным --> <% if (ViewData["Message"] != null) { %> <div style="color: red"> <%= Html.Encode(ViewData["Message"].ToString())%> </div> <% } %> <!-- Форма аутентификации, метод POST --> <% using (Html.BeginForm("Authenticate", "User", FormMethod.Post)) { %> <label for="userOpenId">Ваш OpenID:</label><%= Html.TextBox("userOpenId")%> <input type="submit" value="Login" /> <% } %> </asp:Content> using System; using System.Web; using System.Web.Mvc; namespace MainSite.Controllers { public class HomeController : Controller { public ActionResult Index() { // Добавим в заголовок ответа информацию о // расположении XRDS файла Response.AppendHeader ( "X-XRDS-Location", new Uri( Request.Url, Response.ApplyAppPathModifier("~/Home/xrds") ) .AbsoluteUri ); // Главная страница. return View("Index"); } public ActionResult Xrds() { // Отобразим XRDS описание. return View("Xrds"); } } } <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" ContentType="application/xrds+xml" %> <?xml version="1.0" encoding="UTF-8"?> <xrds:XRDS xmlns:xrds="xri://$xrds" xmlns:openid="http://openid.net/xmlns/1.0" xmlns="xri://$xrd*($v*2.0)"> <XRD> <!-- OpenID 2.0 login service --> <Service priority="10"> <Type>http://specs.openid.net/auth/2.0/signon</Type> <URI><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/user/authenticate"))%></URI> </Service> <!-- OpenID 1.0 login service --> <Service priority="20"> <Type>http://openid.net/server/1.0</Type> <URI><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/user/authenticate"))%></URI> </Service> </XRD> </xrds:XRDS> <authentication mode="Forms"> <forms defaultUrl="~/Home" loginUrl="~/User/Login" name="OpenIdAuth"/> </authentication>
Осталось добавить соответствующие представления для Index и Login, так как обработчики Logout и Authenticate не нуждаются в представлении:
и представление Login.aspx:
Теперь добавим XRDS описание нашего приложения, в котором заявим, что поддерживаем OpenID. Для этого изменим Home-контроллер:
И соответственно добавим само описание XRDS в виде Xrds.aspx (Обратите внимание на ContentType):
Не забываем добавить в Web.config строчки:
Если Вы заранее знаете адрес сервера, где будет располагаться Ваше ASP.NET MVC приложение, то можно указывать абсолютные пути и не вызывать лишний раз ApplyAppPathModifier, это позволит снизить нагрузку на сервер.
Шаг четвертый, заключительный. Запускаем тестовое приложение F5.
Щелкаем "Вход"
Вводим OpenID идентификатор и нажимаем "Login"
Нас направят на сайт провайдера, где нужно ввести пароль. Вводим пароль и нажимаем "Вход"
После успешной аутентификации попадаем на закрытую часть сайта.
Вы еще не написали, что с помощью OpenId можно извлекать автоматически nickname, email, дату рождения и др. данные с OpenId провайдера.
ОтветитьУдалить@Ruslan
ОтветитьУдалитьДа, спасибо за замечание. Кстати, имея email пользователя можно воспользоваться сервисом gravatar-ок, для получения аватара для пользователя.
было бы интересно почитать еще про OAuth+MVC
ОтветитьУдалить@ankstoo
ОтветитьУдалитьСпасибо, как выпадет свободная минутка напишу. Следите за обновлениями)
А за чем в примере код связанный с XRDS? Это вроде нужно только если вы хотите сделать свой сайт OpenID-провайдером. То есть для простой авторизации этого не нужно.
ОтветитьУдалитьСпасибо
ОтветитьУдалитьXRDS документ нужен в консъюмере для успешного прохождения Discovery на провайдере. В нем должен храниться return_to параметр, указывающий на адресс по которому расположена Relay Party. Все это по сути нужно, так как в спецификации по OpenID сказано, что провайдер не должен возвращать успешное прохождение аутентефикации, если не удалось провести Discovery. Об этом написано здесь http://blog.nerdbank.net/2008/06/why-yahoo-says-your-openid-site.html
ОтветитьУдалитьи здесь
https://groups.google.com/forum/?fromgroups=#!searchin/dotnetopenid/IsReturnUrlDiscoverable/dotnetopenid/-YCxTS7xaJs/wKUQndt6o44J
Если это кому-то еще интересно.
@SFH
ОтветитьУдалитьСпасибо! Я уверен, что кому-нибудь да и пригодиться.