asp.net-mvc-3 – 为什么在使用Azure缓存(.NET MVC3应用程序)时
使用Windows Azure的Microsoft.Web.DistributedCache.DistributedCacheOutputCacheProvider作为MVC3应用程序的outputCache提供程序。以下是相关的操作方法:
[ActionName("sample-cached-page")] [OutputCache(Duration = 300,VaryByCustom = "User",Location = OutputCacheLocation.Server)] [Authorize(Users = "me@mydomain.tld,another@otherdomain.tld")] public virtual ActionResult SampleCachedPage() { return View(); } 从Web浏览器加载此视图时,我会收到以下异常: System.Configuration.Provider.ProviderException: When using a custom output cache provider like 'DistributedCache',only the following expiration policies and cache features are supported: file dependencies,absolute expirations,static validation callbacks and static substitution callbacks. System.Configuration.Provider.ProviderException: When using a custom output cache provider like 'DistributedCache',only the following expiration policies and cache features are supported: file dependencies,static validation callbacks and static substitution callbacks. at System.Web.Caching.OutputCache.InsertResponse(String cachedVaryKey,CachedVary cachedVary,String rawResponseKey,CachedRawResponse rawResponse,CacheDependency dependencies,DateTime absExp,TimeSpan slidingExp) at System.Web.Caching.OutputCacheModule.OnLeave(Object source,EventArgs eventArgs) at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean& completedSynchronously) 如果我删除[Authorize]属性,视图将按预期缓存。这是否意味着我不能将[OutputCache]放在必须具有[授权]的操作方法上?或者,是否需要使用为缓存使用静态验证回调方法的自定义实现来覆盖AuthorizeAttribute? 更新1 在Evan的答案之后,我在IIS Express(Azure外)测试了上述动作方法。以下是对OutputCache属性的VaryByCustom =“User”属性的覆盖: public override string GetVaryByCustomString(HttpContext context,string custom) { return "User".Equals(custom,StringComparison.OrdinalIgnoreCase) ? Thread.CurrentPrincipal.Identity.Name : base.GetVaryByCustomString(context,custom); } 当我访问示例缓存页面为me@mydomain.tld时,该页面的输出被缓存,视图显示“此页被缓存在12/31/2011 11:06:12 AM(UTC)”。如果我以login@otherdomain.tld身份登录并登录,请访问该页面,显示“此页面缓存于12/31/2011 11:06:38 AM(UTC)”。重新登录为me@mydomain.tld并重新访问页面将导致缓存显示“此页面被缓存在12/31/2011 11:06:12 AM(UTC)”。进一步登录/尝试显示不同的输出正在被缓存根据用户返回。 这导致我相信输出是基于用户单独缓存的,这是我的VaryByCustom =“用户”设置&覆盖。问题是它不适用于Azure的分布式缓存提供程序。埃文,你是否回答只有缓存公开的内容呢还是站立的? 更新2 我挖出了源代码,发现开箱即用的AuthorizeAttribute实际上有一个非静态的验证回调函数。以下是OnAuthorization的摘录: if (AuthorizeCore(filterContext.HttpContext)) { // ** IMPORTANT ** // Since we're performing authorization at the action level,the authorization code runs // after the output caching module. In the worst case this could allow an authorized user // to cause the page to be cached,then an unauthorized user would later be served the // cached page. We work around this by telling proxies not to cache the sensitive page,// then we hook our custom authorization code into the caching mechanism so that we have // the final say on whether a page should be served from the cache. HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache; cachePolicy.SetProxyMaxAge(new TimeSpan(0)); cachePolicy.AddValidationCallback(CacheValidateHandler,null /* data */); } else { HandleUnauthorizedRequest(filterContext); } CacheValidationHandler将缓存验证委托给受保护的虚拟HttpValidationStatus OnCacheAuthorization(HttpContextBase),这当然不是静态的。它不是静态的一个原因是因为,如上面的重要注释中所述,它调用受保护的虚拟bool AuthorizeCore(HttpContextBase)。 为了从静态缓存验证回调方法中执行任何AuthorizeCore逻辑,它需要知道AuthorizeAttribute实例的Users和Roles属性。但是,似乎并没有一个简单的方法来插入。我必须重写OnAuthorization以将这两个值放入HttpContext(Items集合?)中,然后覆盖OnCacheAuthorization以使它们退出。但是闻起来很脏 如果我们小心地使用OutputCache属性中的VaryByCustom =“User”属性,那么我们只能覆盖OnCacheAuthorization来始终返回HttpValidationStatus.Valid?当action方法没有OutputCache属性时,我们不需要担心这个回调被调用是正确的吗?如果我们有一个没有VaryByCustom =“User”的OutputCache属性,那么显而易见的是,页面可以返回任何缓存的版本,而不管用户的请求是创建缓存的副本。这有多风险? 解决方法
缓存发生在Action之前。您可能需要自定义您的授权机制来处理缓存方案。
查看我发布的一个问题 – MVC Custom Authentication,Authorization,and Roles Implementation。 我认为这将帮助您的一部分是OnAuthorize()方法处理缓存的自定义授权属性。 以下是一个代码块,例如: /// <summary> /// Uses injected authorization service to determine if the session user /// has necessary role privileges. /// </summary> /// <remarks>As authorization code runs at the action level,after the /// caching module,our authorization code is hooked into the caching /// mechanics,to ensure unauthorized users are not served up a /// prior-authorized page. /// Note: Special thanks to TheCloudlessSky on StackOverflow. /// </remarks> public void OnAuthorization(AuthorizationContext filterContext) { // User must be authenticated and Session not be null if (!filterContext.HttpContext.User.Identity.IsAuthenticated || filterContext.HttpContext.Session == null) HandleUnauthorizedRequest(filterContext); else { // if authorized,handle cache validation if (_authorizationService.IsAuthorized((UserSessionInfoViewModel)filterContext.HttpContext.Session["user"],_authorizedRoles)) { var cache = filterContext.HttpContext.Response.Cache; cache.SetProxyMaxAge(new TimeSpan(0)); cache.AddValidationCallback((HttpContext context,object o,ref HttpValidationStatus status) => AuthorizeCache(context),null); } else HandleUnauthorizedRequest(filterContext); } } /// <summary> /// Ensures that authorization is checked on cached pages. /// </summary> /// <param name="httpContext"></param> /// <returns></returns> public HttpValidationStatus AuthorizeCache(HttpContext httpContext) { if (httpContext.Session == null) return HttpValidationStatus.Invalid; return _authorizationService.IsAuthorized((UserSessionInfoViewModel) httpContext.Session["user"],_authorizedRoles) ? HttpValidationStatus.Valid : HttpValidationStatus.IgnoreThisRequest; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 实体框架 – Asp.Net Web API错误:’ObjectContent`1’类型
- asp.net-mvc – ASP MVC区域和ActionLink
- .NET 下基于动态代理的 AOP 框架实现揭秘
- asp.net核心 – ASP.NET核心中的基本身份验证
- asp.net-mvc – Asp.Net Mvc – 在ActionResult.Execute之前
- asp.net – .Net Core 2 Spa模板与角度材料
- ASP.Net – App_Data&App_Code文件夹?
- asp.net-mvc-4 – 使用razor创建数字向上或值控制
- ASP.Net MVC 引用动态 js 脚本
- asp.net-mvc – ASP.NET MVC 4 Web Api和REST经典服务之间的
- asp.net-mvc – 将ASP.NET MVC应用程序部署到IIS
- asp.net – 日期字段不会在Chrome浏览器中显示该
- asp.net-mvc – 使用jQuery $.ajax()和$.post()发
- asp.net – $(“#dialog”).parent().appendTo($
- 我可以在ASP.NET应用程序中禁用IP地址(或一系列地
- asp.net – 什么项目层应该屏幕DTO的生活?
- asp.net-mvc – MVC4异步和并行执行
- 如何在ASP.NET中设置表单提交的目标框架?
- asp.net-mvc – 使JSON.NET和Serializable属性一
- asp.net-mvc – ASP.NET MVC 3从同一表单保存和编