Sử dụng Windows23's Microsoft.Web.DistributedCache.DistributedCacheOutputCacheProvider
làm nhà cung cấp outputCache cho một ứng dụng MVC3. Dưới đây là phương pháp hành động có liên quan:Tại sao tôi không thể kết hợp các thuộc tính [Authorize] và [OutputCache] khi sử dụng bộ đệm ẩn Azure (ứng dụng .NET MVC3)?
[ActionName("sample-cached-page")]
[OutputCache(Duration = 300, VaryByCustom = "User",
Location = OutputCacheLocation.Server)]
[Authorize(Users = "[email protected],[email protected]")]
public virtual ActionResult SampleCachedPage()
{
return View();
}
tôi nhận được ngoại lệ sau khi tải quan điểm này từ trình duyệt 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, absolute expirations, 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)
Nếu tôi loại bỏ các [Duyệt] thuộc tính, các cache xem như sẽ là kỳ vọng. Điều này có nghĩa là tôi không thể đặt [OutputCache] trên một phương thức hành động phải có [Authorize]? Hoặc, tôi có cần ghi đè AuthorizeAttribute với một triển khai tùy chỉnh sử dụng phương thức gọi lại xác thực tĩnh cho bộ đệm không?
Cập nhật 1
Sau câu trả lời Evan, tôi đã thử nghiệm phương pháp hành động nêu trên trong IIS Express (bên ngoài Azure). Dưới đây là ghi đè lên tôi cho VaryByCustom = "Thành viên" tài sản trên thuộc tính OutputCache:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
return "User".Equals(custom, StringComparison.OrdinalIgnoreCase)
? Thread.CurrentPrincipal.Identity.Name
: base.GetVaryByCustomString(context, custom);
}
Khi tôi truy cập vào trang mẫu được lưu trữ như [email protected], sản lượng của trang web được lưu trữ, và các màn hình xem "Trang này đã được lưu vào bộ nhớ cache lúc 12/31/2011 11:06: AM (UTC)". Nếu sau đó tôi đăng xuất và đăng nhập bằng [email protected] và truy cập trang, nó sẽ hiển thị "Trang này đã được lưu vào bộ nhớ cache lúc 12/31/2011 11:06: AM (UTC)". Đăng nhập lại với tên [email protected] và truy cập lại trang sẽ khiến bộ nhớ cache hiển thị "Trang này được lưu vào bộ nhớ cache lúc 12/31/2011 11:06: AM (UTC)" một lần nữa. Các nỗ lực đăng nhập/đăng xuất khác cho thấy rằng đầu ra khác nhau đang được lưu vào bộ nhớ cache & được trả lại tùy thuộc vào người dùng.
Điều này khiến tôi tin rằng đầu ra được lưu trữ riêng biệt dựa trên người dùng, đó là ý định với cài đặt VaryByCustom = "Người dùng" của tôi & ghi đè. Vấn đề là nó không hoạt động với nhà cung cấp bộ nhớ cache phân phối của Azure. Evan, bạn có trả lời về chỉ bộ nhớ đệm nội dung công cộng vẫn còn đứng?
Cập nhật 2
tôi đào lên nguồn, và thấy rằng các out-of-box AuthorizeAttribute nào trong thực tế có một callback xác nhận không tĩnh. Dưới đây là một đoạn trích từ 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
đại biểu xác nhận bộ nhớ cache để protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase)
, trong đó tất nhiên không phải là tĩnh. Một lý do tại sao nó không phải là tĩnh là bởi vì, như đã lưu ý trong chú thích QUAN TRỌNG ở trên, nó gọi protected virtual bool AuthorizeCore(HttpContextBase)
.
Để thực hiện bất kỳ logic AuthorizeCore nào từ phương thức gọi lại xác thực bộ nhớ cache tĩnh, nó sẽ cần phải biết thuộc tính Người dùng và Vai trò của cá thể AuthorizeAttribute. Tuy nhiên có vẻ không phải là một cách dễ dàng để cắm vào. Tôi sẽ phải ghi đè OnAuthorization để đặt 2 giá trị này vào HttpContext (Items collection?) Và sau đó ghi đè OnCacheAuthorization để đưa chúng trở lại. Nhưng có mùi bẩn.
Nếu chúng ta cẩn thận khi sử dụng thuộc tính VaryByCustom = "User" trong thuộc tính OutputCache, chúng ta có thể ghi đè OnCacheAuthorization để luôn trả về HttpValidationStatus.Valid không?Khi phương thức action không có thuộc tính OutputCache, chúng ta sẽ không cần phải lo lắng về việc gọi lại bao giờ được gọi, đúng không? Và nếu chúng ta có thuộc tính OutputCache mà không có VaryByCustom = "User", thì rõ ràng là trang có thể trả về bất kỳ phiên bản được lưu trong bộ nhớ cache bất kể yêu cầu người dùng nào đã tạo bản sao được lưu trong bộ nhớ cache. Làm thế nào nguy hiểm này?
olive - ngoài câu trả lời của tôi bên dưới, bạn có thể tìm kiếm bài đăng gốc của TheCloudlessSky, nơi tôi có ý tưởng từ trong mã của tôi ... cũng tung ra mọi thứ không cần thiết về việc tiêm dịch vụ, hoặc Phiên ... tất cả cụ thể với tôi. Điều quan trọng là xử lý xác thực bộ nhớ cache trong hàm OnAuthorization() theo cách bạn cần để làm việc. :) Bảo trọng. –
Điều gì xảy ra nếu bạn sử dụng "UseSlidingExpiration = False" để thực thi hết hạn tuyệt đối? – lalibi
Bạn có biết nếu vấn đề này vẫn còn tồn tại? Tôi dường như có nó với MVC5 và nó có vẻ không phổ biến khác với bài đăng này. Có vẻ thực sự kỳ lạ rằng nó không hoạt động. Tôi không thể tưởng tượng bằng cách sử dụng bộ nhớ đệm và bộ nhớ đệm đầu ra azure là không phổ biến – GraemeMiller