繁体   English   中英

要缓存还是不缓存? 以及如何在asp.net mvc的基础控制器上缓存它?

[英]To Cache or not to cache? And how to cache it on a base controller in asp.net mvc?

我正在制作自己的基本控制器,因为我想将一些数据传递给母版页。 现在,因为这就像将此代码添加到该控制器中的每个视图一样,它每次都会运行。

当它第一次加载时,我认为它已经至少击中了我的代码两次。 所以我在考虑缓存它。 但在我的书中它表示不会缓存私人数据,因为每个人都会看到它。

所以我不知道该怎么做。

我的几行代码是做什么的。

  1. 查找用户名并将其显示给用户。
  2. 找到用户计划并显示该计划。

所以我需要userName来找出他们的GUID,以便我可以找出他们注册的计划。

所以我不知道如何缓存它,但不将它暴露给每个人。 有没有让它为这个用户缓存?

引用Asp.net mvc框架unleasehd pg 330

不要缓存私人数据

缓存包含私有用户数据的页面非常危险。 当页面缓存在服务器上时,同一页面将提供给所有用户。 因此,如果您缓存显示用户信用卡号的页面,则每个人都可以看到信用卡号(不好!)。

即使您需要授权,也会为所有用户缓存相同的页面。 例如,想象一下,您创建了一个金融服务网站,该网站包含一个显示所有用户投资的页面。 该页面显示用户在一组股票,债券和共同基金中投入的金额。

由于此信息是私有的,因此您需要用户在查看页面之前登录。 换句话说,在用户可以查看页面之前,必须授权每个用户。

要提高金融服务页面的性能,您决定为页面启用缓存。 您将OutputCache属性添加到返回页面的控制器操作。

不要那样做! 如果您缓存返回金融服务页面的控制器操作,则第一个请求页面的人员的私有财务数据将在应用程序的每个后续访问者之间共享。

通常,将OutputCache和Authorize属性添加到同一个控制器操作会打开一个安全漏洞。 避免这样做:

回答是否应缓存某些内容的最佳方法是确定它是否实际影响了您网站的性能。 使用实际指标。 不要猜。 如果它没有伤害任何东西,而且一切看起来都很敏感,那么我会说在其他方面工作直到需要出现。 “过早优化是所有邪恶的根源”已经说过一两次了:)

如果您确实选择缓存数据,我不确定您的意思是每个人都可以看到它? 如果您的意思是ASP.NET缓存框架( HttpContext.Current.Cache ),那么它将存在于您的服务器内存中并且完全不稳定(如果内存压力达到它,它将随时被删除)。 因此,请务必记住这一点并始终检查是否为空。 要使用它,您可以简单地使用Cache.Insert() ,它有一些重载来自定义您的缓存首选项。

现在,如果您正在谈论使用浏览器cookie缓存某些内容,这是另一个故事。 Cookie确实存储在浏览器中,除非你为cookie指定HttpOnly,它可以通过javascript读取(如果你有某个XSS漏洞,这只是一个问题 - 因为恶意用户可以使用javascript来“回家” “用户的私人cookie数据。”因此,除非绝对必要,否则不要将任何内容私有放入cookie中,如果这样做,则应指定HttpOnly并采取适当措施保护您的用户。

如果安全性是您最关心的问题,那么您肯定应该阅读有关XSS和其他常见HTTP安全问题的更多信息。 (它应该是:)

更新以解决有关输出缓存的问题编辑:

好的,所以你专门提到了输出缓存。 事实上,这本书提到了一个安全漏洞, 我认为在MVC 1发布之前已经修补了这个漏洞。 当这两个属性结合使用时,Authorize属性应足够智能以正确处理输出缓存。 也许这本书是在预览版中编写的,不再相关。

我引用了Steve Sanderson(Pro ASP.NET MVC框架的作者)的以下内容

更新:自Beta版本发布以来,[Authorize]过滤器现在可以使用一些聪明的技巧来与ASP.NET输出缓存协作。 具体来说,它使用HttpCachePolicy.AddValidationCallback()注册一个委托,以便它可以拦截未来的缓存命中并告诉ASP.NET输出缓存在[Authorize]拒绝请求时不使用缓存。 这解决了绕过[Authorize]过滤器的ASP.NET输出缓存问题。 如果您要编写自己的授权过滤器,请务必从AuthorizeAttribute派生它,以便继承此有用的行为。

请注意,这不会阻止ASP.NET输出缓存绕过任何其他操作筛选器,并且它不会为部分缓存添加任何支持。 如果这对您来说是个问题,那么请考虑使用[ActionOutputCache](下面)。

阅读他的文章(和他的书,就此而言)是值得的: http//blog.codeville.net/2008/10/15/partial-output-caching-in-aspnet-mvc/

您的Controller类只有一个从action-request延伸到view-rendered的生命周期。 你真的需要缓存这些数据吗? 只需公开Model对象中的数据即可。 查询听起来不够复杂,而且大多数RDBMS供应商倾向于自己进行大量的查询缓存。

HTTP是一种无状态协议,这意味着在请求之后,您的Web服务器会忘记所述请求的所有内容。 为了规避这种无状态,asp.net提供了Application和Session对象。 应用程序全局可用于所有请求,并且会话绑定到单个IP。 将任何数据放在那里通常是最后的手段或部分方案来缓存真正具有大量加载时间的数据。

ASP.NET MVC中的流程大致如此

  • 请求URL
  • 控制器被调用
  • 行动被召唤
  • 动作调用数据模型(用户名/用户计划)
  • Action在viewmodel中设置数据
  • Action使用viewmodel中的数据调用所需的视图
  • 视图已呈现。

在viewmodel上设置数据已经是“私有的”,所以我不确定缓存需求来自何处。 也许我误解了这个问题?

编辑

好的,首先请原谅我,如果我的帖子有点冒昧。 我认为你的代码根本不需要进入基础构造函数的构造函数。 毕竟,您不会将控制器传递给视图。

一个好的做法是传入类型化的ViewModel。 说这是您在site.master中的定义

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MyNS.BaseViewDataModel>" %>

这个定义说你的帮助页面查看:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyNS.HelpViewDataModel>" %>

然后,您可以创建BaseViewDataModel

namespace MyNS
{
    public class BaseViewDataModel

和你的HelpViewDataModel

namespace MyNS
{
    public class HelpViewDataModel : BaseViewDataModel 
    {

然后在你的帮助控制器的适当行动

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index()
{
    var viewDataModel = new HelpViewDataModel ();
            viewDataModel.HelpText = "something";
            ..
            ..
    return View(viewDataModel);
}

您现在可以在BaseViewDataModel的构造函数中实例化您的用户指南和用户计划,并且只会为实际实例化BaseViewDataModel子类的操作调用它。

而且您的视图是类型安全的,因为我们输入了我们现在可以实际调用的视图,因此可以大幅提高生产力

<%= this.Model.HelpText %>

在帮助视图中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM