2014-11-10 2 views
1

У меня есть следующий атрибут, чтобы убедиться, что страница удаленного сайта открывается в режиме https.Remote Require HTTPS MVC 5

public class RemoteRequireHttpsAttribute : RequireHttpsAttribute 
    { 
     public override void OnAuthorization(AuthorizationContext filterContext) 
     { 
      if (filterContext == null) 
      { 
       throw new ArgumentException("Filter Context"); 
      } 

      if (filterContext != null && filterContext.HttpContext != null) 
      { 
       if (filterContext.HttpContext.Request.IsLocal) 
       { 
        return; 
       } 
       else 
       { 
        string val = ConfigurationManager.AppSettings["RequireSSL"].Trim(); 
        bool requireSsl = bool.Parse(val); 
        if (!requireSsl) 
        { 
         return; 
        } 
       } 
      } 

      base.OnAuthorization(filterContext); 
     } 
    } 

Локальное развитие теперь работает нормально, так как я не хочу его открывать в режиме https.

Сайт Dev открывает страницу в режиме https - здесь нет проблем (единственный узел).

Где, как созданный мной (баланс нагрузки - 2 узла) сайт, который я сейчас настраиваю, дает мне следующую ошибку. Пожалуйста, обратите внимание, что Dev и прод сайты имеют те же параметры настройки по и web.config

страница не перенаправлять правильно

Firefox определил, что сервер перенаправляет запрос на этот адрес таким образом, что будет никогда не заканчивается.

Эта проблема иногда может быть вызвана отключением или отказом принимать файлы cookie.

Dev сайт URL, как http://dev.datalab.something.org

Prod сайта URL, как http://datalab.something.org

А вот вызов

[RemoteRequireHttps] 
public ActionResult Index(string returnUrl, string error) 

Что я здесь отсутствует?

Обновление 1: Мой администратор подтвердил, что окончание SSL было настроено на уровне балансировки для мальчика. Я просмотрел сайт iis, и я не вижу привязки https. Я вижу только http привязки. Нужно ли ему также настраивать привязки https?

Обновление 2: @AlexeiLevenkov указал мне в правильном направлении, и this post имел код, который я использовал, и он работает. Перенесали код в отдельный ответ.

+0

Не похоже, что вы перенаправляете пользователя обратно на соединение HTTPS, вы отказываетесь от доступа? –

+0

У вас есть какой-то бесконечный цикл, где ваши страницы перенаправляются туда и обратно. Используйте инструменты отладки вашего браузера, чтобы определить, на каких страницах он перескакивает, а затем проверьте конфигурацию/код для этих страниц. – mason

+0

RemoteRequireHttps наследуется от RequireHttpsAttribute. Это перенаправление. @mason У меня есть тот же код на обоих сайтах dev и prod. Сайт Dev отображает страницу в режиме https просто отлично. Нет проблем с перенаправлением. Для этого действия применяется только один атрибут. –

ответ

2

Ваш сайт находится позади балансировки нагрузки, что делает завершение SSL - так как результат весь входящий трафик на ваш сайт HTTP, независимо от того, что видит пользователь. Это приводит к тому, что ваш код всегда пытается перенаправить на HTTPS-версию и, следовательно, на бесконечный цикл.

Варианты исправить:

  • как правило балансировки нагрузки, что делает терминации SSL будет пересылать оригинальный IP/протокол с помощью специальных заголовков. x-forwarded-proto и x-forwarded-for являются общими для этой цели. Возможно, вам потребуется проверить сетевые администраторы, если эти заголовки используются или требуется какая-то дополнительная конфигурация.
  • В качестве альтернативы вы можете отключить завершение SSL, но это добавит дополнительную нагрузку на ваш сервер.
  • Можно также настроить балансировщик нагрузки для разговора с сервером с тем же протоколом, что и входящий запрос.

Как исследовать такой вопрос:

  • Посмотрите на HTTP Debugger (как Скрипач), чтобы увидеть, если вы получаете 30x перенаправляет запросы в цикле. Если никакие переадресации - вероятный код неправильный.
  • Если вы видите повторяющиеся переадресации, это, вероятно, означает, что сайт не видит актуальную информацию о запросе - может быть протокол, пустые файлы cookie отсутствуют.
  • Чтобы продолжить расследование, посмотрите, какие устройства находятся между пользователем и сервером (CDN, прокси, балансировщик нагрузки ...) - у каждого есть хорошие шансы потерять некоторые даты или преобразовать протоколы.
1

Не то, чтобы я против написания приятных пользовательских атрибутов, не имело бы смысла, возможно, выполнить перенаправление в web.config и использовать преобразования, доступные для web.config, чтобы изменить приведенное значение ниже от false до true для производства развертывает?

<rewrite> 
    <rules> 
    <rule name="SSL_ENABLED" enabled="false" stopProcessing="true"> 
     <match url="(.*)" /> 
     <conditions> 
     <add input="{HTTPS}" pattern="^OFF$" /> 
     </conditions> 
     <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" /> 
    </rule> 
    </rules> 
</rewrite> 
+0

ОП получает перенаправление уже, он просто не заканчивается ... Таким образом, изменение Web.Config, скорее всего, будет вести себя точно так же (и это несколько проще). –

+0

Я использую этот код в нашем производственном приложении, когда мы работаем локально, мы просто имеем значение enabled, равное false, как в приведенном выше примере, когда мы развертываем на наш производственный сервер, мы просто меняем значение на true и затем развертываем.мы также тестировали это на IE, Firefox, Chrome, а также на самых популярных мобильных браузерах, и это работает как шарм для нас. –

+0

Разве это не сделает все страницы https? –

1

Перемещение исправления в отдельный ответ, как указано @AlexeiLevenkov.

public class RemoteRequireHttpsAttribute : RequireHttpsAttribute 
    { 
     public override void OnAuthorization(AuthorizationContext filterContext) 
     { 
      if (filterContext == null) 
      { 
       throw new ArgumentException("Filter Context"); 
      } 

      if(filterContext.HttpContext != null) 
      { 
       if (filterContext.HttpContext.Request.IsSecureConnection) 
       { 
        return; 
       } 

       var currentUrl = filterContext.HttpContext.Request.Url; 
       if (currentUrl.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.CurrentCultureIgnoreCase)) 
       { 
        return; 
       } 

       if (string.Equals(filterContext.HttpContext.Request.Headers["X-Forwarded-Proto"], "https", StringComparison.InvariantCultureIgnoreCase)) 
       { 
        return; 
       } 

       if (filterContext.HttpContext.Request.IsLocal) 
       { 
        return; 
       } 

       var val = ConfigurationManager.AppSettings["RequireSSL"].Trim(); 
       var requireSsl = bool.Parse(val); 
       if (!requireSsl) 
       { 
        return; 
       } 
      } 

      base.OnAuthorization(filterContext); 
     } 
    } 

и я также обновил атрибут ExitHttps. У этого были подобные проблемы ...

public class ExitHttpsAttribute : FilterAttribute, IAuthorizationFilter 
    { 
     public void OnAuthorization(AuthorizationContext filterContext) 
     { 
      if (filterContext == null) 
      { 
       throw new ArgumentException("Filter Context"); 
      } 

      if (filterContext.HttpContext == null) 
      { 
       return; 
      } 

      var isSecure = filterContext.HttpContext.Request.IsSecureConnection; 

      var currentUrl = filterContext.HttpContext.Request.Url; 
      if (!isSecure && currentUrl.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.CurrentCultureIgnoreCase)) 
      { 
       isSecure = true; 
      } 

      if (!isSecure && string.Equals(filterContext.HttpContext.Request.Headers["X-Forwarded-Proto"], "https", StringComparison.InvariantCultureIgnoreCase)) 
      { 
       isSecure = true; 
      } 

      if (isSecure) 
      { 
       //in these cases keep https 
       // abort if a [RequireHttps] attribute is applied to controller or action 
       if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof (RequireHttpsAttribute), true).Length > 0) 
       { 
        isSecure = false; 
       } 

       if (isSecure && filterContext.ActionDescriptor.GetCustomAttributes(typeof (RequireHttpsAttribute), true).Length > 0) 
       { 
        isSecure = false; 
       } 

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

       if (isSecure && filterContext.ActionDescriptor.GetCustomAttributes(typeof (RetainHttpsAttribute), true).Length > 0) 
       { 
        isSecure = false; 
       } 

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

      if (!isSecure) 
      { 
       return; 
      } 

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