Аутентификация и авторизация пользователей в ASP.NET MVC

Каков наилучший метод авторизации и аутентификации пользователя в ASP.NET MVC?

Я вижу, что есть действительно два подхода:

  • Использовать встроенную систему авторизации ASP.NET.
  • Используйте настраиваемую систему с моими собственными таблицами User, Permission, UserGroup и т.д.

Я бы предпочел второй вариант, потому что Пользователь является частью моей модели домена (и у меня есть ноль опыт работы с встроенным компонентом ASP.NET), но я бы очень хотел услышать что люди делали в этой области.

Ответ 1

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

Некоторые статьи по теме:

http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx

http://www.asp.net/learn/videos/video-189.aspx

http://www.15seconds.com/issue/050216.htm

http://davidhayden.com/blog/dave/archive/2007/10/11/CreateCustomMembershipProviderASPNETWebsiteSecurity.aspx

Ответ 2

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

С полностью настраиваемой реализацией вы все равно можете использовать IPrincipal, IIdentity и FormsAuth. И действительно, насколько сложно сделать свою собственную страницу входа в систему и т.д.

Ответ 3

Самый простой способ - использовать имена пользователей asp.net в качестве имен ролей. Вы можете написать свой собственный атрибут authorizarion для авторизации:

public class CustomAuthorizationAttribute:AuthorizeAttribute
{
    public CustomAuthorizationAttribute():base()
    {
        Users = "registereduser";
    }
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        //You must check if the user has logged in and return true if he did that.
        return (bool)(httpContext.Session["started"]??false); 

    }
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.HttpContext.Response.Redirect("SessionManagement/Index/?returningURL=" + 
            filterContext.HttpContext.Server.UrlEncode(filterContext.HttpContext.Request.Url.ToString()));

    }

}

Код должен обрабатывать AuthorizeCore для возврата true, если пользователь запустил сеанс, а HandleUnauthorizedRequest перенаправляет пользователя на страницу входа (необязательно, вы можете прикрепить возвращаемый URL-адрес).

В методах контроллера, которым требуется авторизация, установите для них атрибут:

public class SecretPageController {
    [CustomAuthorizationAttribute]
    ActionResult Index() {
        //Method that requires authorization
        return View();
    }

}

Также установите метод авторизации в "Формы" в веб-конфигурации.

Web.config:

  <authentication>
      <forms timeout="120"></forms>
  </authentication>

Контроллер:

public SessionManagementController:Controller {
    public ActionResult Index(string returningURL)
    {
        return View("Index", new SessionModel() { ReturningURL = returningURL});
    }
    [HttpPost]        
    public ActionResult Index(SessionModel mod)
    {
        if (UserAuthenticated(mod.UserName, mod.Password))
        {
            FormsAuthentication.SetAuthCookie("registereduser", false);
            if (mod.UrlRetorno != null)
            {
                return Redirect(mod.ReturningURL);                    
            }
            return RedirectToAction("Index", "StartPage");
        }
        mod.Error = "Wrong User Name or Password";
        return View(mod);
    }
    bool UserAuthenticated(string userName, string password) {
       //Write here the authentication code (it can be from a database, predefined users,, etc)
        return true;
    }

    public ActionResult FinishSession()
    {
        HttpContext.Session.Clear();//Clear the session information
        FormsAuthentication.SignOut();
        return View(new NotificacionModel() { Message = "Session Finished", URL = Request.Url.ToString() });
    }

}

В контроллере, когда пользователь вводит свое имя пользователя и пароль, установите cookie проверки подлинности форм в TRUE (FormsAuthentication.SetAuthCookie( "registereduser", true)), сигнализируя имя пользователя (зарегистрированный пользователь в примере) для аутентификации, Затем пользователь подписывается, сообщает ASP.NET, чтобы он вызывал FormsAuthentication.SignOut().

Модель:

class SessionModel {
    public string UserName {get;set;}
    public string Password {get;set;}
    public string Error {get;set;}
}  

Используйте модель для хранения пользовательских данных.

Вид (который представляет тип SessionModel):

        <div class="editor-label">
            <%: Html.LabelFor(model => model.UserName) %>
        </div>
        <div class="editor-field">
            <%: Html.TextBoxFor(model => model.UserName) %>
            <%: Html.ValidationMessageFor(model => model.UserName) %>
        </div>

        <div class="editor-label">
            <%: Html.LabelFor(model => model.Password) %>
        </div>
        <div class="editor-field">
            <%: Html.TextBoxFor(model => model.Password) %>
            <%: Html.ValidationMessageFor(model => model.Password) %>
        </div>
        <div class="field-validation-error"><%:Model==null?"":Model.Error??"" %></div>
        <%:Html.HiddenFor(model=>model.ReturningURL) %>
        <input type="submit" value="Log In" />

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

Надеюсь, это поможет (мне пришлось перевести код, поэтому я не уверен, что он на 100% прав).

Ответ 4

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

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

Ответ 5

Вам может быть интересен RPX для бесплатного API для аутентификации ваших пользователей

http://blog.maartenballiauw.be/post/2009/07/27/Authenticating-users-with-RPXNow-(in-ASPNET-MVC).aspx

Попробуйте стартовый комплект для членства в ASP.NET MVC для административного API

Скриншоты

http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/

Настройки старых мест (исторические)

http://mvcmembership.codeplex.com/SourceControl/list/changesets

Новое местоположение:

http://github.com/TroyGoode/MembershipStarterKit

Ответ 6

Это четвертый подход. Используя классы безопасности веб-матрицы, вы можете использовать простой поставщик членства, который может использовать EF, чтобы пользователи и роли могли быть частью вашей модели домена, но также и частью помощники MVC IPrincipal и IIdentity MVC.

Я создал пример проекта Github, чтобы узнать, как это можно использовать с автоматической саморегистрации и регистрацией/паролем электронной почты reset, а также как.