为什么在动作级别使用[RequireHttps]启用SSL后,它会永远保持启用状态?

时间:2011-10-21 08:24:45

标签: asp.net-mvc iis-7 https

我们只在严格要求时才使用https。为什么在调用下面的动作后它会永远保持启用状态?

    [RequireHttps]
    public ActionResult LogIn()
    {
        if(Request.IsAuthenticated)
            return RedirectToAction("Index", "Account");

        return View();
    }

如果不需要,我们可以做些什么来禁用它?

感谢。

2 个答案:

答案 0 :(得分:11)

可以在控制器类型或操作方法上使用[RequireHttps]属性来说“只能通过SSL访问”。对控制器或操作的非SSL请求将被重定向到SSL版本(如果是HTTP GET)或被拒绝(如果是HTTP POST)。您可以覆盖RequireHttpsAttribute并根据需要更改此行为。内置的[RequireHttp]属性没有相反的功能,但如果您愿意,可以轻松制作自己的属性。

Html.ActionLink()也有重载,它采用协议参数;您可以明确指定“http”或“https”作为协议。这是一个这样的重载MSDN documentation。如果您没有指定协议或者如果您调用没有协议参数的重载,则假定您希望链接具有与当前请求相同的协议。

我们在MVC中没有[RequireHttp]属性的原因是它没有太大的好处。它没有[RequireHttps]那么有趣,它鼓励用户做错事。例如,许多网站通过SSL登录并在您登录后重定向回HTTP, 这绝对是错误的做法 。您的登录cookie与您的用户名+密码一样秘密,现在您通过网络以明文形式发送它。此外,在运行MVC管道之前,您已经花时间执行握手并保护通道(这是使HTTPS比HTTP慢的大部分),因此[RequireHttp]将不会发出当前请求或未来要求更快。

如果您要托管utube,请将嵌入更改为使用HTTPS而不是HTTP 如果您在没有正确退出的情况下从HTTPS下拉到HTTP(请参阅http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.signout.aspx),那么您的用户名+密码是敞开的。打电话给SignOut是不够的。

答案 1 :(得分:4)

我使用此动作过滤器,当https操作完成时重定向回http:

using System.Web.Mvc;
using System;
public class ExitHttpsIfNotRequiredAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        // abort if it's not a secure connection
        if (!filterContext.HttpContext.Request.IsSecureConnection) return;

        // abort if a [RequireHttps] attribute is applied to controller or action
        if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Length > 0) return;
        if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Length > 0) return;

        // abort if a [RetainHttps] attribute is applied to controller or action
        if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(RetainHttpsAttribute), true).Length > 0) return;
        if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(RetainHttpsAttribute), true).Length > 0) return;

        // abort if it's not a GET request - we don't want to be redirecting on a form post
        if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) return;

        // redirect to HTTP
        string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
        filterContext.Result = new RedirectResult(url);
    }
}