- PVSM.RU - https://www.pvsm.ru -
Не так давно вышел mvc 5 и одним из ключевых изменений является система авторизации. При создании «пустого» mvc 5 проекта есть возможность подключить авторизацию для Facebook, Google, Twitter и Microsoft аккаунтов. Я тут же полез разбираться с тем как это все работает и результатом стал «middleware» модуль для сети Вконтакте. Его можно поставить через nuget пакеты поискав «Duke.Owin.VkontakteMiddleware» и посмотреть исходники: github.com/DukeNuken/Duke.Owin.VkontakteMiddleware [1]
В интернете есть много статей о owin авторизации [2] и проекте katana с которыми можно ознакомится и даже скачать исходники [3].
А сейчас предлагаю в общих чертах обсудить как это все работает. Немного истории. Когда то давно, лет 6 назад, один мой заказчик просил сделать на сайте красивые ссылки типа "/account/register" и поскольку проект был на asp.net то единственным решением было установление модуля UrlRewriting для IIS и на сайте все работало хорошо, но вот в студии такие линки понятно не открывались, что доставляло некоторые неудобства. С тех пор как Microsoft выпустило mvc логика UrlRewriting осуществляеться на стороне проекта (RouteConfig), точно так же делается на стороне проекта и оптимизация скриптов (BundleConfig). Это позволяет корректно работать проекту все зависимости от сервера. По такому же принципу в mvc 5 добавилась авторизация.
Класс Startup находится в проекте /App_Start и в нем есть всего одна функция ConfigureAuth(IAppBuilder app). Она дергается при старте проекта и подгружает так называемые middleware модули. Что это такое и как они работают? По сути это классы которые наследуются от AuthenticationMiddleware. В этом классе есть конструктор и метод CreateHandler(). Этот метод вызывается при каждом обращении к странице и все что он должен сделать это создать AuthenticationHandler который, в свою очередь, имеет 2 метода. Рассмотрим их подробнее
1) protected override Task ApplyResponseChallengeAsync() — этот метод вызывается после отработки логики в контролах и перед отправкой response к пользователю. Он делает 3 важных шага. Проверяет код http ответа — равен ли 401 (not autorized), если да то специальным хелпером проверяется должен ли этот модуль делать авторизацию, если да то делается редирект на сайт авторизации и в результате юзер видит такую вот форму:

То есть первый метод реально отрабатывает только после того как юзер нажимает на кнопку Vknotakte на странице логина. Пример страницы можно увидеть тут [4], во всех других случаях просто передает управление дальше.
После подтверждения юзер будет переброшен назад на ваш сайт на страницу возврата модуля. Примерно такую '/signin-vkontakte?code=8e40fbe05c7ec232c0' (эта страница возврата задается в параметрах модуля) и в этот момент отрабатывает второй метод метод
2) public override async Task<bool> InvokeAsync() — этот метод дергается на каждой странице до того как отрабатывают контролы и сверяет свою «базовую» линку c запросом. Если они совпадают, то происходит сама авторизация. На примере модуля для вконтакте этот метод по сути ждет линку '/signin-vkontakte' от первого метода.
Внутри метода InvokeAsync дергается страница «oauth.vk.com/access_token [5]» и получает token, после этого происходит обращение к Vkontakte API и получение информации о пользователе — имя и id. На основании этих данных создается AuthenticationTicket. В свою очередь AuthenticationTicket используется для создания ReturnEndpointContext объекта и сохранение информации через Microsoft.Owin.Security.AuthenticationManager. После этого пользователь перебрасывается на /Account/ExternalLoginCallback и может завершить регистрацию указав под каким именем он хочет зарегистрироваться на сайте.
1) Поведение «middleware» модуля очень похоже на обычный http модуль, который получает управление в начале и в конце запроса.

2) Казалось бы, есть два типа регистрации — регистрация на сайте и регистрация через owin модули, но в конечном итоге когда после авторизации на Вконтакте пользователь будет возвращен на страницу сайта "/Account/ExternalLoginCallback" (на странице будет сообщение что он Вконтакт авторизацию прошел успешно, текстовое поле для указания имени и кнопка Register), то только тут при нажатии на Register будет создан обычный аккаунт и в нем будет указано что он относится к «Vkontakte» провайдеру и в качестве параметра там будет userid. В базе это выглядит так

То есть сама по себе owin авторизация на сайте ничего не делает, а только предоставляет информацию для обычной регистрации.
Спасибо за внимание.
Живой пример тут freemusiclib.com/Account/Login [4]
Автор: DukeNuken
Источник [6]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/news/48477
Ссылки в тексте:
[1] github.com/DukeNuken/Duke.Owin.VkontakteMiddleware: https://github.com/DukeNuken/Duke.Owin.VkontakteMiddleware
[2] owin авторизации: http://blogs.msdn.com/b/webdev/archive/2013/07/03/understanding-owin-forms-authentication-in-mvc-5.aspx
[3] исходники: http://katanaproject.codeplex.com/SourceControl/latest#README
[4] тут: http://freemusiclib.com/Account/Login
[5] oauth.vk.com/access_token: https://oauth.vk.com/access_token
[6] Источник: http://habrahabr.ru/post/202344/
Нажмите здесь для печати.