Поделиться через


Авторизация на основе пользователей (C#)

Скотт Митчелл

Примечание.

Так как эта статья была написана, поставщики членства ASP.NET были заменены ASP.NET Identity. Мы настоятельно рекомендуем обновить приложения для использования платформы ASP.NET Identity , а не поставщиков членства, которые были представлены в то время, когда эта статья была написана. ASP.NET Identity имеет ряд преимуществ по сравнению с системой членства ASP.NET, в том числе:

  • Повышенная производительность
  • Улучшенная расширяемость и возможность тестирования
  • Поддержка OAuth, OpenID Connect и двухфакторной проверки подлинности
  • Поддержка удостоверений на основе утверждений
  • Улучшение взаимодействия с ASP.Net Core

Скачивание кода или скачивание PDF

В этом руководстве мы рассмотрим ограничение доступа к страницам и ограничение функциональных возможностей на уровне страниц с помощью различных методов.

Введение

Большинство веб-приложений, предлагающих учетные записи пользователей, частично ограничивают доступ некоторых посетителей к определенным страницам на сайте. Например, на большинстве веб-сайтов доски сообщений все пользователи — анонимные и прошедшие проверку подлинности — могут просматривать записи доски сообщений, но только прошедшие проверку подлинности пользователи могут посетить веб-страницу, чтобы создать новую запись. Кроме того, могут быть административные страницы, доступные только конкретному пользователю (или определенному набору пользователей). Кроме того, функциональные возможности уровня страницы могут отличаться на основе пользователей. При просмотре списка записей пользователи, прошедшие проверку подлинности, отображаются интерфейс для оценки каждой записи, в то время как этот интерфейс недоступен анонимным посетителям.

ASP.NET упрощает определение правил авторизации на основе пользователей. С помощью просто немного разметки в Web.configопределенных веб-страницах или целых каталогах можно заблокировать, чтобы они были доступны только для указанного подмножества пользователей. Функции уровня страницы можно включить или отключить на основе текущего входа пользователя с помощью программных и декларативных средств.

В этом руководстве мы рассмотрим ограничение доступа к страницам и ограничение функциональных возможностей на уровне страниц с помощью различных методов. Приступим.

Просмотр рабочего процесса авторизации URL-адресов

Как описано в руководстве по обзору проверки подлинности форм, когда среда выполнения ASP.NET обрабатывает запрос на ASP.NET ресурс, запрос вызывает ряд событий во время жизненного цикла. Модули HTTP — это управляемые классы , код которых выполняется в ответ на определенное событие в жизненном цикле запроса. ASP.NET поставляется с рядом модулей HTTP, выполняющих основные задачи за кулисами.

Одним из таких модулей HTTP является FormsAuthenticationModule. Как описано в предыдущих руководствах, основная функция FormsAuthenticationModule этого запроса — определить удостоверение текущего запроса. Это достигается путем проверки билета проверки подлинности форм, который находится в файле cookie или внедрен в URL-адрес. Эта идентификация происходит во время AuthenticateRequest события.

Другим важным модулем HTTP является UrlAuthorizationModule, который вызывается в ответ на AuthorizeRequest событие (которое происходит после AuthenticateRequest события). Проверяет UrlAuthorizationModule разметку конфигурации, Web.config чтобы определить, имеет ли текущее удостоверение центр для посещения указанной страницы. Этот процесс называется авторизацией URL-адреса.

Мы рассмотрим синтаксис правил авторизации URL-адресов на шаге 1, но сначала рассмотрим, что UrlAuthorizationModule делает в зависимости от того, авторизован ли запрос или нет. Если запрос UrlAuthorizationModule определен, что запрос авторизован, он ничего не делает, и запрос продолжается через свой жизненный цикл. Однако если запрос не авторизован, то UrlAuthorizationModule прерывает Response жизненный цикл и указывает объекту вернуть состояние HTTP 401 Unauthorized. При использовании проверки подлинности форм этот статус HTTP 401 никогда не возвращается клиенту, так как при FormsAuthenticationModule обнаружении состояния HTTP 401 он изменяет его на HTTP 302 Перенаправление на страницу входа.

Рис. 1 иллюстрирует рабочий процесс конвейера ASP.NET, FormsAuthenticationModuleа также UrlAuthorizationModule время поступления несанкционированного запроса. В частности, на рис. 1 показан запрос анонимного посетителя ProtectedPage.aspx, который является страницей, которая запрещает доступ к анонимным пользователям. Так как посетитель является анонимным, UrlAuthorizationModule он прерывает запрос и возвращает состояние HTTP 401 Unauthorized. Затем он FormsAuthenticationModule преобразует состояние 401 в страницу входа в 302 перенаправление. После проверки подлинности пользователя с помощью страницы входа он перенаправляется в ProtectedPage.aspx. На этот раз FormsAuthenticationModule пользователь определяет пользователя на основе его билета проверки подлинности. Теперь, когда посетитель прошел проверку подлинности, UrlAuthorizationModule разрешение на доступ к странице.

Рабочий процесс проверки подлинности форм и авторизации URL-адресов

Рис. 1. Рабочий процесс проверки подлинности форм и авторизации URL-адресов (щелкните, чтобы просмотреть изображение полного размера)

На рисунке 1 показано взаимодействие, которое происходит, когда анонимный посетитель пытается получить доступ к ресурсу, который недоступен анонимным пользователям. В таком случае анонимный посетитель перенаправляется на страницу входа со страницей, на который она попыталась посетить страницу, указанную в запросе. После успешного входа в систему пользователь автоматически перенаправляется обратно в ресурс, который изначально пытается просмотреть.

Когда несанкционированный запрос выполняется анонимным пользователем, этот рабочий процесс прост и легко понять, что произошло и почему. Но помните, что FormsAuthenticationModule пользователь перенаправит любого несанкционированного пользователя на страницу входа, даже если запрос выполняется прошедшим проверку подлинности пользователем. Это может привести к запутанности взаимодействия с пользователем, если прошедший проверку подлинности пользователь пытается посетить страницу, для которой она не имеет полномочий.

Представьте, что у нашего веб-сайта настроены правила авторизации URL-адреса, чтобы страница OnlyTito.aspx ASP.NET была доступна только к Tito. Теперь представьте, что Сэм посещает сайт, входит в систему, а затем пытается посетить OnlyTito.aspx. Будет UrlAuthorizationModule остановлен жизненный цикл запроса и возвращается состояние HTTP 401 Unauthorized, которое FormsAuthenticationModule обнаружит и перенаправит Sam на страницу входа. Так как Сэм уже вошел в систему, однако, она может задаться вопросом, почему она была отправлена обратно на страницу входа. По ее причине ее учетные данные входа были потеряны каким-либо образом или что она ввела недопустимые учетные данные. Если Сэм повторно отправляет свои учетные данные с страницы входа, она будет входить в систему (снова) и перенаправляться на OnlyTito.aspx. Будет UrlAuthorizationModule обнаружено, что Сэм не может посетить эту страницу, и она будет возвращена на страницу входа.

На рисунке 2 показан этот запутанный рабочий процесс.

Рабочий процесс по умолчанию может привести к запутанному циклу

Рис. 2. Рабочий процесс по умолчанию может привести к запутанному циклу (щелкните, чтобы просмотреть изображение полного размера)

Рабочий процесс, иллюстрированный на рис. 2, может быстро быть перенаправлен даже самым опытным посетителем компьютера. Мы рассмотрим способы предотвращения этого запутанного цикла на шаге 2.

Примечание.

ASP.NET использует два механизма, чтобы определить, может ли текущий пользователь получить доступ к определенной веб-странице: авторизация URL-адреса и авторизация файлов. Авторизация файла реализуется центром управления доступом FileAuthorizationModule, который определяет центр, консультируя запрошенные списки управления доступом к файлам. Авторизация файлов чаще всего используется с проверка подлинности Windows, так как списки управления доступом являются разрешениями, применяемыми к учетным записям Windows. При использовании проверки подлинности форм все запросы на уровне операционной системы и файловой системы выполняются одной учетной записью Windows независимо от пользователя, посещающего сайт. Так как в этом руководстве основное внимание уделяется проверке подлинности форм, мы не будем обсуждать авторизацию файлов.

Область авторизации URL-адреса

Управляемый UrlAuthorizationModule код, который является частью среды выполнения ASP.NET. До версии 7 веб-сервера службы IIS (IIS) корпорации Майкрософт существовал отдельный барьер между конвейером HTTP IIS и конвейером среды выполнения ASP.NET. Короче говоря, в IIS 6 и более ранних версиях ASP. UrlAuthorizationModule NET выполняется только при делегировании запроса из IIS в среду выполнения ASP.NET. По умолчанию IIS обрабатывает статическое содержимое, например HTML-страницы и CSS, JavaScript и файлы изображений, а также только передает запросы к среде выполнения ASP.NET при запросе страницы с расширением .aspxили .asmx.ashx запрашивается.

Однако IIS 7 позволяет интегрировать службы IIS и ASP.NET конвейеры. С помощью нескольких параметров конфигурации можно настроить IIS 7 для вызова UrlAuthorizationModule всех запросов, что означает, что правила авторизации URL-адресов можно определить для файлов любого типа. Кроме того, IIS 7 включает собственный механизм авторизации URL-адресов. Дополнительные сведения об интеграции ASP.NET и функциях авторизации URL-адресов IIS 7 см. в разделе "Общие сведения о авторизации URL-адресов IIS7". Для более подробного изучения интеграции ASP.NET и IIS 7, выберите копию книги Шахрам Хосрави, профессиональный IIS 7 и ASP.NET интегрированное программирование (ISBN: 978-0470152539).

В двух версиях до IIS 7 правила авторизации URL-адресов применяются только к ресурсам, обрабатываемых средой выполнения ASP.NET. Но с IIS 7 можно использовать собственную функцию авторизации URL-адресов IIS или интегрировать ASP. UrlAuthorizationModule NET в конвейер HTTP IIS, тем самым расширяя эту функцию для всех запросов.

Примечание.

Существуют некоторые тонкие, но важные различия в том, как ASP. UrlAuthorizationModule Функция авторизации URL-адресов NET и IIS 7 обрабатывают правила авторизации. В этом руководстве не рассматриваются функции авторизации URL-адресов IIS 7 или различия в анализе правил авторизации по сравнению с этим UrlAuthorizationModule. Дополнительные сведения об этих разделах см. в документации ПО IIS 7 в MSDN или www.iis.net.

Шаг 1. Определение правил авторизации URL-адресов вWeb.config

Определяет UrlAuthorizationModule , следует ли предоставлять или запрещать доступ к запрошенному ресурсу для определенного удостоверения на основе правил авторизации URL-адресов, определенных в конфигурации приложения. Правила авторизации определяются в элементе в <authorization> виде и <deny> дочерних <allow> элементов. Каждый <allow> и <deny> дочерний элемент могут указывать:

  • Конкретный пользователь
  • Список пользователей с разделителями-запятыми
  • Все анонимные пользователи, обозначаемые вопросительным знаком (?)
  • Все пользователи, обозначаемые звездочкой (*)

В следующей разметке показано, как использовать правила авторизации URL-адресов, чтобы разрешить пользователям Tito и Scott и запретить все остальные:

<authorization>
 <allow users="Tito, Scott" />
 <deny users="*" />
</authorization>

Элемент <allow> определяет, какие пользователи разрешены — Tito и Scott, а <deny> элемент указывает, что все пользователи запрещены.

Примечание.

<deny> Элементы <allow> также могут указывать правила авторизации для ролей. В будущем мы рассмотрим авторизацию на основе ролей.

Следующий параметр предоставляет доступ любому, кроме Сэма (включая анонимных посетителей):

<authorization>
 <deny users="Sam" />
</authorization>

Чтобы разрешить только прошедших проверку подлинности пользователей, используйте следующую конфигурацию, которая запрещает доступ ко всем анонимным пользователям:

<authorization>
 <deny users="?" />
</authorization>

Правила авторизации определяются в <system.web> элементе и Web.config применяются ко всем ресурсам ASP.NET в веб-приложении. Часто приложение имеет разные правила авторизации для разных разделов. Например, на сайте электронной коммерции все посетители могут использовать продукты, просматривать отзывы о продуктах, искать каталог и т. д. Однако только прошедшие проверку подлинности пользователи могут получить доступ к кассе или страницам для управления журналом доставки. Кроме того, могут быть части сайта, доступные только для пользователей, таких как администраторы сайта.

ASP.NET упрощает определение различных правил авторизации для разных файлов и папок на сайте. Правила авторизации, указанные в файле корневой папки Web.config , применяются ко всем ASP.NET ресурсам сайта. Однако эти параметры авторизации по умолчанию можно переопределить для определенной <authorization> папки, добавив разделWeb.config.

Давайте обновим наш веб-сайт, чтобы только прошедшие проверку подлинности пользователи могли посетить страницы ASP.NET в папке Membership . Для этого необходимо добавить Web.config файл в Membership папку и задать параметры авторизации, чтобы запретить анонимным пользователям. Щелкните правой кнопкой мыши Membership папку в Обозреватель решений, выберите меню "Добавить новый элемент" в контекстном меню и добавьте новый файл веб-конфигурации с именемWeb.config.

Добавление файла web.config в папку членства

Рис. 3. Добавление Web.config файла в папку Membership (щелкните, чтобы просмотреть изображение полного размера)

На этом этапе проект должен содержать два Web.config файла: один в корневом каталоге и один в папке Membership .

Теперь приложение должно содержать два файла конфигурации Web.config

Рис. 4. Теперь приложение должно содержать два Web.config файла (щелкните, чтобы просмотреть изображение полного размера)

Обновите файл конфигурации в папке Membership , чтобы запретить доступ к анонимным пользователям.

<?xml version="1.0"?>
<configuration>
 <system.web>
 <authorization>
 <deny users="?" />
 </authorization>
 </system.web>
</configuration>

Это все.

Чтобы проверить это изменение, посетите домашнюю страницу в браузере и убедитесь, что вы выполнили выход. Так как поведение приложения по умолчанию ASP.NET заключается в том, чтобы разрешить всем посетителям, и так как мы не вносим никаких изменений авторизации в файл корневого каталога Web.config , мы можем посетить файлы в корневом каталоге в качестве анонимного посетителя.

Щелкните ссылку "Создание учетных записей пользователей", найденную в левом столбце. Это приведет вас к ~/Membership/CreatingUserAccounts.aspx. Web.config Так как файл в папке Membership определяет правила авторизации для запрета анонимного доступа, запрос UrlAuthorizationModule прерывается и возвращается состояние HTTP 401 несанкционированного доступа. Изменяет FormsAuthenticationModule это состояние перенаправления 302, отправляя нас на страницу входа. Обратите внимание, что страница, к которому мы пытались получить доступ (CreatingUserAccounts.aspx), передается на страницу входа с помощью ReturnUrl параметра querystring.

Так как правила авторизации URL-адреса запрещают анонимный доступ, мы перенаправлены на страницу входа

Рис. 5. Так как правила авторизации URL-адреса запрещают анонимный доступ, мы перенаправлены на страницу входа (щелкните, чтобы просмотреть изображение полного размера)

После успешного входа мы перенаправляемся на страницу CreatingUserAccounts.aspx . На этот раз UrlAuthorizationModule разрешение на доступ к странице, так как мы больше не анонимны.

Применение правил авторизации URL-адресов к определенному расположению

Параметры авторизации, определенные в <system.web> разделе Web.config , применяются ко всем ресурсам ASP.NET в этом каталоге и его подкаталогах (до переопределения другим Web.config файлом). Однако в некоторых случаях может потребоваться, чтобы все ASP.NET ресурсы в данном каталоге имели определенную конфигурацию авторизации, за исключением одной или двух определенных страниц. Это можно сделать, добавив <location> элемент в Web.configфайл, указав его на файл, правила авторизации которого отличаются, и определив его уникальные правила авторизации.

Чтобы проиллюстрировать использование <location> элемента для переопределения параметров конфигурации для определенного ресурса, давайте настроим параметры авторизации, чтобы посетить только Tito CreatingUserAccounts.aspx. Для этого добавьте <location> элемент в Membership файл папки Web.config и обновите его разметку, чтобы она выглядела следующим образом:

<?xml version="1.0"?>
<configuration>
 <system.web>
 <authorization>
 <deny users="?" />
 </authorization>
 </system.web>

 <location path="CreatingUserAccounts.aspx">
 <system.web>
 <authorization>
 <allow users="Tito" />
 <deny users="*" />
 </authorization>
 </system.web>
 </location>
</configuration>

Элемент <authorization> , который определяет <system.web> правила авторизации URL-адресов по умолчанию для ASP.NET ресурсов в папке Membership и ее вложенных папок. Элемент <location> позволяет переопределить эти правила для определенного ресурса. В приведенной выше разметке <location> элемент ссылается на CreatingUserAccounts.aspx страницу и задает правила авторизации, такие как разрешение Tito, но запретить всем остальным.

Чтобы проверить это изменение авторизации, начните с посещения веб-сайта в качестве анонимного пользователя. Если вы пытаетесь посетить любую страницу в Membership папке, например UserBasedAuthorization.aspx, UrlAuthorizationModule запретит запрос, и вы будете перенаправлены на страницу входа. После входа, как, скажем, Скотт, вы можете посетить любую страницу в папке Membership , за исключениемCreatingUserAccounts.aspx. Попытка войти CreatingUserAccounts.aspx в систему как любой пользователь, но Tito приведет к попытке несанкционированного доступа, перенаправив вас обратно на страницу входа.

Примечание.

Элемент <location> должен отображаться вне элемента конфигурации <system.web> . Необходимо использовать отдельный <location> элемент для каждого ресурса, параметры авторизации которого необходимо переопределить.

ПросмотрUrlAuthorizationModuleиспользования правил авторизации для предоставления или запрета доступа

Определяет UrlAuthorizationModule , следует ли авторизовать определенное удостоверение для определенного URL-адреса, анализируя правила авторизации URL-адресов по одному за раз, начиная с первого и выполняя свой путь вниз. Как только совпадение найдено, пользователь получает или запрещает доступ, в зависимости от того, найден ли совпадение в элементе <allow> или <deny> элементе. Если совпадение не найдено, пользователь получает доступ. Следовательно, если требуется ограничить доступ, необходимо использовать <deny> элемент в качестве последнего элемента в конфигурации авторизации URL-адреса. Если вы опустите<deny>элемент, все пользователи получат доступ.

Чтобы лучше понять процесс, используемый UrlAuthorizationModule центром определения, рассмотрим пример правил авторизации URL-адресов, которые мы рассмотрели ранее на этом шаге. Первое правило — это <allow> элемент, позволяющий получить доступ к Tito и Скотту. Второе правило — это <deny> элемент, который запрещает доступ всем пользователям. Если анонимный пользователь посещает, начинается с просьбы, UrlAuthorizationModule является ли анонимный Скотт или Тито? Ответ, очевидно, нет, поэтому он переходит к второму правилу. Является ли анонимным в наборе всех? Так как ответ на этот вопрос имеет значение "Да", правило включено, <deny> и посетитель перенаправляется на страницу входа. Аналогичным образом, если Джисун посещает, начинается с просьбы, UrlAuthorizationModule Является ли Джисун либо Скотт или Тито? Так как она не является, продолжение второго вопроса, UrlAuthorizationModule Является Ли Цзисун в наборе всех? Она, так что она тоже отказано в доступе. Наконец, если Tito посещает, первый вопрос, заданный UrlAuthorizationModule ответом, является положительным ответом, поэтому Tito предоставляет доступ.

UrlAuthorizationModule Так как процессы правил авторизации из верхнего уровня вниз, остановившись на любом совпадении, важно иметь более конкретные правила перед менее конкретными. Таким образом, чтобы определить правила авторизации, которые запрещают Jisun и анонимных пользователей, но разрешают всем остальным прошедшим проверку подлинности пользователям, вы начнете с наиболее конкретного правила , которое влияет на Jisun - а затем переходите к менее конкретным правилам , что позволяет всем другим пользователям пройти проверку подлинности, но отрицать всех анонимных пользователей. Следующие правила авторизации URL-адресов реализуют эту политику, сначала запрещая Jisun, а затем запрещая анонимного пользователя. Любой прошедший проверку подлинности пользователь, отличный от Jisun, будет предоставлен доступ, так как ни один из этих <deny> инструкций не будет соответствовать.

<authorization>
 <deny users="Jisun" />
 <deny users="?" />
</authorization>

Шаг 2. Исправление рабочего процесса для несанкционированных пользователей, прошедших проверку подлинности

Как мы уже говорили ранее в этом руководстве в разделе "Просмотр рабочего процесса авторизации URL-адреса", когда неавторизованный запрос прерван, UrlAuthorizationModule запрос прерывается и возвращается состояние HTTP 401 Unauthorized. Это состояние 401 изменяется в FormsAuthenticationModule состояние перенаправления 302, которое отправляет пользователя на страницу входа. Этот рабочий процесс возникает при любом несанкционированном запросе, даже если пользователь проходит проверку подлинности.

Возвращение прошедшего проверку подлинности пользователя на страницу входа, скорее всего, запутает их, так как они уже вошли в систему. С помощью немного работы мы можем улучшить этот рабочий процесс, перенаправив прошедших проверку подлинности пользователей, которые выполняют несанкционированные запросы на страницу, которая объясняет, что они пытались получить доступ к ограниченной странице.

Начните с создания новой страницы ASP.NET в корневой папке UnauthorizedAccess.aspxвеб-приложения; не забудьте связать эту страницу с главной страницей Site.master . После создания этой страницы удалите элемент управления контентом, который ссылается на LoginContent ContentPlaceHolder, чтобы отображалось содержимое главной страницы по умолчанию. Затем добавьте сообщение, объясняющее ситуацию, а именно, что пользователь пытался получить доступ к защищенному ресурсу. После добавления такого сообщения UnauthorizedAccess.aspx декларативная разметка страницы должна выглядеть следующим образом:

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeFile="UnauthorizedAccess.aspx.cs" Inherits="UnauthorizedAccess"
Title="Untitled Page" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent"
Runat="Server">
 <h2>Unauthorized Access</h2>
 <p>
 You have attempted to access a page that you are not authorized to view.
 </p>
 <p>
 If you have any questions, please contact the site administrator.
 </p>
</asp:Content>

Теперь необходимо изменить рабочий процесс, чтобы, если несанкционированный запрос выполняется прошедшим проверку подлинности пользователем, они отправляются на UnauthorizedAccess.aspx страницу вместо страницы входа. Логика, которая перенаправляет несанкционированные запросы на страницу входа, похоронена в частном методе FormsAuthenticationModule класса, поэтому мы не можем настроить это поведение. Однако можно добавить собственную логику на страницу входа, в которую при необходимости перенаправляется пользователь UnauthorizedAccess.aspx.

FormsAuthenticationModule При перенаправлении несанкционированного посетителя на страницу входа он добавляет запрошенный URL-адрес в строку запроса с именемReturnUrl. Например, если неавторизованный пользователь попытался посетить OnlyTito.aspx, FormsAuthenticationModule он перенаправит его в Login.aspx?ReturnUrl=OnlyTito.aspx. Таким образом, если страница входа достигается прошедшим проверку подлинности пользователем со строками запросов, включающими ReturnUrl параметр, то мы знаем, что этот пользователь, не прошедший проверку подлинности, просто попытался посетить страницу, которую она не авторизована для просмотра. В таком случае мы хотим перенаправить ее.UnauthorizedAccess.aspx

Для этого добавьте следующий код в обработчик событий страницы Page_Load входа:

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        if (Request.IsAuthenticated && !string.IsNullOrEmpty(Request.QueryString["ReturnUrl"]))
        // This is an unauthorized, authenticated request...
        Response.Redirect("~/UnauthorizedAccess.aspx");
    }
}

Приведенный выше код перенаправляет прошедших проверку подлинности, несанкционированных пользователей на страницу UnauthorizedAccess.aspx . Чтобы увидеть эту логику в действии, посетите сайт как анонимный посетитель и щелкните ссылку "Создание учетных записей пользователей" в левом столбце. Это позволит вам перейти на ~/Membership/CreatingUserAccounts.aspx страницу, в которой на шаге 1 мы настроили только разрешение доступа к Tito. Так как анонимные пользователи запрещены, FormsAuthenticationModule перенаправляет нас обратно на страницу входа.

На этом этапе мы анонимны, поэтому Request.IsAuthenticated возвращается false и мы не перенаправляемся в UnauthorizedAccess.aspx. Вместо этого отображается страница входа. Войдите как пользователь, отличный от Tito, например Брюс. После ввода соответствующих учетных данных страница входа перенаправляет нас обратно ~/Membership/CreatingUserAccounts.aspx. Однако, так как эта страница доступна только Tito, мы несанкционированно просматриваем ее и быстро вернемся на страницу входа. Однако на этот раз Request.IsAuthenticated возвращается trueReturnUrl параметр запроса существует), поэтому мы перенаправляемся на страницу UnauthorizedAccess.aspx .

Проверка подлинности, неавторизованные пользователи перенаправляются в UnauthorizedAccess.aspx

Рис. 6. Проверка подлинности, перенаправлены неавторизованные UnauthorizedAccess.aspx пользователи (щелкните, чтобы просмотреть изображение полного размера)

Этот настраиваемый рабочий процесс представляет более разумный и простой пользовательский интерфейс путем короткого замыкания цикла, показанного на рис. 2.

Шаг 3. Ограничение функциональности на основе текущего пользователя, вошедшего в систему

Авторизация URL-адресов упрощает указание правил авторизации грубого ввода. Как мы видели на шаге 1, с авторизацией URL-адреса мы можем кратко указать, какие удостоверения разрешены, и какие из них запрещены просматривать определенную страницу или все страницы в папке. Однако в некоторых сценариях может потребоваться разрешить всем пользователям посещать страницу, но ограничить функциональные возможности страницы на основе посещения пользователем.

Рассмотрим случай веб-сайта электронной коммерции, который позволяет прошедшим проверку подлинности посетителей просматривать свои продукты. Когда анонимный пользователь посещает страницу продукта, он увидит только информацию о продукте и не будет предоставлена возможность оставить отзыв. Однако прошедший проверку подлинности пользователь, посещающий ту же страницу, увидит интерфейс проверки. Если пользователь, прошедший проверку подлинности, еще не проверил этот продукт, интерфейс позволит им отправить проверку; в противном случае будет отображаться их ранее отправленный обзор. Чтобы сделать этот сценарий еще одним шагом, страница продукта может отобразить дополнительные сведения и предложить расширенные функции для тех пользователей, которые работают в компании электронной коммерции. Например, страница продукта может вывести список запасов на складе и включить варианты изменения цены и описания продукта при посещении сотрудника.

Такие правила детальной авторизации можно реализовать как декларативно, так и программным способом (или с помощью некоторых сочетаний двух). В следующем разделе показано, как реализовать точное авторизацию с помощью элемента управления LoginView. После этого мы рассмотрим программные методы. Прежде чем мы можем ознакомиться с применением правил авторизации точного зерна, сначала необходимо создать страницу, функциональность которой зависит от пользователя, посещающего его.

Давайте создадим страницу, которая содержит файлы в определенном каталоге в GridView. Помимо перечисления имени, размера и других сведений каждого файла, GridView будет содержать два столбца LinkButtons: один заголовок Представления и один заголовок Delete. Если выбран элемент View LinkButton, будет отображаться содержимое выбранного файла; Если щелкнуть элемент Delete LinkButton, файл будет удален. Сначала создадим эту страницу таким образом, чтобы ее функциональность представления и удаления была доступна всем пользователям. В разделах "Использование элемента управления LoginView" и программного ограничения функциональных возможностей мы увидим, как включить или отключить эти функции на основе пользователя, посещающего страницу.

Примечание.

На странице ASP.NET мы планируем создать элемент управления GridView для отображения списка файлов. Так как в этом руководстве основное внимание уделяется проверке подлинности форм, авторизации, учетным записям пользователей и ролям, я не хочу тратить слишком много времени на обсуждение внутренних действий элемента управления GridView. Хотя в этом руководстве приведены конкретные пошаговые инструкции по настройке этой страницы, он не учитывает сведения о том, почему некоторые варианты были сделаны, или какие эффекты имеют определенные свойства для отрисованных выходных данных. Для тщательного изучения элемента управления GridView ознакомьтесь с моей работой с данными в ASP.NET 2.0 серии руководств.

Начните с открытия UserBasedAuthorization.aspx файла в папке Membership и добавления элемента управления GridView на страницу с именем FilesGrid. В смарт-теге GridView щелкните ссылку "Изменить столбцы", чтобы запустить диалоговое окно "Поля". Отсюда снимите флажок автоматического создания полей в левом нижнем углу. Затем добавьте кнопку "Выбрать", кнопку "Удалить" и два BoundFields в левом верхнем углу (кнопки "Выбрать" и "Удалить" можно найти в типе CommandField). Задайте для свойства кнопки SelectText Select значение View и first BoundField HeaderText и DataField свойства Name. Присвойте второму свойству BoundField HeaderText значение Size в Байтах, свойству DataField Length, свойству {0:N0} DataFormatString и свойству HtmlEncode False.

После настройки столбцов GridView нажмите кнопку "ОК", чтобы закрыть диалоговое окно "Поля". В окно свойств задайте для свойства GridView DataKeyNames значение FullName. На этом этапе декларативная разметка GridView должна выглядеть следующим образом:

<asp:GridView ID="FilesGrid" DataKeyNames="FullName" runat="server" AutoGenerateColumns="False">
 <Columns>
 <asp:CommandField SelectText="View" ShowSelectButton="True"/>
 <asp:CommandField ShowDeleteButton="True" />
 <asp:BoundField DataField="Name" HeaderText="Name" />
 <asp:BoundField DataField="Length" DataFormatString="{0:N0}"
 HeaderText="Size in Bytes" HtmlEncode="False" />
 </Columns>
</asp:GridView>

С помощью разметки GridView мы готовы написать код, который будет извлекать файлы в определенном каталоге и привязывать их к GridView. Добавьте следующий код в обработчик событий страницы Page_Load :

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        string appPath = Request.PhysicalApplicationPath;
        DirectoryInfo dirInfo = new DirectoryInfo(appPath);

        FileInfo[] files = dirInfo.GetFiles();

        FilesGrid.DataSource = files;
        FilesGrid.DataBind();
    }
}

Приведенный DirectoryInfo выше код использует класс для получения списка файлов в корневой папке приложения. Метод GetFiles() возвращает все файлы в каталоге в виде массива FileInfo объектов, которые затем привязаны к GridView. Объект FileInfo имеет ассортимент свойств, таких какNameLength, иIsReadOnly, среди прочего. Как видно из декларативной разметки, GridView отображает только Name те и Length свойства.

Примечание.

Классы DirectoryInfo находятся в System.IO пространствеFileInfo имен. Поэтому необходимо либо предуказать имена этих классов с именами пространств имен, либо импортировать пространство имен в файл класса (через using System.IO).

Перейдите на эту страницу через браузер. Он отобразит список файлов, размещенных в корневом каталоге приложения. При нажатии кнопки "Вид" или "Удалить LinkButtons" происходит обратная связь, но никаких действий не будет происходить, так как мы еще не создали необходимые обработчики событий.

GridView выводит список файлов в корневом каталоге веб-приложения.

Рис. 7. GridView выводит список файлов в корневом каталоге веб-приложения (щелкните, чтобы просмотреть изображение полного размера)

Нам нужен способ отображения содержимого выбранного файла. Вернитесь в Visual Studio и добавьте текстовое поле с именем FileContents выше GridView. Присвойте свойству TextMode MultiLine значение и Columns Rows свойства 95 % и 10 соответственно.

<asp:TextBox ID="FileContents" runat="server" Rows="10"
TextMode="MultiLine" Width="95%"></asp:TextBox>

Затем создайте обработчик событий для события GridView SelectedIndexChanged и добавьте следующий код:

protected void FilesGrid_SelectedIndexChanged(object sender, EventArgs e)
{
    // Open the file and display it
    string fullFileName = FilesGrid.SelectedValue.ToString();
    string contents = File.ReadAllText(fullFileName);
    FileContents.Text = contents;
}

Этот код использует свойство GridView SelectedValue для определения полного имени файла выбранного файла. Во внутренней DataKeys среде коллекция ссылается SelectedValueна эту коллекцию, поэтому необходимо задать для свойства GridView DataKeyNames значение Name, как описано ранее на этом шаге. Класс File используется для чтения содержимого выбранного файла в строку, которая затем назначается FileContents свойству TextBoxText, тем самым отображая содержимое выбранного файла на странице.

Содержимое выбранного файла отображается в текстовом поле

Рис. 8. Содержимое выбранного файла отображается в текстовом поле (щелкните, чтобы просмотреть изображение полного размера)

Примечание.

Если вы просматриваете содержимое файла, содержащего разметку HTML, а затем пытаетесь просмотреть или удалить файл, вы получите сообщение об ошибке HttpRequestValidationException . Это происходит, так как при обратной отправке содержимого TextBox обратно на веб-сервер. По умолчанию ASP.NET вызывает ошибку HttpRequestValidationException при обнаружении потенциально опасного содержимого обратной передачи, например разметки HTML. Чтобы отключить эту ошибку, отключите проверку запроса на страницу, добавив ValidateRequest="false" в директиву @Page . Дополнительные сведения о преимуществах проверки запросов, а также о том, какие меры предосторожности следует предпринять при отключении, ознакомьтесь со статьей "Проверка запросов— предотвращение атак скриптов".

Наконец, добавьте обработчик событий со следующим кодом для события GridView:RowDeleting

protected void FilesGrid_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
    string fullFileName = FilesGrid.DataKeys[e.RowIndex].Value.ToString();
    FileContents.Text = string.Format("You have opted to delete {0}.", fullFileName);

    // To actually delete the file, uncomment the following line
    // File.Delete(fullFileName);
}

Код просто отображает полное имя файла для удаления в FileContents Текстовом поле без фактического удаления файла.

Нажатие кнопки

Рис. 9. Нажатие кнопки "Удалить" не удаляет файл (щелкните, чтобы просмотреть изображение полного размера)

На шаге 1 мы настроили правила авторизации URL-адреса, чтобы запретить анонимным пользователям просматривать страницы в папке Membership . Для лучшей проверки подлинности на основе детализированной проверки подлинности давайте позволим анонимным пользователям посетить UserBasedAuthorization.aspx страницу, но с ограниченными возможностями. Чтобы открыть эту страницу для доступа ко всем пользователям, добавьте следующий <location> элемент Web.config в файл в папку Membership :

<location path="UserBasedAuthorization.aspx">
 <system.web>
 <authorization>
 <allow users="*" />
 </authorization>
 </system.web>
</location>

После добавления этого <location> элемента проверьте новые правила авторизации URL-адресов, выполнив выход из сайта. Как анонимный пользователь, который вы должны быть разрешены для посещения UserBasedAuthorization.aspx страницы.

В настоящее время любой прошедший проверку подлинности или анонимный пользователь может посетить UserBasedAuthorization.aspx страницу и просмотреть или удалить файлы. Давайте сделаем это так, чтобы только прошедшие проверку подлинности пользователи могли просматривать содержимое файла, и только Tito может удалить файл. Такие правила детальной авторизации можно применять декларативно, программно или с помощью сочетания обоих методов. Давайте используем декларативный подход, чтобы ограничить, кто может просматривать содержимое файла; Мы будем использовать программный подход для ограничения того, кто может удалить файл.

Использование элемента управления LoginView

Как мы видели в предыдущих руководствах, элемент управления LoginView полезен для отображения различных интерфейсов для прошедших проверку подлинности и анонимных пользователей, а также предоставляет простой способ скрыть функциональные возможности, недоступные анонимным пользователям. Так как анонимные пользователи не могут просматривать или удалять файлы, необходимо отобразить FileContents текстовое поле только при посещении страницы прошедшим проверку подлинности пользователем. Для этого добавьте элемент управления LoginView на страницу, назовите его LoginViewForFileContentsTextBoxи переместите FileContents декларативную разметку TextBox в элемент управления LoggedInTemplateLoginView.

<asp:LoginView ID=" LoginViewForFileContentsTextBox " runat="server">
 <LoggedInTemplate>
 <p>
 <asp:TextBox ID="FileContents" runat="server" Rows="10"
 TextMode="MultiLine" Width="95%"></asp:TextBox>
 </p>
 </LoggedInTemplate>
</asp:LoginView>

Веб-элементы управления в шаблонах LoginView больше не доступны непосредственно из класса code-behind. Например, FilesGrid обработчики gridView SelectedIndexChanged и RowDeleting обработчики событий в настоящее время ссылались на FileContents элемент управления TextBox с кодом, например:

FileContents.Text = text;

Однако этот код больше не действителен. Путем перемещения текстового FileContents поля в текстовое LoggedInTemplate поле невозможно напрямую получить доступ. Вместо этого необходимо использовать FindControl("controlId") метод для программной ссылки на элемент управления. FilesGrid Обновите обработчики событий, чтобы ссылаться на textBox, как показано ниже.

TextBox FileContentsTextBox = LoginViewForFileContentsTextBox.FindControl("FileContents") as TextBox;
FileContentsTextBox.Text = text;

После перемещения TextBox в LoginView LoggedInTemplate и обновления кода страницы для ссылки на TextBox с помощью FindControl("controlId") шаблона посетите страницу в качестве анонимного пользователя. Как показано на рисунке 10, текстовое FileContents поле не отображается. Однако элемент View LinkButton по-прежнему отображается.

Элемент управления LoginView отображает только текстовое поле FileContents для прошедших проверку подлинности пользователей

Рис. 10. Элемент управления LoginView отображает FileContents только текстовое поле для прошедших проверку подлинности пользователей (щелкните, чтобы просмотреть изображение полного размера)

Одним из способов скрытия кнопки "Вид" для анонимных пользователей является преобразование поля GridView в TemplateField. При этом будет создан шаблон, содержащий декларативную разметку для представления LinkButton. Затем мы можем добавить элемент управления LoginView в TemplateField и поместить LinkButton в систему LoginView LoggedInTemplate, тем самым скрывая кнопку "Вид" от анонимных посетителей. Для этого щелкните ссылку "Изменить столбцы" из смарт-тега GridView, чтобы запустить диалоговое окно "Поля". Затем нажмите кнопку "Выбрать" из списка в левом нижнем углу и щелкните поле "Преобразовать" в ссылку TemplateField. Это приведет к изменению декларативной разметки поля:

<asp:CommandField SelectText="View" ShowSelectButton="True"/>

Кому:

<asp:TemplateField ShowHeader="False">
 <ItemTemplate>
 <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False"
 CommandName="Select" Text="View"></asp:LinkButton>
 </ItemTemplate>
</asp:TemplateField>

На этом этапе можно добавить LoginView в TemplateField. Следующая разметка отображает представление LinkButton только для прошедших проверку подлинности пользователей.

<asp:TemplateField ShowHeader="False">
 <ItemTemplate>
 <asp:LoginView ID="LoginView1" runat="server">
 <LoggedInTemplate>
 <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False"
 CommandName="Select" Text="View"></asp:LinkButton>
 </LoggedInTemplate>
 </asp:LoginView>
 </ItemTemplate>
</asp:TemplateField>

Как показано на рисунке 11, конечный результат не так выглядит, как столбец View по-прежнему отображается, даже если представление LinkButtons в столбце скрыты. Мы рассмотрим, как скрыть весь столбец GridView (а не только LinkButton) в следующем разделе.

Элемент управления LoginView скрывает linkButtons view для анонимных посетителей

Рис. 11. Элемент управления LoginView скрывает представление LinkButtons для анонимных посетителей (щелкните, чтобы просмотреть изображение полного размера)

Программное ограничение функциональных возможностей

В некоторых случаях декларативные методы недостаточно для ограничения функциональности на страницу. Например, доступность определенных функций страниц может зависеть от условий, не зависящих от того, является ли пользователь, посещая страницу анонимным или прошедшим проверку подлинности. В таких случаях различные элементы пользовательского интерфейса можно отображать или скрывать с помощью программных средств.

Чтобы ограничить функциональные возможности программными средствами, необходимо выполнить две задачи:

  1. Определите, может ли пользователь, посещая страницу, получить доступ к функциям и
  2. Программно изменяйте пользовательский интерфейс на основе того, имеет ли пользователь доступ к функциональностью, которая имеется в вопросе.

Чтобы продемонстрировать применение этих двух задач, давайте разрешаем Tito удалять файлы из GridView. Наша первая задача , то, чтобы определить, является ли Tito посетить страницу. После определения необходимо скрыть (или показать) столбец GridView Delete. Столбцы GridView доступны через его Columns свойство. Столбец отображается только в том случае, если его Visible свойство задано true (по умолчанию).

Добавьте следующий код в Page_Load обработчик событий перед привязкой данных к GridView:

// Is this Tito visiting the page?
string userName = User.Identity.Name;
if (string.Compare(userName, "Tito", true) == 0)
    // This is Tito, SHOW the Delete column
    FilesGrid.Columns[1].Visible = true;
else
    // This is NOT Tito, HIDE the Delete column
    FilesGrid.Columns[1].Visible = false;

Как мы обсуждали в руководстве по обзору проверки подлинности форм, User.Identity.Name возвращает имя удостоверения. Это соответствует имени пользователя, введенного в элементе управления "Вход". Если на странице используется Tito, для свойства второго столбца Visible GridView задано trueзначение; в противном случае он имеет falseзначение . Чистый результат заключается в том, что если кто-то другой, кроме Tito, посещает страницу либо другой прошедший проверку подлинности, либо анонимный пользователь, столбец Delete не отображается (см. рис. 12); Однако, когда Tito посещает страницу, столбец Delete присутствует (см. рис. 13).

Столбец удаления не отображается при посещении кого-то другого, кроме Тито (например, Брюса)

Рис. 12. Столбец удаления не отображается при посещении кем-то, кроме Tito (например, Брюс) (щелкните, чтобы просмотреть изображение полного размера)

Столбец удаления отрисовывается для Tito

Рис. 13. Столбец удаления отрисовывается для Tito (щелкните, чтобы просмотреть изображение полного размера)

Шаг 4. Применение правил авторизации к классам и методам

На шаге 3 мы запретили анонимным пользователям просматривать содержимое файла и запрещали всем пользователям, но Tito удалять файлы. Это было сделано путем скрытия связанных элементов пользовательского интерфейса для несанкционированных посетителей с помощью декларативных и программных методов. В нашем простом примере правильное скрытие элементов пользовательского интерфейса было простым, но что касается более сложных сайтов, где может быть много различных способов выполнения одной и той же функциональности? При ограничении этой функциональности несанкционированным пользователям что произойдет, если мы забыли скрыть или отключить все применимые элементы пользовательского интерфейса?

Простой способ обеспечить доступ к определенной части функциональности неавторизованным пользователем — декорировать этот класс или метод атрибутомPrincipalPermission. Если среда выполнения .NET использует класс или выполняет один из его методов, проверяет, имеет ли текущий контекст безопасности разрешение на использование класса или выполнение метода. Атрибут PrincipalPermission предоставляет механизм, с помощью которого можно определить эти правила.

Давайте продемонстрируем использование PrincipalPermission атрибута в обработчиках событий GridView SelectedIndexChanged и RowDeleting запретить выполнение анонимными пользователями и пользователями, кроме Tito, соответственно. Все, что нам нужно сделать, — добавить соответствующий атрибут на вершину каждого определения функции:

[PrincipalPermission(SecurityAction.Demand, Authenticated=true)]
protected void FilesGrid_SelectedIndexChanged(object sender, EventArgs e)
{
    ...
}

[PrincipalPermission(SecurityAction.Demand, Name="Tito")]
protected void FilesGrid_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
    ...
}

Атрибут обработчика SelectedIndexChanged событий определяет, что только прошедшие проверку подлинности пользователи могут выполнять обработчик событий, где в качестве атрибута обработчика RowDeleting событий ограничивает выполнение tito.

Если, как-то, пользователь, отличный от Tito, пытается выполнить RowDeleting обработчик событий или пользователь, не прошедший проверку подлинности, пытается выполнить SelectedIndexChanged обработчик событий, среда выполнения .NET вызовет ошибку SecurityException.

Если контекст безопасности не авторизован для выполнения метода, создается исключение SecurityException

Рис. 14. Если контекст безопасности не авторизован для выполнения метода, SecurityException создается исключение (щелкните, чтобы просмотреть изображение полного размера)

Примечание.

Чтобы разрешить нескольким контекстам безопасности доступ к классу или методу, украсите класс или метод атрибутом PrincipalPermission для каждого контекста безопасности. То есть, чтобы разрешить обработчику RowDeleting событий Tito и Bruce, добавьте два PrincipalPermission атрибута:

[PrincipalPermission(SecurityAction.Demand, Name="Tito")]

[PrincipalPermission(SecurityAction.Demand, Name="Bruce")]

Помимо страниц ASP.NET, многие приложения также имеют архитектуру, которая включает различные слои, такие как бизнес-логика и уровни доступа к данным. Эти уровни обычно реализуются как библиотеки классов и предлагают классы и методы для выполнения бизнес-логики и связанных с данными функций. Атрибут PrincipalPermission полезен для применения правил авторизации к этим уровням.

Дополнительные сведения об использовании атрибута PrincipalPermission для определения правил авторизации для классов и методов см. в записи блога Скотта Гутри, в записи блога "Добавление правил авторизации в уровни бизнес-и данных с помощью".PrincipalPermissionAttributes

Итоги

В этом руководстве мы рассмотрели, как применять правила авторизации на основе пользователей. Мы начали с просмотра ASP. Платформа авторизации URL-адресов NET. По каждому запросу модуль UrlAuthorizationModule ASP.NET проверяет правила авторизации URL-адресов, определенные в конфигурации приложения, чтобы определить, разрешено ли удостоверение получить доступ к запрошенным ресурсам. Короче говоря, авторизация URL-адресов упрощает указание правил авторизации для определенной страницы или для всех страниц в определенном каталоге.

Платформа авторизации URL-адресов применяет правила авторизации на странице. При авторизации URL-адреса запрашивающее удостоверение авторизовано для доступа к определенному ресурсу или нет. Однако во многих сценариях требуется более точное правило авторизации. Вместо определения того, кто разрешен для доступа к странице, может потребоваться предоставить всем доступ к странице, но показать разные данные или предложить различные функциональные возможности в зависимости от пользователя, посещающего страницу. Авторизация на уровне страницы обычно включает скрытие определенных элементов пользовательского интерфейса, чтобы предотвратить доступ несанкционированных пользователей к запрещенным функциям. Кроме того, можно использовать атрибуты для ограничения доступа к классам и выполнению методов для определенных пользователей.

Счастливое программирование!

Дополнительные материалы

Дополнительные сведения о разделах, описанных в этом руководстве, см. в следующих ресурсах:

Об авторе

Скотт Митчелл, автор нескольких книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Сэмс Учит себя ASP.NET 2.0 в 24 часах. Скотт можно получить по mitchell@4guysfromrolla.com адресу или через свой блог.http://ScottOnWriting.NET

Особое спасибо

Эта серия учебников была проверена многими полезными рецензентами. Хотите просмотреть мои предстоящие статьи MSDN? Если да, упадите меня линию в mitchell@4GuysFromRolla.com.