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

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core

Последнее обновление: 31.10.2015

Хотя рекомендуемым способом аутентификации в приложениях 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 получает в качестве значения имя пользователя.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850