Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Хотя рекомендуемым способом аутентификации в приложениях ASP.NET MVC 5 является аутентификация на основе AspNet Identity, но все же это не единственный доступный механизм. В предыдущих версиях MVC механизм аутентификации основывался на аутентификации форм. И мы также можем использовать данный механизм в приложениях ASP.NET MVC 5.
Посмотрим на примере. Создадим новое приложение для MVC 5, выбрав при создании в качестве типа аутентификации No Authentication:
Поскольку все данные о пользователях у нас будут находиться в базе данных MS SQL Server, то для взаимодействия с ней добавим в проект через NuGet библиотеки EntityFramework.
После подключения Entity Framework в проект нам надо включить аутентификацию форм. Это делается в файле web.config. Найдем в нем секцию
<system.web>
и внутри этой секции поместим следующую подсекцию:
<authentication mode="Forms"> <forms name="cookies" timeout="2880" loginUrl="~/Account/Login" /> </authentication>
Установив mode="Forms", мы тем самым подключаем аутентификацию форм. Далее мы задаем ряд параметров. Нам доступен в общей сложности следующий список параметров:
coockieless: определяет, применяются ли куки-наборы и как они используются. Может принимать следующие значения: UseCookies(определяет, что куки-наборы будут использоваться всегда вне зависимости от устройства), UseUri (куки-наборы никогда не используются), AutoDetect (если устройство поддерживает куки-наборы, то они используются, в противном случае они не применяются, при этом проводится тестирование, определяющее, включена ли поддержка), UseDeviceProfile (используется по умолчанию) (если устройство поддерживает куки-наборы, то они используются, в противном случае они не применяются, в отличие от предыдущего случая тестирование не проводится)
defaultUrl: определяет путь, по которому осуществляется переход после авторизации
domain: определяет куки-наборы для всего домена. Благодаря этому мы можем использовать одни и те же куки-набры для главного домена и его субдоменов. По умолчанию имеет значение в качестве пустой строки
loginUrl: адрес для аутентификации пользователя. Значение по умолчанию - "~/Account/Login"
name: задает имя для куки-набора. Значение по умолчанию - ".ASPXAUTH"
path: задает путь для куки-наборов. Значение по умолчанию - "/"
requireSSL: определяет, требуется ли SSL-соединение для передачи куки-наборов. Значение по умолчанию false
timeout: определяет срок действия куков в минутах
В нашем случае мы задаем только три параметра.
Также добавим в файл web.config строку подключения для EntityFramework:
<connectionStrings> <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB; AttachDbFilename=|DataDirectory|\FormsAuth.mdf; Initial Catalog=FormsAuth;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings>
Теперь надо создать всю необходимую инфраструктуру для аутентификации - модели, контроллеры и представления. Создадим модель User, которая будет описывать пользователя:
public class User { public int Id { get; set; } public string Email { get; set; } public string Password { get;set;} public int Age { get; set; } }
Также добавим контекст данных UserContext Для взимодействия с БД:
public class UserContext : DbContext { public UserContext() : base("DefaultConnection") { } public DbSet<User> Users { get; set; } }
При регистрации и логине мы не будем напрямую взаимодействовать с моделью User. Вместо этого мы будем использовать специальные модели, которые также добавим в проект:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel.DataAnnotations; namespace FormsAuthApp.Models { public class LoginModel { [Required] public string Name { get; set; } [Required] [DataType(DataType.Password)] public string Password { get; set; } } public class RegisterModel { [Required] public string Name { get; set; } [Required] [DataType(DataType.Password)] public string Password { get; set; } [Required] [DataType(DataType.Password)] [Compare("Password", ErrorMessage="Пароли не совпадают")] public string ConfirmPassword { get; set; } [Required] public int Age { get; set; } } }
Эти модели будет использоваться соответственно для представлений логина и регистрации. Пусть представление для регистрации будет выглядеть следующим образом:
@model FormsAuthApp.Models.RegisterModel @{ ViewBag.Title = "Регистрация"; } <h2>Регистрация</h2> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> @Html.ValidationSummary(true) <div class="form-group"> @Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Name) @Html.ValidationMessageFor(model => model.Name) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Password, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Password) @Html.ValidationMessageFor(model => model.Password) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.ConfirmPassword, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.ConfirmPassword) @Html.ValidationMessageFor(model => model.ConfirmPassword) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Age, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Age) @Html.ValidationMessageFor(model => model.Age) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Зарегистрировать" class="btn btn-default" /> </div> </div> </div> } @section Scripts { @Scripts.Render("~/bundles/jqueryval") }
Представление для логина будет выглядеть аналогично. Теперь добавим новый контроллер AccountController со следующим содержанием:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Security; using System.Web.Mvc; using FormsAuthApp.Models; namespace FormsAuthApp.Controllers { public class AccountController : Controller { public ActionResult Login() { return View(); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult Login(LoginModel model) { if (ModelState.IsValid) { // поиск пользователя в бд User user = null; using (UserContext db = new UserContext()) { user = db.Users.FirstOrDefault(u => u.Email == model.Name && u.Password == model.Password); } if (user != null) { FormsAuthentication.SetAuthCookie(model.Name, true); return RedirectToAction("Index", "Home"); } else { ModelState.AddModelError("", "Пользователя с таким логином и паролем нет"); } } return View(model); } public ActionResult Register() { return View(); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult Register(RegisterModel model) { if(ModelState.IsValid) { User user = null; using (UserContext db = new UserContext()) { user = db.Users.FirstOrDefault(u => u.Email == model.Name); } if (user == null) { // создаем нового пользователя using (UserContext db = new UserContext()) { db.Users.Add(new User { Email = model.Name, Password = model.Password, Age=model.Age }); db.SaveChanges(); user = db.Users.Where(u => u.Email == model.Name && u.Password == model.Password).FirstOrDefault(); } // если пользователь удачно добавлен в бд if (user != null) { FormsAuthentication.SetAuthCookie(model.Name, true); return RedirectToAction("Index", "Home"); } } else { ModelState.AddModelError("", "Пользователь с таким логином уже существует"); } } return View(model); } public ActionResult Logoff() { FormsAuthentication.SignOut(); return RedirectToAction("Index", "Home"); } } }
При регистрации мы добавляем нового пользователя в БД, а при логине просто смотрим, есть ли такой пользователь. И если пользователь найден, то с помощью
аутентификации форм устанавливаем куки FormsAuthentication.SetAuthCookie(model.Name, true);
.
Теперь, если пользователь аутентифицирован в системе, и его куки установлены, то мы можем идентифицировать его в любом месте приложения. Например, по умолчанию у нас уже есть контроллер Home, а в нем метод Index. Изменим этот метод так, чтобы он возвращал логин аутентифицированного пользователя:
public string Index() { string result = "Вы не авторизованы"; if(User.Identity.IsAuthenticated) { result = "Ваш логин: " + User.Identity.Name; } return result; }
Вся информация о пользователе в Asp.Net MVC хранится в свойстве HttpContext.User
, которое представляет реализацию
интерфейса IPrincipal, который определен в пространстве имен System.Security.Principal
.
Интерфейс IPrincipal определяет свойство Identity
, которое хранит объект интерфейса IIdentity, который описывает текущего
пользователя.
Интерфейс IIdentity содержит следующие свойства:
AuthenticationType: тип аутентификации
IsAuthenticated: если пользователь аутентифицирован, то возвращает true
Name: имя пользователя в системе
Для определения аутентицирован ли пользователь, ASP.NET MVC принимает от браузера куки, и если пользователь аутентифицирован, у свойства
IIdentity.IsAuthenticated
устанавливается значение true
, а в свойство Name получает в качестве значения имя пользователя.