Pull to refresh

Руководство SimpleMembership в ASP.NET MVC 4

Reading time 6 min
Views 44K
С появлением ASP.NET MVC 4 и WebMatrix команда mvc стремиться сделать вещи проще для разработчика. Исходя из отзывов одно из направлений для улучшения была выбрана безопасность asp.net. 

ASP.NET MVC 4 шаблон проекта Internet добавил несколько новых очень полезных функций, которые построены с использованием SimpleMembership. SimpleMembership принес простую настройку ролей и пользователей, а также добавил поддержку OAuth. Однако новый провайдер не совместим с существующим ASP.NET Membership Provider.

В этом посте я расскажу о том, что такое SimpleMembership и как его использовать в проекте ASP.NET MVC 4.


Что такое SimpleMembership


  • SimpleMembership разработан для замены предыдущей версии ASP.NET Membership Provider (ASP.NET Role)
  • SimpleMembership решает те же самые задачи, но делает их проще для разработчика и приспосабливается к современным требованиям обеспечения безопасности
  • Контроллер AccountController в шаблоне проекта Interner ASP.NET MVC 4 требует SimpleMembership и не совместим с использованем старых версий
  • Досадная новость в том, что Web Site Administration Tool (WSAT) не совместим с SimpleMembership.

Система ASP.NET Membership System была представлена в 2005 году. Она была разработана для решения общих задач, таких как регистрации на сайте с использованием связки логина и пароля, хранения профиля в базе данных SQL Server. Также были добавлены механизмы расширения, позволяющие переопределить стандартную логику работы MembershipProvider и RoleProvider. 8 лет назад этот механизм справлялся со своей задачей, но сегодня это неудобный инструмент. Если профилю пользователя требуются дополнительные поля, то все они хранятся в одной колонке и для доступа требуют вызовов API соответствующего провайдера.

В ASP.NET WebPages и WebMatrix по новому представлены многие вещи, например движок представлений Razor и SimpleMembership.

Почему использование ASP.NET Membership не рекомендуется


Стандартный провайдер прекрасно работает, если выполняются следующие условия: вся информация будет храниться в полной версии базы данных SQL Server и то, что все необходимые данны представлены в виде набора атрибутов (UserName, Password, IsApproved, CreationDate...) и другая информация будет предоставлена используя Profile Provider. 

Требуется полный SQL Server по умолчанию


Большинство полнофункциональных провайдеров ASP.NET требуют полную версию SQL Server (т.к. опираются на работу хранимых процедур, на кеш SQL Server и другие возможности сервера). Кроме того, провайдеры по умолчанию не будут работать на SQL Azure.

Трудности работы с другой базой данных


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

Ориентация на модель Пользователь > Роль


Существующие поставщики данных строго ориентированы на эту модель, в которой пользователь имеет логин и пароль. Конечно, дополнительные сведения могут быть добавлены через API, но такая модель не подходит для OAuth (там пользователь не имеет пароля). 

Система ориентирована на роли не всегда будет уместна, бывает удобнее использовать модель прав доступа к отдельным объектам или действиям (Claims)

Также требуется жестка схема базы данных с большим количеством blob колонок.

SimpleMembership улучшенная система пользователей


SimpleMembership был разработан как раз для решения проблем, озвученных выше. 

Matthew Osborn в своей записи Using SimpleMembership With ASP.NET WebPages объясняет, что SimpleMembership разработан, чтобы легко интегрироваться с вашей базой данных.

SimpleMembership требует, чтобы было 2 колонки в таблице пользователей: «ID» и «UserName». Важная часть здесь, что эти колонки могут иметь любые названия.


Схема таблицы пользователи

Теперь необходимо рассказать об этом SimpleMembership: добавить строку подключения к базе данных.
<connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=ARCTURUS\SQLEXPRESS;Initial Catalog=MembershipDemoDB;Integrated Security=True;Pooling=False" providerName="System.Data.SqlClient" />
  </connectionStrings>

И определить инициализацию:
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "Id", "Name", autoCreateTables: true);


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

SimpleMembership создал таблицы

SimpleMembership работает со всей линейкой SQL Server (SQL Azure, SQL Server CE, SQL Server Express и LocalDB). Все реализовано как вызовы SQL, что здесь гораздо лучше, чем использование хранимых процедур.

Использование EntityFramework с Code First


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

[Table("Users")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Name { get; set; }

    public string Address { get; set; }
}


Теперь можно легко получить доступ к этому полю не используя сам провайдер, а напрямую из базы данных. Это позволяет принимать SimpleMembership как прослойку между базой данных и системой ASP.NET Membership.

Как он реализован я опущу, можно посмотреть в оригинальной записи SimpleMembership. Важно знать, что SimpleMembership унаследован от ExtendedMembershipProvider.

ASP.NET MVC 4 Internet template


В шаблоне по умолчанию реализован следующий механизм работы с SimpleMembership:

ASP.NET MVC 4 Internet template

  • AccountModel.cs описывает базовый аккаунт пользователя и включает атрибуты для базы данных
  • InitializeSimpleMembershipAttribute.cs как раз содержит информацию для инициализации провайдера: какую базу данных использовать, какие поля и другие настройки.
  • AccountController.cs содержит вызовы WebSecurity класс библиотеки WebMatrix.

WebSecurity работает с любым ExtendedMembershipProvider. По умолчанию используется SimpleMembershipProvider, однако можно реализовать свой.

Настройка SimpleMembership


Добавление SimpleMembership в существующий проект


Хотя этот провайдер работает по умолчанию в проекте с шаблоном ASP.NET MVC 4 Internet, некоторые (и я в том числе) создают проект с пустого шаблона. Необходимо добавить 2 ссылки: WebMatrix.Data и WebMatrix.WebData. Или установить эти библиотеки через NuGet с одноименными идентификаторами).

WebMatrix data

Теперь необходимо добавить провайдера и указать на использование WebMatrix

 <roleManager enabled="true" defaultProvider="SimpleRoleProvider">
      <providers>
        <clear />
        <add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider,WebMatrix.WebData" />
      </providers>
    </roleManager>
    <membership defaultProvider="SimpleMembershipProvider">
      <providers>
        <clear />
        <add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
      </providers>
    </membership>


Так как WSAT использовать не получится, есть 2 способа создания пользователей и ролей. Если используется модель EntityFramework Code First, удобно будет добавить Micragion с созданием пользователей по умолчанию:

public partial class AddDefaultUser : DbMigration
{
    public override void Up()
    {
        if (!WebSecurity.Initialized)
        {
            WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "Id", "UserName",
                autoCreateTables:
                    true);
        }

        var roles = (SimpleRoleProvider)Roles.Provider;
        var membership = (SimpleMembershipProvider)Membership.Provider;

        if (!roles.RoleExists("Admin"))
        {
            roles.CreateRole("Admin");
        }
        if (membership.GetUser("Admin", false) == null)
        {
            membership.CreateUserAndAccount("Admin", "SuperAdminPassword");
        }
        if (!roles.GetRolesForUser("Admin").Contains("Admin"))
        {
            roles.AddUsersToRoles(new[] { "Admin" }, new[] { "Admin" });
        }

    }

    public override void Down()
    {
        throw new NotImplementedException();
    }
}


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

Ссылки


Tags:
Hubs:
+12
Comments 11
Comments Comments 11

Articles