ASP MVC 3注销

时间:2012-05-30 16:03:47

标签: asp.net-mvc-3 security caching

我在asp.mvc中注销时遇到问题。 用户可以按回按钮,他将看到上次访问的页面。

我进行了一些搜索并找到了这样的解决方案:

this.Response.Cache.SetExpires(DateTime.UtcNow.AddYears(-1));
this.Response.Cache.SetCacheability(HttpCacheability.NoCache);
this.Response.Cache.SetNoStore();

但是我应该将它添加到每个页面以使其正常工作。

是否有某种方法可以为mvc应用程序中的所有控制器的所有GET请求禁用缓存,然后为其中一些控制器启用缓存,例如使用属性或自定义过滤器?

3 个答案:

答案 0 :(得分:3)

让它在全球范围内运作并不是很重要。我在过去所做的是创建一个派生自ActionFilter的类,然后将其添加为global.asax中的全局动作过滤器。另请注意,实际强制所有浏览器重新加载并非易事。即使是下面的代码并不总是适用于Safari,它通常必须通过body标签或类似的空载件进行欺骗。

 using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Web.Mvc;

 /// <summary>
 /// Action filter that instructs the page to expire.
 /// </summary>
 public class PageExpirationAttribute : ActionFilterAttribute
 {
    /// <summary>
    /// The OnActionExecuted method.
    /// </summary>
    /// <param name="filterContext">The current ActionExecutedContext. </param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
       base.OnActionExecuting(filterContext);

       filterContext.HttpContext.Response.ClearHeaders();
       filterContext.HttpContext.Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate, post-check=0, pre-check=0, max-age=0");
       filterContext.HttpContext.Response.AppendHeader("Pragma", "no-cache");
       filterContext.HttpContext.Response.AppendHeader("Keep-Alive", "timeout=3, max=993");
       filterContext.HttpContext.Response.AppendHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
    }
 }

如果您希望能够排除某些页面,则可以创建另一个可应用于控制器或方法的属性。您的OnActionExecuting()可以检查属性是否存在:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class AllowCachingAttribute : Attribute 
{ 
}

要添加到OnActionExecuting的近似代码

using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Web.Mvc;

 /// <summary>
 /// Action filter that instructs the page to expire.
 /// </summary>
 public class PageExpirationAttribute : ActionFilterAttribute
 {
    /// <summary>
    /// The OnActionExecuted method.
    /// </summary>
    /// <param name="filterContext">The current ActionExecutedContext. </param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
       base.OnActionExecuting(filterContext);

       bool skipCache = filterContext.ActionDescriptor.IsDefined(typeof(AllowCachingAttribute), true)
                || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowCachingAttributee), true);

       if (!skipCache)
       {

       filterContext.HttpContext.Response.ClearHeaders();
       filterContext.HttpContext.Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate, post-check=0, pre-check=0, max-age=0");
       filterContext.HttpContext.Response.AppendHeader("Pragma", "no-cache");
       filterContext.HttpContext.Response.AppendHeader("Keep-Alive", "timeout=3, max=993");
       filterContext.HttpContext.Response.AppendHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
       }
    }
 }

答案 1 :(得分:0)

您可以创建一个Utilities类并添加一个公共静态方法来执行上面的代码然后调用它。然后在控制器的方法中,调用Utilities方法。我将提供一些代码:

namespace App
{
    public class Utility
    {
        public static void SetResponsAttributes(HttpResponseBase theResponseObject)
        {
            if (theResponseObject == null) return;

            theResponseObject.Cache.SetExpires(DateTime.UtcNow.AddYears(-1));
            theResponseObject.Cache.SetCacheability(HttpCacheability.NoCache);
            theResponseObject.Cache.SetNoStore(); 
        }
   }
}

答案 2 :(得分:0)

为什么不设置会话标志以指示登录指示符并将整个视图内容包装在if块中。在退出时放弃会话。