Asp.net mvc 3 自定义授权属性不总是有效
我从以前的自定义授权属性中提取了代码,并得出以下结论:Asp.net mvc 3 自定义授权属性不总是有效,asp.net-mvc-3,attributes,filter,authorization,Asp.net Mvc 3,Attributes,Filter,Authorization,我从以前的自定义授权属性中提取了代码,并得出以下结论: public class PortalAuthorizeAttribute : AuthorizeAttribute { private WebSiteSession m_UserSession; protected WebSiteSession myUserSession { get { if (m_UserSession == null)
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不再有效,但它就像用户仍然能够访问页面一样
谢谢您的代码出现问题的原因是ASP.NET MVC 3可能会缓存操作筛选器的实例。这是一个: 在以前版本的ASP.NET MVC中,操作筛选器是根据创建的 除少数情况外,请求。这种行为从来都不是一种保证 行为,而不仅仅是实现细节和合同 过滤器被认为是无状态的。在ASP.NET MVC 3中,过滤器是 更积极地缓存。因此,任何自定义操作都会筛选 存储实例状态可能已损坏 由于您已将
m_UserSession
private字段缓存到操作筛选器中,因此它永远不会为null,并且您的测试不会通过
因此,以下是您可以继续操作的方法:
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
实例并将其存储到会话中,授权过滤器不应该这样做。认证成功后,您应该在登录
操作中执行此操作。授权筛选器仅用于检查用户是否有权访问操作。代码的问题源于ASP.NET MVC 3可能缓存操作筛选器的实例。这是一个:
在以前版本的ASP.NET MVC中,操作筛选器是根据创建的
除少数情况外,请求。这种行为从来都不是一种保证
行为,而不仅仅是实现细节和合同
过滤器被认为是无状态的。在ASP.NET MVC 3中,过滤器是
更积极地缓存。因此,任何自定义操作都会筛选
存储实例状态可能已损坏
由于您已将m_UserSession
private字段缓存到操作筛选器中,因此它永远不会为null,并且您的测试不会通过
因此,以下是您可以继续操作的方法:
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
实例并将其存储到会话中,授权过滤器不应该这样做。认证成功后,您应该在登录
操作中执行此操作。授权过滤器仅用于检查用户是否有权访问操作。非常感谢,这为我澄清了问题。我不知道。非常感谢,这为我澄清了这个问题。我不知道。