ASP.NET MVC Создание олицетворенного пользователя - PullRequest
4 голосов
/ 30 марта 2010

У меня есть приложение MVC, где у меня есть класс User, и пользователь также может выдавать себя за другого пользователя (только для пользователей Admin).

Итак, у меня есть следующий код, который аутентифицирует запрос и создает мою версию класса User.

Затем он пытается получить олицетворенного пользователя из объекта Session, но Session недоступен в этом методе в global.asax.

Надеюсь, это имеет смысл.

Как еще я мог это сделать?

У меня вопрос, наверное, в какой точке методов global.asax вы получаете доступ к объекту Session для каждого запроса?

protected void Application_OnAuthenticateRequest(object sender, EventArgs e)
{
    IMylesterService service = ObjectFactory.GetInstance<IMylesterService>();

    if (Context.User != null)
    {
        if (Context.User.Identity.IsAuthenticated)
        {
            User user = service.GetUser(Context.User.Identity.Name);
            if (user == null)
                throw new ApplicationException("Context.user.Identity.name is not a recognized user");

            User impersonatedUser = (User)this.Session["ImpersonatedUser"];
            if (impersonatedUser == null)
                user.ImpersonatedUser = user;
            else
                user.ImpersonatedUser = impersonatedUser;

            System.Threading.Thread.CurrentPrincipal = Context.User = user;
            return;
        }
    }
    User guest = service.GetGuestUser();
    guest.ImpersonatedUser = guest;

    System.Threading.Thread.CurrentPrincipal = Context.User = guest;
}

Ответы [ 3 ]

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

Попробуйте создать фильтр авторизации:

public class CustomAuthorizationFilter : AuthorizeAttribute
{
    protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
    {
        // perform your authorization here
        // full access to HttpContext and session
    }
}

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

0 голосов
/ 31 марта 2010

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

    protected void Application_AcquireRequestState(Object sender, EventArgs e)
    {
        if (Request.IsAuthenticated && Context.Session != null)
        {
            // access Context.Session
        }
    }

Это часто срабатывает, и текущий контекст не всегда имеет допустимый объект сеанса, поэтому проверка.

РЕДАКТИРОВАТЬ : пришлось добавить проверку для IsAuthenticated тоже - получал нулевую ошибку при выходе из системы. Отлично работает сейчас.

0 голосов
/ 31 марта 2010

Сессия не будет доступна во время AuthenticateRequest: вам нужно будет пометить необходимую информацию в Identity.userData; так, например, если вы используете проверку подлинности с помощью форм, выполните следующие действия:

void Application_AuthenticateRequest(object sender, EventArgs e)
{
   if (Context.User != null)
   {
     if (Context.User.Identity.IsAuthenticated)
     {
       // retrieve the value 
       var id = (FormsIdentity)Context.User.Identity;
       var myvalue = id.Ticket.UserData; // "Here you are"
     }
   }
}

Для входа в систему с помощью форм вам необходимо написать собственный файл cookie: MVC -> class FormsAuthenticationService: IFormsAuthenticationService

public static void SetAuthenticationCookie(HttpContextBase context, FormsAuthenticationTicket ticket)
{
    var cookie = new HttpCookie(FormsAuthentication.FormsCookieName)
       {
          Value = FormsAuthentication.Encrypt(ticket),
          Secure = FormsAuthentication.RequireSSL,
          Domain = FormsAuthentication.CookieDomain,
          HttpOnly = true,
          Expires = DateTime.Now.AddMinutes(15)
       };

    if (!context.Request.IsSecureConnection && FormsAuthentication.RequireSSL)
    {
        throw new HttpException("Ticket requires SSL.");
    }
    context.Response.Cookies.Add(cookie);
}
public static FormsAuthenticationTicket CreateTicket(HttpContextBase context, string emailAddress, string userData, bool persist)
{
    return new FormsAuthenticationTicket(1, emailAddress, DateTime.Now, DateTime.Now.AddMinutes(15), persist, userData, FormsAuthentication.FormsCookiePath);
}

Наконец, при входе в систему вы теперь должны создать требуемый билет, вызвав CreateTicket (...), а затем выписать его с помощью SetAuthenticationCookie (...).

public void SignIn(string userName, string password)
{
    if(CheckUserValid(userName,password, out string email))
    {
        var ticket = CreateTicket(email, "Here you are", true);
        SetAuthenticationCookie(HttpContext.Current.Base(), ticket);
    }
}

Я никогда не использовал его, но предположим, что состояние сеанса назначается во время AcquireRequestState:

public void Init(HttpApplication context)
{
    context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...