2012-07-18 2 views
0

Я пытаюсь реализовать очень базовую схему входа для моего сайта MVC3. Если я правильно понял, вместо добавления разметки [Авторизовать] для каждого из моих классов контроллеров, я должен был бы просто реализовать глобальные настройки. Для достижения этой цели, я добавил следующее в global.asax:глобальная авторизация не работает - результаты отображаются пустой страницей

protected void Application_Start() 
{ 
    RegisterGlobalFilters(GlobalFilters.Filters); 
} 

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    filters.Add(new AuthorizeAttribute()); 

} 

и в моем WebConfig, я добавил:

<authentication mode="Forms"> 
    <forms loginUrl="~/Account/LogOn" timeout="2880" /> 
</authentication> 

Результат является то, что в результате страница полностью пустая. Глядя на URL-адрес, кажется, что mvc перенаправляется на мой логин, как ожидалось, кроме страницы пустым. Если я комментирую код в global.asax и просто размещаю разметку [Авторизовать] прямо в каждом контоллере, он работает так, как ожидалось.

В качестве обходного пути я внедрил то, что я прочитал в качестве лучшей практики MVC2, которая должна была создать класс BaseController: Controller, добавить к нему разметку [Authorize], а затем изменить присущие мне все мои контроллеры, чтобы не попасть из BaseController вместо Controller.

Это, кажется, работает достаточно хорошо.

Но почему реализация global.asax не работает?

ответ

3

Давайте посмотрим, что здесь происходит:

  1. Вы перемещаетесь к /
  2. Ваш глобальный AUTHORIZE атрибут пинки в и так как пользователь не прошел проверку подлинности, он перенаправляется на ~/Account/LogOn (как указано в вашем web.config файл) для аутентификации
  3. Ваш глобальный атрибут авторизации запускается, и поскольку пользователь не аутентифицирован, он перенаправляется на ~/Account/LogOn (как указано в файле вашего web.config) для аутентификации
  4. То же 3.
  5. То же 4.
  6. ...

Я думаю, вы получите точку. Действие LogOn должно быть исключено из проверки подлинности, иначе пользователь никогда не сможет получить доступ к вашему веб-сайту.

Поскольку вы применили атрибут Authorize глобально, это невозможно. Один из возможных способов - написать настраиваемый атрибут AuthorizeAttribute, который будет применяться глобально и который исключит это действие из проверки подлинности.

Таким образом, вы могли бы написать атрибут маркера:

public class AllowAnonymousAttribute : Attribute 
{ 
} 

и глобальный атрибут пользовательского авторизовать:

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     var exclude = ((AllowAnonymousAttribute[])filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), false)).Any(); 
     if (!exclude) 
     { 
      base.OnAuthorization(filterContext); 
     } 
    } 
} 

, который будет зарегистрирован:

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    filters.Add(new MyAuthorizeAttribute()); 
} 

Теперь все, что осталось вы должны украсить действия контроллера, которые вы хотите исключить из проверки подлинности, с помощью нашего маркера атрибут:

public class AccountController : Controller 
{ 
    [AllowAnonymous] 
    public ActionResult LogOn() 
    { 
     return View(); 
    } 

    [AllowAnonymous] 
    [HttpPost] 
    public ActionResult LogOn(LogOnModel model, string returnUrl) 
    { 
     ... 
    } 
} 
+0

Спасибо Дарин, это, безусловно, очень ясно и помогает. Очень признателен. – NewJoizey

+0

@NewJoizey, вам удалось заставить его работать? У вас еще есть вопросы по этому вопросу? –

+0

Дарин, спасибо за продолжение. Я упомянул в оригинальной записи, что я получил эту работу, используя обходное решение MVC2, которое было достаточно хорошим на данный момент. Я не мог понять «почему» за наблюдаемым поведением, но вы объяснили это в разделе «Давайте посмотрим, что здесь происходит». Теперь, когда я это понимаю, я, вероятно, оставлю его в будущем рефакторе для реализации. – NewJoizey