【问题标题】:MVC3 Session in Custom Authorization Filter Strange Behaviour自定义授权过滤器奇怪行为中的 MVC3 会话
【发布时间】:2011-08-27 12:06:01
【问题描述】:

我们最近从 mvc2 升级到 mvc3,我们的自定义授权过滤器之一(位于 ActionResult 方法上)似乎只构建了一次,但执行了多次。我们知道这是因为过滤器包含一个错误列表(在构造函数中是新的),并且错误被添加到 AuthorizeCore。

自定义过滤器用于检查用户对特定操作方法的访问权限(并且他们的级别存储在会话中)

一些代码:

public class SecurityAttribute : AuthorizeAttribute
    {
        public int MinAccessLevel = 1;
        public string UserRole = String.Empty;
        private List<string> _errors;

        public SecurityAttribute()
        {
            _errors = new List<string>();
        }

        public override void OnAuthorization(AuthorizationContext filterContext)
        {

            if (WebSession.AccessLevel < MinAccessLevel)
                _errors.Add("Your access level(" + WebSession.AccessLevel + ") must be " + MinAccessLevel + " or higher");

            if (!String.IsNullOrEmpty(UserRole) && WebSession.UserRole != UserRole)
                _errors.Add("Your User Role must be " + UserRole);

            if (_errors.Any())
            {
                var viewResult = new ViewResult() { ViewName = "SecurityError"};
                viewResult.ViewData.Model = new SecurityErrorViewModel(){Errors = _errors};
                filterContext.Result = viewResult;
            }
        }
    }

这将像下面这样使用:

[HttpPost, Security(MinAccessLevel = 4)]
public ActionResult Complete(int id, string userid){}

视图上的输出(以随机间隔)看起来像这样(在项目符号列表中)

  • 您的访问级别 (6) 必须为 4 或更高
  • 您的访问级别 (6) 必须为 4 或更高
  • 您的访问级别 (6) 必须为 4 或更高
  • 您的访问级别 (6) 必须为 4 或更高

此问题仅在我们升级到 mvc3 后发生,因此我正在寻找任何线索来说明为什么会发生这种情况,或进行适当的修复。我已经阅读了有关无会话状态控制器等的各种 SO 帖子,但这似乎不适合我们面临的情况

谢谢,马克

【问题讨论】:

    标签: asp.net-mvc-3 session action-filter


    【解决方案1】:

    根据 MVC 3 发行说明:

    在以前的 ASP.NET MVC 版本中,操作过滤器是基于每个请求创建的,但在少数情况下除外。这种行为从来都不是有保证的行为,而只是一个实现细节,过滤器的约定是认为它们是无状态的。在 ASP.NET MVC 3 中,过滤器被更积极地缓存。因此,任何不正确地存储实例状态的自定义操作过滤器都可能被破坏。

    因此,您不应将错误存储在操作过滤器中。直接在 OnAuthorization 方法中新建列表,或者如果您需要在其他地方访问它们,您可以将它们存储在 HttpContext.Items 或 Session 中。

    【讨论】:

    • 感谢上述 - 主要问题是我们有一个访问级别,看起来它是从第一个请求(由某个用户)缓存的,然后任何具有有效访问级别的人都有来自第一个请求的信息
    • 抱歉,我是个笨蛋——我明白你的意思,Errors 变量已在构造函数中初始化并被缓存。当未经授权的用户进入 mvc3 缓存时缓存了错误变量,我的 _errors.Any() 调用将始终返回它的第一个实例(至少包含一个错误!)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    相关资源
    最近更新 更多