Можно ли создать систему входа в систему с ASP.NET MVC, но не использовать MembershipProvider? - PullRequest
58 голосов
/ 17 сентября 2009

У меня есть существующая база данных с таблицей пользователей, и мы планируем взять базу данных и использовать ее для новой системы, встроенной в ASP.NET MVC. Однако я не уверен, могу ли я создать систему входа в систему, в которой не используется встроенный контроллер учетных записей или обычный поставщик членства, чтобы мы все еще могли использовать существующую структуру таблиц.

Итак, мой вопрос, возможно ли это? Или даже особенно сложно это сделать?

Какой самый распространенный и самый простой способ ведения дел?

Ответы [ 4 ]

81 голосов
/ 17 сентября 2009

У меня было точно такое же требование. У меня была своя собственная схема пользователя и роли, и я не хотел переходить на схему членства asp.net, но я хотел использовать фильтры действий ASP.NET MVC для проверки авторизации и ролей. Я должен был изрядно покопаться, чтобы выяснить, что именно нужно сделать, но в конце концов это было относительно легко. Я избавлю тебя от неприятностей и расскажу, что я сделал.

1) Я создал класс, производный от System.Web.Security.MembershipProvider. MembershipProvider имеет массу абстрактных методов для всех видов функций, связанных с аутентификацией, таких как забытый пароль, смена пароля, создание нового пользователя и т. Д. Все, что мне нужно, - это возможность аутентификации по моей собственной схеме. Так что мой класс содержал в основном пустые переопределения. Я только что переопределил ValidateUser:

public override bool ValidateUser(string username, string password)
{
    if (string.IsNullOrWhiteSpace(username) ||
        string.IsNullOrWhiteSpace(password))
      return false;

    string hash = EncryptPassword(password);
    User user = _repository.GetByUserName(username);
    if (user == null) return false;

    return user.Password == hash;
}

2) Я создал класс, производный от System.Web.Security.RoleProvider. Опять же, у меня были пустые реализации для всего того, что мне не нужно, например, создание и смена ролей. Я просто переопределил два метода:

public override string[] GetRolesForUser(string username)
{
    User user = _repository.GetByUserName(username);
    string[] roles = new string[user.Role.Rights.Count + 1];
    roles[0] = user.Role.Description;
    int idx = 0;
    foreach (Right right in user.Role.Rights)
        roles[++idx] = right.Description;
    return roles;
}

public override bool IsUserInRole(string username, string roleName)
{
    User user = _repository.GetByUserName(username);
    if(user!=null)
        return user.IsInRole(roleName);
    else
        return false;
}

3) Затем я подключил эти два класса в свой web.config:

<membership defaultProvider="FirstlookMemberProvider" userIsOnlineTimeWindow="15">
  <providers>
    <clear/>
    <add name="FirstlookMemberProvider" type="FirstlookAdmin.DomainEntities.FirstlookMemberProvider, FirstlookAdmin" />
  </providers>
</membership>
<roleManager defaultProvider="FirstlookRoleProvider" enabled="true" cacheRolesInCookie="true">
  <providers>
    <clear/>
    <add name="FirstlookRoleProvider" type="FirstlookAdmin.DomainEntities.FirstlookRoleProvider, FirstlookAdmin" />
  </providers>
</roleManager>

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

11 голосов
/ 17 сентября 2009

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

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

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

Если вам необходимо реализовать пользовательский атрибут MVC, то вам следует ввести подтип AuthorizeAttribute и переопределить AuthorizeCore, внимательно следя за комментариями в исходном коде относительно безопасности потоков.

10 голосов
/ 17 сентября 2009

Конечно можно. Я сделал это для своих проектов, полностью игнорируя поставщика членства.

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

Для атрибута вы можете определить любые параметры, необходимые для поддержки вашей модели аутентификации / авторизации.

public class AuthorizationAttribute : ActionFilterAttribute, IActionFilter
{
   public MyRole UserRole { get; set; }

   void IActionFilter.OnActionExecuting (ActionExecutedContext filterContext)
   {
       // Decide whether to grant access to the action or redirect away
   }
}

[Authorization (UserRole = MyRole.All)]
public class UserController : Controller
{
    [Authorization (UserRole = MyRole.Admin)]
    public ActionResult Delete ()
    {
    }
}

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

Объяснение проблемы: Совет ASP.NET MVC № 40. Не кэшируйте страницы, требующие авторизации

1 голос
/ 17 сентября 2009

У вас есть как минимум две возможности

  • атрибут фильтра настраиваемого действия, который обеспечит вашу проверку авторизации
  • пользовательский IHttpModule, который заполнит все необходимые данные для вошедшего в систему пользователя (включая роли), и вы сможете использовать существующие фильтры действий

Второй вариант можно использовать и с обычными веб-формами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...