Учебники

ASP.NET MVC — Безопасность

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

  • облако
  • База данных SQL
  • Локальный активный каталог Windows

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

Аутентификация

Аутентификация пользователя означает проверку личности пользователя. Это действительно важно. Вам может потребоваться представить ваше приложение только аутентифицированным пользователям по очевидным причинам.

Давайте создадим новое приложение ASP.Net MVC.

Новое приложение MVC

Нажмите OK, чтобы продолжить.

Когда вы запускаете новое приложение ASP.NET, одним из шагов в этом процессе является настройка служб аутентификации для нужд приложения.

Выберите шаблон MVC, и вы увидите, что кнопка Изменить аутентификацию теперь включена.

Кнопка аутентификации включена

Это делается с помощью кнопки «Изменить аутентификацию», которая появляется в диалоговом окне «Новый проект». Аутентификация по умолчанию — индивидуальные учетные записи пользователей.

Параметры аутентификации

Когда вы нажмете кнопку «Изменить», вы увидите диалоговое окно с четырьмя параметрами, которые перечислены ниже.

Нет аутентификации

Первый вариант — Без аутентификации, и этот вариант используется, когда вы хотите создать сайт, который не заботится о том, кто посетители.

Нет аутентификации

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

Индивидуальные учетные записи пользователей

Второй вариант — индивидуальные учетные записи пользователей, и это традиционная проверка подлинности на основе форм, когда пользователи могут посещать веб-сайт. Они могут зарегистрироваться, создать логин, и по умолчанию их имя пользователя хранится в базе данных SQL Server с использованием некоторых новых функций идентификации ASP.NET, которые мы рассмотрим.

Индивидуальные учетные записи пользователей

Пароль также хранится в базе данных, но сначала он хэшируется. Поскольку пароль хешируется, вам не нужно беспокоиться о паролях в виде простого текста, которые хранятся в базе данных.

Эта опция обычно используется для интернет-сайтов, где вы хотите установить личность пользователя. В дополнение к тому, что пользователь может создать локальный логин с паролем для вашего сайта, вы также можете включить логин от третьих лиц, таких как Microsoft, Google, Facebook и Twitter.

Это позволяет пользователю войти на ваш сайт, используя свою учетную запись Live или учетную запись Twitter, и он может выбрать локальное имя пользователя, но вам не нужно хранить какие-либо пароли.

Это опция, с которой мы проведем некоторое время в этом модуле; опция индивидуальных учетных записей пользователей.

Работа и школьные счета

Третий вариант — использовать учетные записи организации, и это обычно используется для бизнес-приложений, где вы будете использовать службы федерации активных каталогов.

Счета рабочей школы

Вы либо настроите Office 365, либо будете использовать службы Azure Active Directory, и у вас будет единый вход для внутренних приложений и облачных приложений.

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

Проверка подлинности Windows

Четвертый вариант — проверка подлинности Windows, которая хорошо работает для приложений интрасети.

Проверка подлинности Windows

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

Давайте рассмотрим аутентификацию на основе форм, которая называется «Индивидуальные учетные записи пользователей». Это приложение будет хранить имена пользователей и пароли, старые пароли в локальной базе данных SQL Server, и при создании этого проекта Visual Studio также добавит пакеты NuGet.

Аутентификация на основе форм

Теперь запустите это приложение, и когда вы впервые зайдете в это приложение, вы станете анонимным пользователем.

Анонимный пользователь

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

Нажмите на ссылку Зарегистрироваться, и вы увидите следующий вид.

Нажмите ссылку Регистрация

Введите свой адрес электронной почты и пароль.

Введите EmailId пароль

Нажмите Зарегистрироваться. Теперь приложение распознает вас.

Нажмите Зарегистрироваться

Он сможет отображать ваше имя. На следующем снимке экрана вы можете увидеть Hello, [email protected]! отображается. Вы можете нажать на это, и это ссылка на страницу, где вы можете изменить пароль.

Показать ваше имя

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

Нажмите кнопку выхода

Нажмите еще раз на ссылку Войти, и вы перейдете на следующую страницу.

Нажмите на ссылку для входа

Вы можете войти снова с теми же учетными данными.

За сценой идет большая работа, чтобы добраться до этой точки. Однако мы хотим изучить каждую из функций и посмотреть, как построен этот пользовательский интерфейс. Что такое управление выходом из системы и процессом входа в систему? Где эта информация отсортирована в базе данных?

Давайте просто начнем с пары простых основ. Сначала мы увидим, как отображается это имя пользователя. Откройте _Layout.cshtml из папки View / Shared в обозревателе решений.

<!DOCTYPE html>
<html>
   <head>
      <meta charset = "utf-8" />
      <meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
      <title>@ViewBag.Title - My ASP.NET Application</title>
      @Styles.Render("~/Content/css")
      @Scripts.Render("~/bundles/modernizr")
   </head>
	
   <body>
      <div class = "navbar navbar-inverse navbar-fixed-top">
         <div class = "container">
			
            <div class = "navbar-header">
               <button type = "button" class = "navbar-toggle" datatoggle = "collapse"
                  data-target = ".navbar-collapse">
                     <span class = "icon-bar"></span>
                     <span class = "icon-bar"></span>
                     <span class = "icon-bar"></span>
               </button>
					
               @Html.ActionLink("Application name", "Index", "Home", new
               { area = "" }, new { @class = "navbar-brand" })
            </div>
				
            <div class = "navbar-collapse collapse">
               <ul class = "nav navbar-nav">
                  <li>@Html.ActionLink("Home", "Index", "Home")</li>
                  <li>@Html.ActionLink("About", "About", "Home")</li>
                  <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
               </ul>
					
               @Html.Partial("_LoginPartial")
            </div>
				
         </div>
			
      </div>
      <div class = "container body-content">
         @RenderBody()
         <hr />
         <footer>
            <p>© @DateTime.Now.Year - My ASP.NET Application</p>
         </footer>
      </div>
		
      @Scripts.Render("~/bundles/jquery")
      @Scripts.Render("~/bundles/bootstrap")
      @RenderSection("scripts", required: false)
		
   </body>
</html>

Существует общая панель навигации, имя приложения, меню, и есть частичное представление, которое отображается как _loginpartial. Это на самом деле представление, которое отображает имя пользователя или регистр и имя входа. Так что _loginpartial.cshtml также находится в общей папке.

@using Microsoft.AspNet.Identity
@if (Request.IsAuthenticated) {
   using (Html.BeginForm("LogOff", "Account", FormMethod.Post,
      new { id = "logoutForm", @class = "navbar-right" })){
         @Html.AntiForgeryToken()
         <ul class = "nav navbar-nav navbar-right">
            <li>
               @Html.ActionLink("Hello " + User.Identity.GetUserName() + "!",
               "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
            </li>
				
            <li>
               <a href = "javascript:document.getElementById('logoutForm').submit()">Logoff</a>
            </li>
				
         </ul>
      }
}else{
   <ul class = "nav navbar-nav navbar-right">
      <li>@Html.ActionLink("Register", "Register", "Account", routeValues:
         null, htmlAttributes: new { id = "registerLink" })</li>
			
      <li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null,
         htmlAttributes: new { id = "loginLink" })</li>
   </ul>
}

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

На данный момент мы хотим посмотреть, как получить имя пользователя, и это внутри Request.IsAuthenticated. Вы можете увидеть вызов User.Identity.GetUserName. Это позволит получить имя пользователя, которое в данном случае будет «[email protected]».

авторизация

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

Щелкните правой кнопкой мыши папку контроллера и выберите «Добавить» → «Контроллер».

Пользователь вошел в систему

Выберите контроллер MVC 5 — Пустой контроллер и нажмите «Добавить».

Введите имя SecretController и нажмите кнопку «Добавить».

SecretController

Он будет иметь два действия внутри, как показано в следующем коде.

using System.Web.Mvc;

namespace MVCSecurityDemo.Controllers{
   public class SecretController : Controller{
      // GET: Secret
      public ContentResult Secret(){
         return Content("Secret informations here");
      }
		
      public ContentResult PublicInfo(){
         return Content("Public informations here");
      }
   }
}

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

Секретная информация здесь

Таким образом, только аутентифицированные пользователи могут получить доступ к методу секретного действия, и PublicInfo может использовать любой пользователь без какой-либо аутентификации.

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

// GET: Secret
[Authorize]
public ContentResult Secret(){
   return Content("Secret informations here");
}

Теперь снова запустите это приложение и укажите тот же URL-адрес http: // localhost: 54232 / Secret / Secret . Приложение MVC обнаружит, что у вас нет доступа к этой конкретной области приложения, и автоматически перенаправит вас на страницу входа, где она даст вам возможность войти в систему и попытаться вернуться в эту область приложения. где вам было отказано.

Перенаправить страницу автоматического входа

Вы можете видеть, что он указан в обратном URL-адресе, который, по сути, сообщает этой странице, что, если пользователь успешно вошел в систему, перенаправьте его обратно в / secret / secret.

Введите свои учетные данные и нажмите кнопку «Войти». Вы увидите, что он идет прямо на эту страницу.

Секретная информация здесь

Если вы вернетесь на домашнюю страницу и выйдете из системы, вы не сможете перейти на секретную страницу. Вас снова попросят войти в систему, но если перейти в / Secret / PublicInfo, вы можете увидеть эту страницу, даже если вы не прошли аутентификацию.

Публичная информация здесь

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

using System.Web.Mvc;

namespace MVCSecurityDemo.Controllers{
   [Authorize]
   public class SecretController : Controller{
      // GET: Secret
      public ContentResult Secret(){
         return Content("Secret informations here");
      }
		
      public ContentResult PublicInfo(){
         return Content("Public informations here");
      }
   }
}

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

using System.Web.Mvc;

namespace MVCSecurityDemo.Controllers{
   [Authorize]
   public class SecretController : Controller{
      // GET: Secret
      public ContentResult Secret(){
         return Content("Secret informations here");
      }
		
      [AllowAnonymous]
      public ContentResult PublicInfo(){
         return Content("Public informations here");
      }
   }
}

Запустите это приложение, и вы сможете получить доступ к / Secret / PublicInfo при входе в систему, но для выполнения других действий потребуется проверка подлинности.

Публичная информация здесь

Это позволит анонимным пользователям участвовать только в этом действии.

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

using System.Web.Mvc;

namespace MVCSecurityDemo.Controllers{
   [Authorize(Users = "[email protected]")]
   public class SecretController : Controller{
      // GET: Secret
      public ContentResult Secret(){
         return Content("Secret informations here");
      }
		
      [AllowAnonymous]
      public ContentResult PublicInfo(){
         return Content("Public informations here");
      }
   }
}

Когда вы запустите это приложение и перейдете в / secret / secret, оно попросит вас войти в систему, потому что он не является подходящим пользователем для этого контроллера.