MVC RequireHttps весь сайт

Я прочитал предыдущие сообщения об использовании RequireHttpsAttribute для защиты отдельных контроллеров:

ASP.NET MVC RequireHttps только в рабочей среде

но есть ли способ применить это ко всему сайту? Из-за моего хоста (Discountasp.net) я не могу использовать настройку «RequireSSL IIS».


person CodeGrue    schedule 19.07.2010    source источник
comment
Я бы порекомендовал настраиваемый модуль перенаправления, так как он быстрее поймает и перенаправит в жизненном цикле mvc. Я бы сделал это иначе, чем в этой статье [alexwolfoughtts.com/], но он показывает некоторые возможности.   -  person christo8989    schedule 30.03.2016


Ответы (9)


Зарегистрируйте RequireHttpsAttribute как глобальный фильтр.

В global.asax:

protected void Application_Start()
{
    GlobalFilters.Filters.Add(new RequireHttpsAttribute());

    //... other stuff
}
person hwiechers    schedule 10.04.2013
comment
Определенно самый чистый метод. - person Serj Sagan; 20.01.2014
comment
Я делаю это и получаю петлю перенаправления. У меня сработала функция перезаписи URL. - person Raciel R.; 21.02.2014
comment
@RacielR. У меня была такая же проблема раньше, проблема заключалась в том, что партнер по хостингу принял ssl на брандмауэре, но затем отправил запрос через http на мой сервер ... Убедитесь, что ваш партнер по хостингу не делает то же самое. - person Julian; 05.03.2014
comment
Спасибо @Julian, это был именно наш случай. - person Raciel R.; 05.03.2014
comment
Это чистое решение, но разве оно не применимо только к контроллерам MVC? Что, если вы хотите принудительно использовать HTTPS для любого URL-адреса, включая статические ресурсы или устаревшие aspx-страницы веб-форм? Похоже, что метод перезаписи URL является наиболее универсальным. Будет работать даже для приложений Node.js, размещенных в iisnode (я знаю, потому что делаю это). - person dprothero; 21.05.2015
comment
Я применил это к своему приложению при использовании IIS Express, и все, что он делает, перенаправляет на localhost. - person Joel McBeth; 23.09.2015
comment
Я бы предпочел использовать метод RegisterGlobalFilters в Global.asax для регистрации глобальных фильтров (например, RequireHttps, Authorize и т. Д.). Я добавил пример в свой ответ ниже. - person Dhanuka777; 18.04.2016
comment
RequireHttpsAttribute отправляет 302 (временное перенаправление) вместо 301 (постоянное), что может повредить SEO. http://benjii.me/2015/10/redirect-to-https-asp-net-mvc/ - person Sam Rueby; 19.04.2016
comment
К вашему сведению, если кто-то использует OverrideAuthorizationAttribute на контроллере или действии, он очищает глобальный фильтр. - person odyth; 12.07.2017
comment
@ Sam.Rueby GlobalFilters.Filters.Add (новый RequireHttpsAttribute (true)); // передать true для постоянного - person Kris; 26.02.2018

В итоге я использовал 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>
person CodeGrue    schedule 20.07.2010
comment
Для тех, кто, как и я, обнаружил это спустя годы, это вызвало у меня ошибку в vs2017. Сработал следующий ответ, похожий на этот: stackoverflow.com/a/47095/4180481 - person Ozan; 03.11.2017

Вы всегда можете добавить проверку на уровне приложения в свой 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);
   }
}
person Todd Smith    schedule 19.07.2010

Чтобы обновить этот ответ для MVC 3 и более поздних версий, используйте следующее в файле Filterconfig.cs в папке App_start

        filters.Add(new RequireHttpsAttribute());

Очевидно, вам потребуются серверы IIS, настроенные для использования действующего сертификата SSL, дешевые сертификаты можно приобрести здесь: https://www.namecheap.com/ Я думаю, что в последний раз, когда я купил один, он стоил 9 долларов за домен в год.

person Alex Stephens    schedule 25.10.2014
comment
Благодарим вас за то, что вы нашли время вернуться и обновить этот вопрос с помощью актуального ответа. - person James Wilson; 15.05.2015
comment
Ожидается, что RequireHttpsAttribute будет перенаправлять пользователей на https, когда пользователи вводят http, или вместо этого будет выдана ошибка 403? - person usefulBee; 14.01.2016
comment
Интересно, что RequireHttpsAttribute отправляет 302 (временное) перенаправление, а НЕ 301. Странно, потому что 301 - это постоянное перенаправление, которое здесь гораздо более применимо. В любом случае важно помнить, что это только первый вызов сайта через HTTP, который подталкивает 302 к HTTPS, а затем все последующие вызовы в этом сеансе выполняются в рамках протокола HTTPS. Есть способ преодолеть 302, 1 здесь предлагает Бен http://benjii.me/2015/10/redirect-to-https-asp-net-mvc/ - person Alex Stephens; 15.01.2016

В вашем 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 на каждой странице.

person joegreentea    schedule 15.04.2017
comment
Еще не видел IsDebuggingEnabled! - person madannes; 03.12.2017

Здесь не используется RequireHttps, но я думаю, что это лучшее решение, потому что оно быстрее улавливает перенаправление в Жизненный цикл MVC.

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() { }
}

Идея пришла из этой статьи.

Вы можете зарегистрировать модуль в своем Web.config или внутри Global.asax. Я покажу вам в web.cofig.

<system.webServer>
    <modules>
        <add name="ConfigModuleName" type="Your.Namespace.RedirectModule"/>
    </modules>
</system.webServer>
person christo8989    schedule 30.03.2016
comment
Application_BeginRequest, кажется, вызывается до того, как обработчик событий зарегистрирован в PostResolveRequestCache - person odyth; 12.07.2017

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.cs.
  2. Используйте логику RequireHttpsAttribute, поскольку она проверена (Microsoft). Никогда не используйте «волшебные» строки, такие как «http: //» и «https: //», если этого можно избежать, повторно используя компонент Microsoft, созданный для обеспечения той же логики.

Если вы запускаете свой веб-сайт MVC на локальном хосте без SSL:

  • http: // localhost: 1337 / (без SSL)
  • https: // localhost: 1337 / (SSL)

Рассмотрите возможность просмотра https://stackoverflow.com/a/38244992/1095493.

Примечание.

В качестве альтернативы мы могли бы создать «класс 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
}
person Nick Niebling    schedule 07.07.2016

В 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());            
}
person Dhanuka777    schedule 18.04.2016

Вы можете использовать базовый класс для всех своих контроллеров и украсить его атрибутом require ssl.

person DanP    schedule 19.07.2010
comment
Я (или другой член команды) не хочу случайно забыть добавить атрибут к новому контроллеру или, таким образом, забыть наследовать от базового класса. Мы хотим, чтобы он был надежным. - person CodeGrue; 20.07.2010
comment
@CodeGrue: вы всегда можете добавить модульный тест, который утверждает, что все ваши контроллеры используют этот атрибут; см. мой недавний вопрос о сериализуемом атрибуте: stackoverflow.com/questions/3257004/ - person DanP; 20.07.2010