【问题标题】:session becoming null in MVC AuthorizeAttribute会话在 MVC AuthorizeAttribute 中变为空
【发布时间】:2011-06-30 08:08:17
【问题描述】:

我正在使用 AuthorizeAttribute 来检查用户是否设置了超过 18 岁的 cookie 来访问页面。

这工作正常,但我现在稍微扩展。 由于所有视图都使用此属性,因此我使用它来允许我尽早启动我的网站。 如果使用添加 ?VIEWSITE=true 到任何 URL,它将设置一个 Session 变量,并允许他们访问该站点。否则,他们会被引导到一个保留页面。

这在页面第一次运行时运行良好。但是,我在页面上使用了输出缓存,下次页面加载时,我的 httpcontext.session 为空?

我在属性中添加了一个“Order”变量,以确保它们以正确的顺序执行:

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

我的属性截图:

        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;

从缓存加载页面后,我在这里是否缺少一些东西以便我能够读取/设置会话变量?

需要明确的是,为空的是 httpContext.Session,而不是具体的 httpContext.Session["VIEWSITE"]

【问题讨论】:

    标签: model-view-controller asp.net-mvc-3 outputcache authorize-attribute


    【解决方案1】:

    3 年后,我遇到了类似的问题。现在我不是专家,但我相信每个控制器上下文调用在它自己的空间中都是唯一的,因此 httpContext.Session 在新调用中将为空。

    我的问题是以登录 AD 用户的形式出现的,我想在会话变量中存储(使用他的自定义应用程序权限)。我也在扩展 AuthorizationAttribute,但是当这个过滤器应用于控制器操作时,即使用户被保存,httpContext 也为空。

    对于遇到相同问题的人,解决此问题的方法是创建一个基本控制器,在该控制器中,此用户及其会话状态在其他控制器中保持不变(继承基本控制器)。

    例如

    我的模特:

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

    我的基本控制器:

    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;
            }
    
        }
    

    我的 HomeController(任何 MVC 示例的标准):

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

    我将用于任何其他控制器操作的自定义权限检查过滤器:

    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);
            }
        }
    

    用法:

    public class Some_OtherController : /*PossibleNamespace?.*/ControllerBase
        {
    
            [PermissionAuthorize("somepermission")] // This was a CRUD application thus 1 permission per actionresult
            public ActionResult ViewWhatever()
            {
                ....
            }
        }
    

    【讨论】:

    • 除此之外,这篇文章对我也有帮助:stackoverflow.com/questions/5447611/…。在 HttpSessionStateBase(包装器)和 System.Web.SessionState.HttpSessionState(asp.net 1 时代的底层核心)中添加了 MVC 语义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-11
    • 2012-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多