ASP.Net MVC 3 странное поведение сессии - PullRequest
5 голосов
/ 04 июня 2011

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

Я заблудился относительно того, почему приложение начинает новый сеанс в этот момент?Я не поручил это сделать.Кто-нибудь может порекомендовать решения, чтобы остановить это поведение и заставить его сохранить старый сеанс?

Спасибо.

ОБНОВЛЕНИЕ - Некоторые код:

Обратите внимание, что сеанс, кажется, завершается сразу после ответа на отправленную Create форму

Контроллер CMS, который использует собственный атрибут Autorize, называемый "RDAutorize" для всех действий:

[RDAuthorize]
public class PhotoCMSController : Controller
{

public ActionResult Create()
{
    /* Code omitted: set up a newPhoto object with default state */
    /* Display view containing form to upload photo and set title etc. */
    return View("../Views/PhotoCMS/Create", newPhoto);
}

[HttpPost]
public ContentResult Upload(int pPhotoId)
{   
    /* Code ommited: receive and store image file which was posted
     via an iframe on the Create view */  
    string thumbnail = "<img src='/path/to/thumb.jpg' />";
    return Content(thumbnail);
}

[HttpPost]
public ActionResult Create(string pPhotoTitle, string pCaption etc...)
{
     /*Code omitted: receive the rest of the photo data and save
      it along with a reference to the image file which was uploaded
      previously via the Upload action above.*/

      /* Display view showing list of all photo records created */
      return View("../Views/PhotoCMS/Index", qAllPhotos.ToList<Photo>());

      /* **Note: after this view is returned the Session_End() method fires in 
       the Global.asax.cs file i.e. this seems to be where the session is
       being lost** */
}

}/*End of CMS Controller*/

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

public class RDAuthorize : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Boolean authorized = Convert.ToBoolean(
            HttpContext.Current.Session["UserIsAuthorized"]
        );

        if (!authorized) {
            /* Not logged in so send user to the login page */
            filterContext.HttpContext.Response.Redirect("/Login/Login");
        }
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext) {}
    public override void OnResultExecuting(ResultExecutingContext filterContext) {}
    public override void OnResultExecuted(ResultExecutedContext filterContext) {}

}/*End of Authorize Action Filter*/

Контроллер входа в систему:

public class LoginController : Controller
{
    private PhotoDBContext _db = new PhotoDBContext();

    public ActionResult Login()
    {
        string viewName = "";
        Boolean authorized = Convert.ToBoolean(Session["UserIsAuthorized"]);
        if (authorized)
        {
            viewName = "../Views/Index";
        }
        else
        {
            viewName = "../Views/Login/Login";
        }
        return View(viewName);
    }

    [HttpPost]
    public ActionResult Login(string pUsername, string pPassword)
    {
        string viewName = "";
        List<Photo> model = new List<Photo>();

        var qUsers = from u in _db.Users
                select u;

        foreach (User user in qUsers.ToList<User>())
        {
            /* If authorized goto CMS pages */
            if (pUsername == user.Username && pPassword == user.Password)
            {
                Session["UserIsAuthorized"] = true;
                var qPhotos = from p in _db.Photos
                              where p.IsNew == false
                              select p;

                model = qPhotos.ToList<Photo>();
                viewName = "../Views/PhotoCMS/Index";
                break;
            }
        }

        return View(viewName, model);

    }

}/* End of Login controller */

Ответы [ 5 ]

2 голосов
/ 09 июня 2011

Оказывается, все приложение ASP.Net перезапускалось, потому что в процессе загрузки фотографий я сохранял файл изображения во временной папке, а затем удалял каталог после перемещения файла в постоянное место.Очевидно, его поведение по умолчанию для ASP.Net перезапускается, если каталог на веб-сайте удаляется.Я нашел эту запись , которая описывает проблему и предлагает решение, посредством которого следующий код добавляется в файл Global.asax.cs.Реализация этого решения устранила проблему.Исправление применяется путем вызова FixAppDomainRestartWhenTouchingFiles () из события Application_Start ():

    protected void Application_Start()
    {
        FixAppDomainRestartWhenTouchingFiles();
    }

    private void FixAppDomainRestartWhenTouchingFiles()
    {
        if (GetCurrentTrustLevel() == AspNetHostingPermissionLevel.Unrestricted)
        {
            /* 
             From: http://www.aaronblake.co.uk/blog/2009/09/28/bug-fix-application-restarts-on-directory-delete-in-asp-net/
             FIX disable AppDomain restart when deleting subdirectory
             This code will turn off monitoring from the root website directory.
             Monitoring of Bin, App_Themes and other folders will still be 
             operational, so updated DLLs will still auto deploy.
            */

            PropertyInfo p = typeof(HttpRuntime).GetProperty(
                "FileChangesMonitor", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
            object o = p.GetValue(null, null);
            FieldInfo f = o.GetType().GetField(
                "_dirMonSubdirs", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase);
            object monitor = f.GetValue(o);
            MethodInfo m = monitor.GetType().GetMethod(
                "StopMonitoring", BindingFlags.Instance | BindingFlags.NonPublic);
            m.Invoke(monitor, new object[] { });
        }
    }

    private AspNetHostingPermissionLevel GetCurrentTrustLevel()
    {
        foreach (AspNetHostingPermissionLevel trustLevel in
            new AspNetHostingPermissionLevel[] {
                AspNetHostingPermissionLevel.Unrestricted,
                AspNetHostingPermissionLevel.High,
                AspNetHostingPermissionLevel.Medium,
                AspNetHostingPermissionLevel.Low,
                AspNetHostingPermissionLevel.Minimal }
            )
        {
            try
            {
                new AspNetHostingPermission(trustLevel).Demand();
            }
            catch (System.Security.SecurityException)
            {
                continue;
            }

            return trustLevel;
        }

        return AspNetHostingPermissionLevel.None;
    }
0 голосов
/ 10 июля 2012

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

public class KeepSessionAlive : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if(filterContext.HttpContext.Session != null)
        {
            filterContext.HttpContext.Session["HeartBeat"] = DateTime.Now.ToShortDateString();
        }
}

    public void OnActionExecuted(ActionExecutedContext filterContext) { }

}

И в global.asax:

protected override void AddCustomGlobalFilters(GlobalFilterCollection filters)
{
   filters.Add(new KeepSessionAlive());
}

Возможно, это не лучшее решение, но оно помогло мне в моем случае.

0 голосов
/ 04 июня 2011

Содержит ли действие контроллера, которое вы публикуете, какой-либо атрибут [Авторизация].Вам нужно опубликовать код.

0 голосов
/ 04 июня 2011
  1. Убедитесь, что новый сеанс действительно запускается каждый раз.Проверьте вывод трассировки для идентификатора сеанса пользователя, чтобы убедиться, что он действительно изменился.
  2. Убедитесь, что отправляемый файл cookie действительно устанавливается и отправляется.(называется ASPsessionIDSOMETHING) и, если это отправляется браузером.Загрузите инструмент Fiddler, чтобы легко проверять файлы cookie (установите заголовок файла cookie, исходящий от сервера, и запросите файлы cookie, возвращающиеся на сервер из браузера. Убедитесь, что ваш браузер принимает файл cookie, и вы не говорите ... отключите файлы cookie.
  3. Если идентификатор вашего сеанса меняется при каждом запросе, то ваш сеанс не устанавливается должным образом с первого раза, установите точку останова для этого кода, если вы этого еще не сделали.
  4. Вы можете войти, когдарабочий процесс сбрасывается - убедитесь, что это не так. см. http://www.microsoft.com/technet/prodtechnol/windowsserver2003/library/IIS/87892589-4eda-4003-b4ac-3879eac4bf48.mspx
0 голосов
/ 04 июня 2011

Поскольку сеансы связаны с файлами cookie, они доступны для определенного домена.

Распространенной ошибкой является запрос переменной сеанса в том же приложении, когда домен изменился (т.е. перенаправление на поддомен).

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