2012-03-07 147 views
1

我从一个自定义的授权属性所采取的代码,并提出了这一点:自定义授权属性并不总是工作

public class PortalAuthorizeAttribute : AuthorizeAttribute 
{ 
    private WebSiteSession m_UserSession; 
    protected WebSiteSession myUserSession 
    { 
     get 
     { 
      if (m_UserSession == null) 
       try { m_UserSession = (WebSiteSession)HttpContext.Current.Session["UserSession"]; } 
       catch 
       { 
        m_UserSession = new WebSiteSession(); 
        HttpContext.Current.Session["UserSession"] = m_UserSession; 
       } 
      return m_UserSession; 
     } 
    } 

    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (filterContext.Result is HttpUnauthorizedResult || myUserSession == null || !myUserSession.IsAuthenticated || myUserSession.AdvertiserId == 0) 
     { 
      filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary 
      { 
        { "client", filterContext.RouteData.Values["client"] }, 
        { "controller", "Account" }, 
        { "action", "Login" }, 
        { "returnUrl", filterContext.HttpContext.Request.RawUrl } 
      }); 
     } 
    } 
} 

我从一个更大的项目中工作,所以我们从更高的命名空间让我们的会议。如果我注销或者我没有授权(重定向到区域登录页面),但它似乎如果我闲置(会话超时??)它将仍然按照我的授权行事,但不会有任何凭据附加到会话。所以它仍然认为我有效登录,但我不是。我在过滤器检查中忘记了什么吗?该Cookie不再有效,但它仍像用户仍能访问该页面。

感谢

回答

1

与您的代码的问题,从一个事实,即ASP.NET MVC 3可以缓存的作用过滤器实例茎。这是breaking changes之一:

在ASP.NET MVC的早期版本中,动作过滤器每 请求创建除了在少数情况下。这种行为从来没有保证 的行为,但只是一个实施细节和合同 过滤器是认为他们无国籍。在ASP.NET MVC 3中,更积极地缓存过滤器 。因此,任何自定义操作筛选器不正确地存储实例状态可能会被破坏。

既然你已经缓存在m_UserSession私人领域进入行动过滤器,它从来没有空,你的测试没有通过。

所以,这里是你如何能继续:

public class PortalAuthorizeAttribute : AuthorizeAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     var userSession = filterContext.HttpContext.Session["UserSession"] as WebSiteSession; 
     if (userSession == null || !userSession.IsAuthenticated || userSession.AdvertiserId == 0) 
     { 
      filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary 
      { 
       { "client", filterContext.RouteData.Values["client"] }, 
       { "controller", "Account" }, 
       { "action", "Login" }, 
       { "returnUrl", filterContext.HttpContext.Request.RawUrl } 
      }); 
     } 
    } 
} 

至于创建和存储新WebSiteSession实例到会话中,这不是东西,授权过滤器应该做的。在成功验证后,您应该在Login操作中执行此操作。授权过滤器仅用于检查用户是否有权访问该操作。

+0

非常感谢,这已经为我澄清了这个问题。我不知道它缓存了。 – Darren 2012-03-07 17:51:22