【问题标题】:MVC RequireHttps entire siteMVC RequireHttps 整个站点
【发布时间】:2011-03-18 03:12:59
【问题描述】:

我已经阅读了之前关于使用 RequireHttpsAttribute 保护单个控制器的帖子:

ASP.NET MVC RequireHttps in Production Only

但是有没有办法将此应用到整个网站?由于我的主机 (discountasp.net) 我无法使用“RequireSSL IIS”设置。

【问题讨论】:

  • 我会推荐一个自定义重定向模块,因为它会在 mvc 生命周期中更快地捕获和重定向。我的做法与本文 [alexwolfthoughts.com/…] 不同,但它显示了一些可能性。

标签: asp.net-mvc ssl


【解决方案1】:

您可以为所有控制器使用基类,并使用 require ssl 属性对其进行装饰。

【讨论】:

  • 我(或其他团队成员)不想意外忘记将属性添加到新控制器,或者同样忘记从基类继承。我们希望它是万无一失的。
  • @CodeGrue:你总是可以添加一个单元测试来断言你的所有控制器都使用这个属性;请参阅我最近关于可序列化属性的问题:stackoverflow.com/questions/3257004/…
【解决方案2】:

您始终可以在 global.asax 中的应用程序级别添加检查

protected void Application_BeginRequest(Object sender, EventArgs e)
{
   if (!HttpContext.Current.Request.IsSecureConnection)
   {
    Response.Redirect("https://" + Request.ServerVariables["HTTP_HOST"]
                                 + HttpContext.Current.Request.RawUrl);
   }
}

【讨论】:

    【解决方案3】:

    我最终使用 IIS URL Rewrite 2.0 来强制网站切换到 HTTPS。 web.config 中的这段代码可以解决问题:

      <system.webServer>
        <!-- This uses URL Rewrite 2.0 to force the entire site into SSL mode -->
        <rewrite xdt:Transform="Insert">
          <rules>
            <rule name="Force HTTPS" enabled="true">
              <match url="(.*)" ignoreCase="false" />
              <conditions>
                <add input="{HTTPS}" pattern="off" />
              </conditions>
              <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
            </rule>
          </rules>
        </rewrite>
      </system.webServer>
    

    【讨论】:

    【解决方案4】:

    RequireHttpsAttribute注册为全局过滤器。

    在 global.asax 中:

    protected void Application_Start()
    {
        GlobalFilters.Filters.Add(new RequireHttpsAttribute());
    
        //... other stuff
    }
    

    【讨论】:

    • 绝对是最干净的方法。
    • 我正在这样做,我得到一个重定向循环。 URL 重写对我有用。
    • @RacielR。我之前也遇到过同样的问题,问题是托管合作伙伴在防火墙上接受了 ssl,但通过 http 将请求发送到我的服务器...确保您的托管合作伙伴没有做同样的事情。
    • 这是一个干净的解决方案,但它不只适用于 MVC 控制器吗?如果您想对 任何 URL(包括静态资源或旧版 Web 窗体 aspx 页面)强制实施 HTTPS,该怎么办?似乎 URL Rewrite 方法是最通用的。甚至适用于 iisnode 中托管的 Node.js 应用程序(我知道,因为我正在这样做)。
    • RequireHttpsAttribute 发送 302(temp redir) 而不是 301(permanent),这会损害 SEO。 benjii.me/2015/10/redirect-to-https-asp-net-mvc
    【解决方案5】:

    只是为了使这个答案更新到 MVC 3 及更高版本,请在 App_start 文件夹内的 Filterconfig.cs 文件中使用以下内容

            filters.Add(new RequireHttpsAttribute());
    

    显然,您需要将服务器的 IIS 配置为使用有效的 SSL 证书,可以在这里购买便宜的证书:https://www.namecheap.com/ 我想我上次购买的时候是每个域每年 9 美元。

    【讨论】:

    • 感谢您抽出宝贵时间回来并使用最新答案更新此问题
    • 是 RequireHttpsAttribute 在用户键入 http 时将用户重定向到 https,还是会引发 403 错误?
    • 有趣的是,RequireHttpsAttribute 发送的是 302(临时)重定向而不是 301。奇怪的是,301 是永久重定向,在这里似乎更适用。无论如何,重要的是要记住它只是通过 HTTP 对站点的第一次调用将 302 推送到 HTTPS,然后该会话中的所有后续调用都在 HTTPS 协议内。有办法克服 302,Ben benjii.me/2015/10/redirect-to-https-asp-net-mvc 在此建议了一种方法
    【解决方案6】:

    这没有使用RequireHttps,但我认为这是一个更好的解决方案,因为它可以更快地在MVC Lifecycle 中捕获重定向。

    public class RedirectModule : IHttpModule
    {
        private HttpApplication _context;
    
        public void Init(HttpApplication context)
        {
            _context = context;
            _context.PostResolveRequestCache += HttpRedirect;
        }
    
        public void HttpRedirect(Object src, EventArgs args)
        {
            if (_context.Request.Url.Scheme == Uri.UriSchemeHttp)
            {
                //Redirect to https
                var scheme = Uri.UriSchemeHttps + "://";
                var authority = _context.Request.Url.Authority;
                var url = _context.Request.RawUrl;
    
                var redirectTo = scheme + authority + url;
                _context.Response.PermanentRedirect(redirectTo);
            }
        }
    
        public void Dispose() { }
    }
    

    这个想法来自article

    您可以在Web.configGlobal.asax 中注册模块。我会在 web.cofig 中向您展示。

    <system.webServer>
        <modules>
            <add name="ConfigModuleName" type="Your.Namespace.RedirectModule"/>
        </modules>
    </system.webServer>
    

    【讨论】:

    • Application_BeginRequest 似乎在 PostResolveRequestCache 注册的事件处理程序之前被调用
    【解决方案7】:

    在 Global.asax.cs 中,使用“RegisterGlobalFilters”注册全局属性。

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new RequireHttpsAttribute());
        //e.g. filters.Add(new HandleErrorAttribute());
        //e.g. filters.Add(new System.Web.Mvc.AuthorizeAttribute());            
    }
    

    【讨论】:

      【解决方案8】:

      MVC 6 (ASP.NET Core 1.0) 在注册过滤器的方式上略有不同:

      Startup.cs - AddMvc 过滤 RequireHttpsAttribute:

      public void ConfigureServices(IServiceCollection services)
      {
          // TODO: Register other services
      
          services.AddMvc(options =>
          {
              options.Filters.Add(typeof(RequireHttpsAttribute));
          });
      }
      

      解释设计决策:

      1. 在 Startup.cs 中使用过滤器进行全局设置(因为我们希望它适用于任何地方)。 Startup 应负责注册和设置所有全局规则。如果您的公司雇用了一位新开发人员,她会希望在 Startup.cs 中找到全局设置。
      2. 使用 RequireHttpsAttribute 逻辑,因为它已被证明(由 Microsoft)。切勿使用“http://”和“https://”之类的“神奇”字符串,因为可以通过重复使用为提供相同逻辑而创建的 Microsoft 组件来避免这种情况。

      如果您在没有 SSL 的 localhost 中运行您的 MVC 网站:

      • http://localhost:1337/(无 SSL)
      • https://localhost:1337/ (SSL)

      考虑查看how to run without SSL in localhost while still requiring https it in production

      注意:

      作为替代方法,我们可以创建一个“类 BaseController : Controller”,并让我们所有的控制器都继承自“BaseController”(而不是 Controller)。那么我们只需要设置属性1全局的地方(并且不需要在Startup.cs中注册过滤器)。

      有些人更喜欢属性样式。

      使用示例:

      [RequireHttpsAttribute]
      public class BaseController : Controller
      {
          // Maybe you have other shared controller logic..
      }
      
      public class HomeController : BaseController
      {
          // Add endpoints (GET / POST) for Home controller
      }
      

      【讨论】:

        【解决方案9】:

        在你的 FilterConfig.cs 中应用这个:

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
             // only if Debug is not enabled, do not require https for local development
             if (!HttpContext.Current.IsDebuggingEnabled)
                  filters.Add(new RequireHttpsAttribute());
        
             //... any other filters
        }
        

        这应该会强制您的应用在每个页面上使用 https。

        【讨论】:

        • 还没见过IsDebuggingEnabled
        猜你喜欢
        • 2010-12-07
        • 2011-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多