...

суббота, 16 ноября 2013 г.

[Из песочницы] MVC 5 Owin авторизация на примере Вконтакте

Не так давно вышел mvc 5 и одним из ключевых изменений является система авторизации. При создании «пустого» mvc 5 проекта есть возможность подключить авторизацию для Facebook, Google, Twitter и Microsoft аккаунтов. Я тут же полез разбираться с тем как это все работает и результатом стал «middleware» модуль для сети Вконтакте. Его можно поставить через nuget пакеты поискав «Duke.Owin.VkontakteMiddleware» и посмотреть исходники: github.com/DukeNuken/Duke.Owin.VkontakteMiddleware

В интернете есть много статей о owin авторизации и проекте katana с которыми можно ознакомится и даже скачать исходники.



А сейчас предлагаю в общих чертах обсудить как это все работает. Немного истории. Когда то давно, лет 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 на странице логина. Пример страницы можно увидеть тут, во всех других случаях просто передает управление дальше.


После подтверждения юзер будет переброшен назад на ваш сайт на страницу возврата модуля. Примерно такую '/signin-vkontakte?code=8e40fbe05c7ec232c0' (эта страница возврата задается в параметрах модуля) и в этот момент отрабатывает второй метод метод


2) public override async Task<bool> InvokeAsync() — этот метод дергается на каждой странице до того как отрабатывают контролы и сверяет свою «базовую» линку c запросом. Если они совпадают, то происходит сама авторизация. На примере модуля для вконтакте этот метод по сути ждет линку '/signin-vkontakte' от первого метода.


Внутри метода InvokeAsync дергается страница «oauth.vk.com/access_token» и получает 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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. FiveFilters.org recommends: March Against Mainstream Media (More info).


Комментариев нет:

Отправить комментарий