session becoming null in MVC AuthorizeAttribute

不问归期 提交于 2019-12-11 03:34:30

问题


I am using an AuthorizeAttribute to check that users have an over 18 age cookie set to access pages.

This works fine, but I am extending in slightly now. As all Views use this Attribute, I am using it to allow me to launch my site early. If uses add ?VIEWSITE=true to any URL, it will set a Session variable, and allow them access to the site. Otherwise, they get directed to a holding page.

This works fine first time the page runs. But, I am using output caching on the page, and the next time the page loads, my httpcontext.session is null?

I've added an "Order" varible to my attributes to ensure they execute in the correct order:

    [OfAge(Order = 1)]
    [OutputCache(Order = 2, Duration = 2000, VaryByParam = "categoryName")]

Snipit from my Attribute:

        protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        HttpRequestBase req = httpContext.Request;
        HttpResponseBase res = httpContext.Response;


        DateTime Live_Date = new DateTime(2011, 07, 01, 07, 0, 0);

        if (DateTime.Now > Live_Date || req.QueryString["VIEWSITE"] != null || httpContext.Session["VIEWSITE"] != null)
        {
            httpContext.Session["VIEWSITE"] = true;

Is there something I am missing here for me to be able to read/set session variables once a page is loaded from cache?

To be clear, it's httpContext.Session that is null, and not specifically httpContext.Session["VIEWSITE"]


回答1:


3 years down the line and I ran into a similar issue. Now I'm no expert but I believe each controller context call is unique in it's own space, thus httpContext.Session would be null on a new call.

My issue came in the form of a logged in AD user I wanted to store (with his custom application permissions) in a session variable. I'm extending on the AuthorizationAttribute too, but when this filter is applied to a controller action, httpContext is null even though the user was saved.

For people battling with the same issue, the way around this is to create a base controller where this user and it's session state is kept throughout other controllers (inheriting the base controller).

ex.

My Model:

public class LoggedInUser
    {
        public somenamespace.userclass UserProfile { get; set; }
        public List<somenamespace.user_permission_class> UserPermissions { get; set; }
    }

My Base Controller:

public class ControllerBase : Controller
    {
        private LoggedInUser _LoginUser;

        public LoggedInUser LoginUser
        {
            get 
            {
                if (_LoginUser != null)
                    return _LoginUser;

                if (Session["_LoginUser"] == null)
                    return null;

                return Session["_LoginUser"] as LoggedInUser;
            }
            set
            {
                _LoginUser = value;
                Session["_LoginUser"] = _LoginUser;
            }
        }

        public void PerformUserSetup(string sUsername) // sUsername for testing another user, otherwise User.Identity will be used.
        {
            sUsername = string.IsNullOrEmpty(sUsername) ? User.Identity.Name : sUsername;
            sUsername = (sUsername.IndexOf("\\") > 0) ? sUsername.Split('\\').ToArray()[1] : sUsername;

            // Todo - SQL conversion to stored procedure
            List<userclass> tmpUser = Root.Query<userclass>(/*sql to select user*/).ToList();

            List<user_permission_class> tmpUserpermissions = Root.Query<user_permission_class>(/*sql to select user permissions*/).ToList();

            LoggedInUser _LoginUser = new LoggedInUser();
            _LoginUser.UserProfile = tmpUser.First();
            _LoginUser.UserPermissions = tmpUserpermissions;

            LoginUser = _LoginUser;
        }

    }

My HomeController (standard with any MVC example) :

public class HomeController : ControllerBase
    {
        [Authorize] // Standard AuthorizeAttribute (AD test)
        public ActionResult Index()
        {
            if (Session["_LoginUser"] == null)
                PerformUserSetup("");

            return View();
        }
    }

My Custom permission checking filter which I'll use on any other controller action:

public class PermissionAuthorize : AuthorizeAttribute
    {
        private readonly string[] permissions;
        public PermissionAuthorize(params string[] perms)
        {
            this.permissions = perms;
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            bool auth = false;

            if (httpContext.Session["_LoginUser"] == null)
            {
                // Do nothing as auth is false.
            }
            else
            {
                // Check permissions and set auth = true if permission is valid.
                auth = true;
            }

            return auth;
        }

        /* not using
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var tmp = filterContext.HttpContext.Session;
        }
        */
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            // Todo - direct to "unauth page"
            base.HandleUnauthorizedRequest(filterContext);
        }
    }

Usage:

public class Some_OtherController : /*PossibleNamespace?.*/ControllerBase
    {

        [PermissionAuthorize("somepermission")] // This was a CRUD application thus 1 permission per actionresult
        public ActionResult ViewWhatever()
        {
            ....
        }
    }


来源:https://stackoverflow.com/questions/6531792/session-becoming-null-in-mvc-authorizeattribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!