- PVSM.RU - https://www.pvsm.ru -

MVC 5 Owin авторизация на примере Вконтакте

Не так давно вышел 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), если да то специальным хелпером проверяется должен ли этот модуль делать авторизацию, если да то делается редирект на сайт авторизации и в результате юзер видит такую вот форму:

image

То есть первый метод реально отрабатывает только после того как юзер нажимает на кнопку 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 модуль, который получает управление в начале и в конце запроса.
image

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

image

То есть сама по себе 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/