вход по коду в core
Вход по коду в core
Коротко: перейдите по ссылке, которую прислал учитель. Если учитель прислал код, то зайдите на сайт urok.io и введите код в специальное окно.
Дальше введите свои данные в окне авторизации (они должны быть полными и верными, иначе учитель не сможет опознать вас) и вуаля, урок открыт!
Если учитель прислал ссылку на урок (например, такую: https://coreapp.ai/app/player/lesson/5e778344bd6ed9bbdb651a2e/2), скопируйте и вставьте ее в адресную строку браузера.
В случае, если учитель прислал код урока (например, такой: OEUV), введите в адресную строку браузера адрес «urok.io». Откроется страница с полем для ввода текста, в которое нужно ввести код урока, который вы получили и нажать на кнопку «Перейти в урок».
Далее вы попадете в окно авторизации. Пройти его нужно обязательно, иначе учитель не сможет узнать, кто проходил урок. Более того, нужно обязательно записать не только имя, но и фамилию. Ведь если урок пройдет несколько «тезок», то учитель не сможет понять, кто есть кто.
Если регистрация на платформе CORE уже есть, то выберете «Войти со своим аккаунтом», укажите свой e-mail и пароль. Дальше нажмите на кнопку «Войти».
Если до этого на платформе не регистрировались, но решили это сделать, выберете «Создать аккаунт и войти».
Здесь нужно будет указать свой e-mail, придумать пароль, ввести свою фамилию и имя. Ознакомьтесь с пользовательским соглашением и кликнете на кнопку «Зарегистрироваться и войти». Для того чтобы подтвердить почту, нужно будет зайти в свой почтовый ящик. Там будет ждать письмо с инструкциями.
Если аккаунта на платформе CORE нет, но он и не нужен — не беда, выберете «Войти без регистрации». Здесь понадобится ввести свое имя и фамилию (обязательно записываем правильно!). Дальше нажимаем на кнопку «Начать урок».
Однако мы рекомендуем проходить регистрацию. Ведь если есть аккаунт, то все уроки, которые будет посылать учитель, сохранятся в личном кабинете. А если нет аккаунта, то и личного кабинета тоже нет!
Вход по коду в core
Кратко: чтобы зайти в личный кабинет ученика, вам необходимо зарегистрироваться в CORE.
Автоматически вы попадете в личный кабинет учителя. Для того, чтобы попасть в кабинет ученика в правом верхнем углу экрана нажмите на значок с вашим именем. В выпавшем списке выберите «Режим «Учусь»».
В личном кабинете сохраняются все уроки/курсы, которые вы проходите или уже прошли. Вы можете открыть их, чтобы пройти повторно, или же чтобы посмотреть ваши результаты и комментарии учителя.
После авторизации мы попадаем в личный кабинет. Каждый пользователь CORE имеет два кабинета:
Как понять, в каком кабинете вы находитесь? Посмотрите на окошко в правом верхнем углу. Под вашим именем будет написан статус – «Обучаю» или «Учусь». Если вы в личном кабинете учителя, кликните на окошко и в выпавшем списке выберите «Режим «Учусь»».
Хотите изменить имя или фамилию, указанные при регистрации?
Кликните на вкладку «Личный кабинет», а затем в центре экрана выберите
вкладку «Профиль и безопасность».
Хотите подключить номер телефона к аккаунту CORE?
Нажмите на вкладку «Личный кабинет», а затем выберите вкладку «Профиль и безопасность».
Рядом с пунктом «номер телефона» нажмите «изменить», введите номер мобильного телефона. Далее — нажмите «сохранить».Если номер необходимо изменить, повторите действия, указав корректный номер телефона.
Итак, мы находимся в личном кабинете ученика. Не стоит бояться что-то случайно удалить: перед удалением система обязательно запросит у вас подтверждение.
На панели сверху мы видим две основные вкладки:
Все уроки, которые вы проходите, представлены в виде прямоугольных карточек. Справа название урока, слева дата вашего последнего прохождения и статусы.
Если вы не закончили урок, то увидите кнопку «Продолжить прохождение».
Кликните на неё, чтобы продолжить проходить урок. Кнопка «Продолжить прохождение» будет отображаться до тех пор, пока вы не нажмете внутри урока на кнопку «Завершить урок».
Если урок завершен, то на карточке будут отображены две кнопки:
Авторизация в ASP.NET Core MVC
В статье описаны паттерны и приемы авторизации в ASP.NET Core MVC. Подчеркну, что рассматривается только авторизация (проверка прав пользователя) а не аутентификация, поэтому в статье не будет использования ASP.NET Identity, протоколов аутентификации и т.п. Будет много примеров серверного кода, небольшой экскурс вглубь исходников Core MVC, и тестовый проект (ссылка в конце статьи). Приглашаю интересующихся под кат.
Claims
Принципы авторизации и аутентификации в ASP.NET Core MVC не изменились по сравнению с предыдущей версией фреймворка, отличаясь лишь в деталях. Одним из относительно новых понятий является claim-based авторизация, с нее мы и начнем наше путешествие. Что же такое claim? Это пара строк «ключ-значение», в качестве ключа может выступать «FirstName», «EmailAddress» и т.п. Таким образом, claim можно трактовать как свойство пользователя, как строку с данными, или даже как некоторое утверждение вида «у пользователя есть что-то«. Знакомая многим разработчикам одномерная role-based модель органично содержится в многомерной claim-based модели: роль (утверждение вида «у пользователя есть роль X«) представляет собой один из claim и содержится в списке преопределенных System.Security.Claims.ClaimTypes. Не возбраняется создавать и свои claim.
Следующее важное понятие — identity. Это единое утверждение, содержащее набор claim. Так, identity можно трактовать как цельный документ (паспорт, водительские права и др.), в этом случае claim — строка в паспорте (дата рождения, фамилия. ). В Core MVC используется класс System.Security.Claims.ClaimsIdentity.
Еще на уровень выше находится понятие principal, обозначающее самого пользователя. Как в реальной жизни у человека может быть на руках несколько документов одновременно, так и в Core MVC — principal может содержать несколько ассоциированных с пользователем identity. Всем известное свойство HttpContext.User в Core MVC имеет тип System.Security.Claims.ClaimsPrincipal. Естественно, через principal можно получить все claim каждого identity. Набор из более чем одного identity может использоваться для разграничения доступа к различным разделам сайта/сервиса.
На диаграмме указаны лишь некоторые свойства и методы классов из пространства имен System.Security.Claims.
Зачем это все нужно? При claim-based авторизации, мы явно указываем, что пользователю необходимо иметь нужный claim (свойство пользователя) для доступа к ресурсу. В простейшем случае, проверяется сам факт наличия определенного claim, хотя возможны и куда более сложные комбинации (задаваемые при помощи policy, requirements, permissions — мы подробно рассмотрим эти понятия ниже). Пример из реальной жизни: для управления легковым авто, у человека должны быть водительские права (identity) с открытой категорией B (claim).
Подготовительные работы
Здесь и далее на протяжении статьи, мы будем настраивать доступ для различных страниц веб-сайта. Для запуска представленного кода, достаточно создать в Visual Studio 2015 новое приложение типа «ASP.NET Core Web Application», задать шаблон Web Application и тип аутентификации «No Authentication».
При использовании аутентификации «Individual User Accounts» был бы сгенерирован код для хранения и загрузки пользователей в БД посредством ASP.NET Identity, EF Core и localdb. Что является совершенно избыточным в рамках данной статьи, даже несмотря на наличие легковесного EntityFrameworkCore.InMemory решения для тестирования. Более того, нам в принципе не потребуется библиотека аутентификации ASP.NET Identity. Получение principal для авторизации можно самостоятельно эмулировать in-memory, а сериализация principal в cookie возможна стандартными средствами Core MVC. Это всё, что нужно для нашего тестирования.
Для эмуляции хранилища пользователей достаточно открыть Startup.cs и зарегистрировать сервисы-заглушки во встроенном DI-контейнере:
Кстати, мы всего лишь проделали ту же работу, что проделал бы вызов AddEntityFrameworkStores :
Начнем с авторизации пользователя на сайте: на GET /Home/Login нарисуем форму-заглушку, добавим кнопку для отправки пустой формы на сервер. На POST /Home/Login вручную создадим principal, identity и claim (в реальном приложении эти данные были бы получены из БД). Вызов HttpContext.Authentication.SignInAsync сериализует principal и поместит его в зашифрованный cookie, который в свою очередь будет прикреплен к ответу веб-сервера и сохранен на стороне клиента:
Включим cookie-аутентификацию в методе Startup.Configure(app):
Этот код с небольшими модификациями будет основой для всех последующих примеров.
Атрибут Authorize и политики доступа
Атрибут [Authorize] никуда не делся из MVC. По-прежнему, при маркировке controller/action этим атрибутом — доступ внутрь получит только авторизованный пользователь. Вещи становятся интереснее, если дополнительно указать название политики (policy) — некоторого требования к claim пользователя:
Политики создаются в уже известном нам методе Startup.ConfigureServices :
Такая политика устанавливает, что попасть на страницу About сможет только авторизованный пользователь с claim-ом «age», при этом значение claim не учитывается. В следующем разделе, мы перейдем к примерам посложнее (наконец-то!), а сейчас разберемся, как это работает внутри?
[Authorize] — атрибут маркерный, сам по себе логики не содержащий. Нужен он лишь для того, чтобы указать MVC, к каким controller/action следует подключить AuthorizeFilter — один из встроенных фильтров Core MVC. Концепция фильтров та же, что и в предыдущих версиях фреймворка: фильтры выполняются последовательно, и позволяют выполнить код до и после обращения к controller/action. Важное отличие от middleware: фильтры имеют доступ к специфичному для MVC контексту (и выполняются, естественно, после всех middleware). Впрочем, грань между filter и middleware весьма расплывчата, так как вызов middleware возможно встроить в цепочку фильтров при помощи атрибута [MiddlewareFilter].
Вернемся к авторизации и AuthorizeFilter. Самое интересное происходит в его методе OnAuthorizationAsync:
Надеюсь, приведенные ссылки на исходный код дали вам представление об внутреннем устройстве фильтров в Core MVC.
Настройки политик доступа
Requirement — не более чем DTO для передачи параметров в соответствующий handler, который в свою очередь имеет доступ к HttpContext.User и волен налагать любые проверки на principal и содержащиеся в нем identity/claim. Более того, handler может получать внешние зависимости через встроенный в Core MVC DI-контейнер:
Регистрируем сам handler в Startup.ConfigureServices(), и он готов к использованию:
Resource-based авторизация
Как уже говорилось ранее, policy-based авторизация выполняется Core MVC в filter pipeline, т.е. ДО вызова защищаемого action. Успех авторизации при этом зависит только от пользователя — либо он обладает нужными claim, либо нет. А что, если необходимо учесть также защищаемый ресурс и его свойства, получить какие данные из внешних источников? Пример из жизни: защищаем action вида GET /Orders/
Затем создадим новую политику и handler:
Наконец, проверяем пользователя + ресурс на соответствие нужной политике внутри action (заметьте, атрибут [Authorize] больше не нужен):
У метода IAuthorizationService.AuthorizeAsync есть перегрузка, принимающая список из requirement — вместо названия политики:
Что позволяет еще более гибко настраивать права доступа. Для демонстрации, используем преопределенный OperationAuthorizationRequirement (да, этот пример перекочевал в статью прямо с docs.microsoft.com):
что позволит вытворять следующие вещи:
В методе HandleRequirementAsync(context, requirement, resource) соответствующего handler — нужно лишь проверить права соответственно операции, указанной в requirement.Name и не забыть вызвать context.Fail() если пользователь провалил авторизацию:
Handler будет вызван столько раз, сколько requirement вы передали в AuthorizeAsync и проверит каждый requirement по-отдельности. Для единовременной проверки всех прав на операции за один вызов handler — передавайте список операций внутри requirement, например так:
На этом обзор возможностей resource-based авторизации закончен, и самое время покрыть наши handler-ы тестами:
Авторизация в Razor-разметке
Выполняемая непосредственно в разметке проверка прав пользователя может быть полезна для скрытия элементов UI, к которым пользователь не должен иметь доступ. Конечно же, во view можно передать все необходимые флаги через ViewModel (при прочих равных я за этот вариант), либо обратиться напрямую к principal через HttpContext.User:
С другой стороны, мы можем использовать подход из предыдущего раздела: получить реализацию IAuthorizationService через DI (да, прямо во view) и проверить пользователя на соответствие требованиям нужной политики:
Permission-based авторизация. Свой фильтр авторизации
Декларативное перечисление всех запрашиваемых операций (в первую очередь из числа CRUD) при авторизации пользователя, такое как:
… имеет смысл, если в вашем проекте построена система персональных разрешений (permissions): имеется некий набор из большого числа высокоуровневых операций бизнес-логики, есть пользователи (либо группы пользователей), которым были в ручном режиме выданы права на конкретные операции с конкретным ресурсом. К примеру, у Васи есть права «драить палубу», «спать в кубрике», а Петя может «крутить штурвал». Хорош или плох такой паттерн — тема для отдельной статьи (лично я от него не в восторге). Очевидная проблема данного подхода: список операций легко разрастается до нескольких сотен даже не в самой большой системе.
Ситуация упрощается, если для авторизации нет нужды учитывать конкретный экземпляр защищаемого ресурса, и наша система обладает достаточной гранулярностью, чтобы просто навесить на весь метод атрибут со списком проверяемых операций, вместо сотен вызовов AuthorizeAsync в защищаемом коде. Однако, использование авторизации на основе политик [Authorize(Policy = «foo-policy»)] приведет к комбинаторному взрыву числа политик в приложении. Почему бы не использовать старую добрую role-based авторизацию? В примере кода ниже, пользователю необходимо быть членом всех указанных ролей для получения доступа к FooController:
Начнем с создания enum для операций, requirement и handler для проверки пользователя:
К счастью, в Core MVC эти проблемы легко разрешимы при помощи атрибута [TypeFilter]:
Мы получили полностью работающее, но безобразно выглядящее решение. Для того, чтобы скрыть детали реализации нашего фильтра от вызывающего кода, нам и пригодится атрибут [AuthorizePermission] :
Дополнительные материалы для чтения по теме (также приветствуются ваши ссылки для включения в список):
Вход по коду в core
Перейдите по ссылке, которую прислал учитель. Если учитель прислал код, то зайдите на сайт urok.io и введите код в специальное окно.
Затем введите свои данные в окно авторизации (они должны быть полными и верными, иначе учитель не сможет опознать вас) и вуаля, урок открыт!
Открыв урок, вы увидите карточку(-и). Это и есть содержание урока. Чтобы открыть карточку, просто кликните по ней.
Внутри карточек вы найдете материал, который подготовил для вас учитель: образовательный материал и тесты.
Нажимая на кнопку «Следующая страница», вы перейдете к следующей карточке, не возвращаясь в содержание.
Чтобы вернуться к выбору карточек, нажмите на кнопку «Вернуться в содержание».
После того, как закончите урок, обязательно нажмите на «Завершить урок».
Ученик может отслеживать статус проверки домашнего задания в центре уведомлений. Для этого зайдите в личный кабинет ученика и кликните на колокольчик в верхней панели управления. В центре уведомлений ученик может видеть все действия учителя. Ученик может нажать кнопку «Смотреть сводку», расположенной на карточке с названием урока, и увидеть ответы учителя.
Кликнув на комментарий от преподавателя, ученик откроет диалоговое окно. Если преподаватель не принял ответ, то ученик сможет повторно прислать домашнее задание.
Войдите в курс по ссылке, если он общедоступный, или по приглашению на почте, если курс закрытый. Если у вас нет аккаунта на CORE — создайте его. Все курсы будут храниться в личном кабинете во вкладке «Курсы». Внутри курса вы найдете список уроков. Для того, чтобы открыть их — кликните по ним. Для того чтобы посмотреть результаты (в том числе обратную связь от учителя), кликните на кнопку «К результатам». Она расположена в карточке с названием урока. Для того чтобы кнопка отобразилась, просто наведите курсор на нужный урок.
Обратите внимание, что если урок является контрольной работой, то последующие уроки в курсе будут заблокированы, пока вы не решите верно минимум 80% заданий из контрольной.
© ООО «Цифровая жажда» 2021
Путь ASP.NET Core [уровень 1] Основы
ASP.NET Core — новейший фреймворк для кроссплатформенной веб разработки. Пока его популярность (как и количество вакансий) только начинает набирать обороты самое время узнать о нем побольше. Ну а для того, чтобы все знания не испарились сразу после прочтения — добавим существенную практическую часть. Создадим простое приложение, для тестирования прочитанного.
Если вы считаете, что уже достаточно круты в новом фреймворке — можете попробовать пройти тест до того, как прочтете статью. Линк. Весь код проекта можно посмотреть на гитхабе.
Первая часть включает:
В чем же тогда особенности и отличия ASP.NET Core от предыдущего ASP.NET? Некоторые из них это:
Класс Statup можно, в какой-то степени, охарактеризовать как новый вариант Global.asax (Это класс для глобальной настройки всего приложения в предыдущей версии ASP.NET). Грубо говоря, можно сказать, что метод ConfigureServices нужен для конфигурации контейнера для внедрения зависимостей и его сервисов, а метод Configure для конфигурации конвейера обработки запросов.
Приступим к практической реализации
Чтобы облегчить себе жизнь, выберем Web Application и поменяем аутентификацию на Individual User Accounts. Таким образом Visual Studio уже сгенерирует весь нужный код для базового приложения.
Рассмотрим детальней что же нового появилось в ASP.NET Core. С точки зрения разработки вся концепция осталась прежней. Структура проекта базируется на паттерне MVC. Для работы с данными по умолчанию используем Entity Framework, логика описана в классах-контроллерах, на уровне представлений используем синтаксис cshtml + новая фишка tag helpers.
Проверим классы Program.cs и Startup.cs, они действительно выглядят такими же, как было описано выше. Конечно класс Startup не совсем пуст, а уже вмещает функционал для считывания конфигурации, настройки базового логирования, маршрутизации и привязку на нашу модель базы данных.
Дополним модель базы данных сущностями для создания и прохождения тестов. Будем использовать следующие сущности: Набор тестовых вопросов — TestPackage, Сам вопрос (тест) — TestItem, Результат теста — TestResult. Пример можно посмотреть тут. Радует, что EntityFramework Core уже поддерживает большинство функционала и можно полноценно пользоваться Code First миграциями.
Добавляем логику
Теперь, когда у нас есть модель базы данных, мы можем приступить к созданию логики для нашего приложения. Самый простой способ создания админки — это механизм scaffolding. Для этого, кликаем правой кнопкой мыши по папке контроллеров и выбираем Add → New Scaffold Item:
Выбираем «MVC Controller с представлениями, с использованием Entity Framework». Этот шаблон позволяет нам быстро создать контроллер и вьюхи для управления одной конкретной моделью. Проделаем такой трюк для TestPackage и TestItem. В результате у нас есть готовый прототип админки для нашей системы. Можно запустить проект и зайти на страницы этих контроллеров, просто добавить его имя без слова Controller в конец адреса, например, /testpackages. Конечно в ней еще не все идеально, поэтому нужно допилить некоторые моменты и сделать их более удобными.
После создания модели и простого функционала для работы с ней, можно перейти к самому процессу прохождения тестов. В общем, все выглядит просто. Сервер присылает вопрос, варианты, мы отсылаем назад ответ. Сервер сохраняет его. В конце теста показываем результат. Добавим код для этого поведения.
В общем, все что нужно для теста у нас есть.
Основы Dependency Injection в ASP.NET Core
Важным новшеством новой версии ASP.NET так же является встроенный механизм внедрения зависимостей. В 2016 году уже никого не удивишь тем, что механизм внедрения зависимостей можно перенести внутрь фреймворка. Мало какое серьёзное приложение пишут без использование этого подхода. DI в ASP.NET Core реализован достаточно базово, но в то же время позволяет решить большинство задач управления зависимостями.
Конфигурация контейнера осуществляется в методе ConfigureServices класса Startup. Пример:
Можно заметить, что для контекста базы данных и Identity фреймворка есть дополнительные, не типичные методы их регистрации. Это позволяет более гибко их сконфигурировать. В этот подход регистрации сервисов очень красиво вписываются extension-методы.
После регистрации сервисов, самый легкий способ получить из в коде (например, в контроллерах) — это просто добавить параметр конструктора типа, который был зарегистрирован. Такие контроллеры по умолчанию создаются скаффолдингом.
Деплой
Одним из самых простых способов деплоймента остается Microsoft Azure. Нам достаточно самых базовых настроек для полноценной работы. Развертывание сайта на сервере все так же просто — с помощью нескольких кликов, начиная с контекстного меню на файле проекта.