Как определить страницу входа, на которую вы хотите перенаправить неавторизованного пользователя? - PullRequest
2 голосов
/ 04 августа 2010

Я украсил свой контроллер атрибутом Authorize следующим образом:

[Authorize(Roles="ExecAdmin")]

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

Я понятия не имею, почему он это делает - или, возможно, он пытается перенаправить на какую-то другую страницу, на которой отображается LogOnUserControl.ASCX.Или, может быть, он ищет что-нибудь с «LogOn» в названии?(Хотя мое имя входа в систему называется LogOn.aspx ...)

Как мне узнать, на какую страницу перенаправлять?

ОБНОВЛЕНИЕ: У меня есть это в global.asax

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie == null || authCookie.Value == "")
    {
        return;
    }
    FormsAuthenticationTicket authTicket = null;
    try
    {
        authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    }
    catch
    {
        return;
    }
    string[] roles = authTicket.UserData.Split(new char[] { ';' });
    //Context.ClearError(); 
    if (Context.User != null)
    {
        Context.User = new System.Security.Principal.GenericPrincipal(Context.User.Identity, roles);
    }
}

... поскольку я использую нестандартный способ определения ролей;т. е. я не использую схему членства в ASP.NET (провайдеры ролей определены в web.config и т. д.).Вместо этого я устанавливаю роли следующим образом:

// get user's role
string role = rc.rolesRepository.GetUserType(rc.loginRepository.GetUserID(userName)).ToString();

// create encryption cookie
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
        1,
        userName,
        DateTime.Now,
        DateTime.Now.AddMinutes(120),
        createPersistentCookie,
        role //user's role 
        );

// add cookie to response stream
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);

System.Web.HttpCookie authCookie = new System.Web.HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
System.Web.HttpContext.Current.Response.Cookies.Add(authCookie);

(Это вызывается после того, как пользователь был проверен.)

Не уверен, как это может повлиять на все это, хотя ...

ОБНОВЛЕНИЕ: благодаря решению Роберта, вот как я решил это - расширьте класс AuthorizeAttribute:

public class AuthorizeAttributeWithMessage : AuthorizeAttribute
{
    private string _message = "";
    public string Message
    {
        get { 
            return _message; 
        }
        set { 
            _message = value;
        }
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            // user is logged in but wrong role or user:
            filterContext.Controller.TempData.Add("Message", Message);
        }
        base.HandleUnauthorizedRequest(filterContext);
    }
}

Затем в представлении LogOn:

<% 
    if (HttpContext.Current.Request.IsAuthenticated)
    {
        // authenticated users should not be here
        Response.Redirect("/Home/Index");
    }
%>

И ввид домашней страницы:

<% if (TempData != null && TempData.Count > 0 && TempData.ContainsKey("Message"))
   { %>
<div class="largewarningtext"><%= TempData["Message"]%></div>
<% } %>

И поверх затронутых контроллеров:

[AuthorizeAttributeWithMessage(Roles = "Consultant,ExecAdmin", Message = "You do not have access to the requested page")]

Преимущество ВСЕГДА заключается в перенаправлении любого аутентифицированного пользователя, который оказывается на Logon.aspx - аутентифицированных пользователейне должно быть там.Если в TempData есть сообщение, оно распечатает его на домашней странице;если нет, то он, по крайней мере, сделал перенаправление.

1 Ответ

3 голосов
/ 04 августа 2010

Страница входа настраивается в файле web.config.

Но вы, вероятно, уже знаете это.Реальная проблема здесь немного сложнее.Я полагаю, что вы столкнулись с чем-то очень интересным, поскольку страница входа практически не аутентифицирует пользователяОн не проверяет свою авторизацию для определенного ресурса (в данном случае, когда авторизация не проходит), поэтому это не должно перенаправлять на страницу входа.

Проверка AuthorizeAttribute исходного кода, вы должныполучить 401: Unauthorize Request ответ от сервера.Он не перенаправляет вас на страницу входа в систему (как я и ожидал в предыдущем абзаце, поскольку вход в систему слишком глупый для этого. Поэтому в вашем коде есть что-то еще, что не работает должным образом.

Редактировать

Как на этой странице говорится:

Если сайт настроен на использование проверки подлинности на основе форм ASP.NET, статус 401код заставляет браузер перенаправить пользователя на страницу входа в систему.

На основании этой информации он фактически формирует аутентификацию, которая видит этот 401 и перенаправляет на вход в систему (настроенный, как вы описали в комментарии).

Но. Было бы неплохо представить пользователю какое-то сообщение о том, почему они были перенаправлены на страницу входа в первую очередь. Никаких встроенных функций для этого нет ... Тем не менее, эти знания не решают вашу проблему, не так лиэто ...

Редактировать 2

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

Симплer one

  1. Напишите свой собственный атрибут авторизации (просто наследуйте от существующего и добавьте к нему дополнительное общедоступное свойство Message), где вы также можете предоставить некоторый видсообщение с объявлением атрибута, например ie.

    [AuthorizeWithMessage(Role = "ExecAdmin", Message = "You need at least ExecAdmin permissions to access requested resource."]
    
  2. Ваш атрибут авторизации должен заполнить TempData словарь предоставленным сообщением (проверьте документация о TempData, чтоЯ бы использовал в этом случае), а затем вызвал бы функциональность базового класса.

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

Сложный

  1. создайте свой собственный фильтр авторизации (не наследуя от оригинала) и предоставьте свое собственное перенаправление для некоторых представлений авторизации авторизации это будет служить логином в случае, если у пользователя недостаточно прав.

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

  3. пользовательские классы конфигурации, которые обслуживают эту конфигурацию пользовательской страницы входа.

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

Какой из них выбрать?

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

...