asp.net c # перенаправление с http на https - PullRequest
49 голосов
/ 15 марта 2011

Итак, в моем коде я хочу определить, называется ли моя страница входа в систему http, и перенаправить ее на https.

Я знаю, что не существует кодовых способов избавиться от этой кошки, но из-за разочаровывающих технических соображений мне приходится делать это в коде.

            if (!Request.IsSecureConnection)
            {
                string redirectUrl = Request.Url.ToString().Replace("http:", "https:");
                Response.Redirect(redirectUrl);
            }

Итак, я уронил это в свой Page_Load(...), убедившись, что мой отладчик использует реальный IIS, а не IIS VS2008, и нажал отладку.

В отладчике, вальс, хит Response.Redirect ( "https://localhost/StudentPortal3G/AccessControl/AdLogin.aspx"), нажмите f5.

Get "Internet Explorer не может отобразить веб-страницу, URL-адрес HTTP, а не HTTPS. Не получено информативной ошибки ... то же самое происходит, не запущенный в отладчике.

Так чего мне не хватает? это не похоже на ракетостроение, я видел похожий код во многих блогах ...

Что я делаю не так? Я полагаю, это должно быть совершенно очевидной ошибкой новичка, но я ее не вижу.

Ответы [ 9 ]

82 голосов
/ 15 марта 2011

Я бы также сделал !Request.IsLocal, чтобы убедиться, что я не отлаживаю, хотя, если вы используете реальный экземпляр IIS с сертификатом, примененным при отладке, это не должно быть проблемой.

if (!Request.IsLocal && !Request.IsSecureConnection)
{
    string redirectUrl = Request.Url.ToString().Replace("http:", "https:");
    Response.Redirect(redirectUrl, false);
    HttpContext.ApplicationInstance.CompleteRequest();
}

Примечание. Этот ответ предполагает наличие контекста MVC в контроллере, где HttpContext - это свойство, содержащее текущий контекст. Если вам не повезло, что вы все еще используете WebForms или ссылаетесь на контекст вырожденным образом, вам нужно будет использовать HttpContext.Current.ApplicationInstance.CompleteRequest().

Примечание. Я обновил его, чтобы он соответствовал рекомендованному шаблону для завершения запроса в соответствии с структурной документацией .

Когда вы используете этот метод в обработчике страницы для завершения запроса одну страницу и начать новый запрос для другой страницы, установите endResponse в false и затем вызовите метод CompleteRequest. Если вы укажете истину для параметра endResponse этот метод вызывает метод End для исходный запрос, который генерирует исключение ThreadAbortException когда это завершится. Это исключение имеет пагубное влияние на сеть производительность приложения, поэтому передача false для Параметр endResponse рекомендуется. Для получения дополнительной информации см. Завершить метод.

24 голосов
/ 15 марта 2011

Я обычно вызываю следующее из OnPreInit в базовом классе, от которого наследуются все мои страницы. Конечно, вы могли бы просто делать это на каждой странице ... но вы бы не хотели делать это сейчас, не так ли?

Обратите внимание, что у меня есть два свойства для каждой страницы, так что я могу указать требование SSL для каждой страницы (Требуется SSL), а также я могу переопределить и перенаправить проверку, если я хочу (с IgnoreRequiresSSL, что полезно для страниц, таких как ошибка) страницы, которые вы переписываете и не знаете, будут ли они зашифрованы или нет), но, конечно, вы можете удалить их для простых настроек.

    protected override void OnPreInit(EventArgs e)
    {
        base.OnPreInit(e);

        if (!IsPostBack)
            RedirectAccordingToRequiresSSL();

        ...
    }

    /// <summary>
    /// Redirect if necessary to ssl or non-ssl enabled URL dependant on RequiresSSL property setting.
    /// </summary>
    private void RedirectAccordingToRequiresSSL()
    {
        if (IgnoreRequiresSSL) return;

        if (RequiresSSL)
        {
            if (!Request.IsSecureConnection) // Need to redirect to https
                RedirectAccordingToRequiresSSL(Uri.UriSchemeHttps);
        }
        else if (Request.IsSecureConnection)
        {
            RedirectAccordingToRequiresSSL(Uri.UriSchemeHttp);
        }

        // Otherwise don't need to do any redirecting as already using the correct scheme
    }

    /// <summary>
    /// Redirect as requested to specified scheme
    /// </summary>
    /// <param name="scheme"></param>
    private void RedirectAccordingToRequiresSSL(string scheme)
    {
        var url = scheme + Uri.SchemeDelimiter + Request.Url.Authority + Request.Url.PathAndQuery;
        Response.Redirect(url, false);
    }
9 голосов
/ 21 августа 2016

На мой взгляд, следующий всесторонний подход - лучший.

Три причины

  1. Работает как для MVC, так и для Web API, как на уровне IIS.
  2. Не влияет на локальные / отладочные настройки. (постоянное перенаправление может вас испортить при отладке не https сайтов на вашем компьютере).
  3. Использует постоянное перенаправление, поэтому все будущие запросы будут автоматически переходить на https

Просто добавьте следующее в ваш <system.webServer> раздел вашего Web.config для вашего проекта.

 <system.webServer>
 ....

 <rewrite>
  <rules>
    <rule name="HTTP to HTTPS redirect" stopProcessing="true">
      <match url="(.*)" />
      <conditions>
        <add input="{HTTP_HOST}" pattern="localhost" negate="true" />
        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
      </conditions>
      <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
    </rule>
  </rules>
  <outboundRules>
    <rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
      <match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
      <conditions>
        <add input="{HTTPS}" pattern="on" ignoreCase="true" />
      </conditions>
      <action type="Rewrite" value="max-age=31536000" />
    </rule>
  </outboundRules>
</rewrite>
</system.webServer>
7 голосов
/ 02 июня 2014

Вы также можете использовать новый UriBuilder:

Dim context As HttpContext = HttpContext.Current
If Not context.Request.IsSecureConnection Then
    Dim secureUrl As New UriBuilder(context.Request.Url)
    secureUrl.Scheme = "https"
    secureUrl.Port = 443
    context.Response.Redirect(secureUrl.ToString, False)
    Return
End If

C #

HttpContext context = HttpContext.Current;
if (!context.Request.IsSecureConnection)
{
    UriBuilder secureUrl = new UriBuilder(context.Request.Url);
    secureUrl.Scheme = "https";
    secureUrl.Port = 443;
    context.Response.Redirect(secureUrl.ToString(), false);
}
3 голосов
/ 19 декабря 2015

Один из способов, которым я смог применить перенаправление https, заключается в следующем:

В пуле приложений мое приложение работает только на порте 443, поэтому незашифрованный сеанс не может возникнуть (если схема шифрования не нарушена уязвимостью ...) Я создал другое приложение на порту 80 с тем же IP-адресом, который содержит только файл web.config со следующим кодом

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
    <httpRedirect enabled="true" destination="https://yourWebsiteURL.com" />
</system.webServer>

2 голосов
/ 13 мая 2014

Я бы также предложил решение tvalfonsso, но с небольшой модификацией на случай переписывания URL-адреса (RawUrl отличается от Url)

    if (SPPage == SPPages.StartAutotrading && !Request.IsLocal && !Request.IsSecureConnection)
        {
            string redirectUrl = (Request.Url.ToString().Replace(Request.Url.PathAndQuery.ToString(), "") + Request.RawUrl).Replace("http:", "https:");
            Response.Redirect(redirectUrl);
        }
2 голосов
/ 26 июля 2013

Вот мое решение:

// Force HTTPS connection
if (!Request.IsSecureConnection)
{
    var uri = new Uri(Request.Url.ToString());
    var redirectUrl = Settings.CanonicalDomain + uri.PathAndQuery;
    Response.Status = "301 Moved Permanently";
    Response.AddHeader("Location", redirectUrl);
    Response.End();
}

Где Settings.CanonicalDomain - ваше имя хоста HTTPS. Он 301 перенаправляет, что может быть правильным ответом в некоторых случаях.

1 голос
/ 02 марта 2014

В моей среде разработки мне нравится иметь отдельный каталог публикации с установленным IIS с самозаверяющим сертификатом, который отличается от моего каталога кода без сертификата, который я отлаживаю непосредственно в Visual Studio.В этом сценарии !Request.IsLocal не идеален, потому что он не работает нигде в вашей среде разработки, даже в каталоге IIS с сертификатом.Я предпочитаю это:

if (!IsPostBack && !HttpContext.Current.IsDebuggingEnabled) 
{
    // do http->https and https->http redirection here
}

HttpContext.Current.IsDebuggingEnabled основано на значении компиляции debug = "true / false" в вашем web.config.У меня установлено значение true в моей директории кода и значение false в моей директории публикации, когда мне нужно локально проверить перенаправление http и https.

Я добавляю в IsPostBack просто, чтобы сделать его (немного) более эффективнымпропуская дополнительную проверку ssl, когда она не нужна.

1 голос
/ 09 февраля 2013

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

Я бы порекомендовал использовать http://nuget.org/packages/SecurePages/. Это дает вам возможность защитить определенные страницы или использовать Regex для определения совпадений. Это также принудительно заставит все страницы, не соответствующие Regex или прямо указанные обратно, HTTP.

Вы можете установить его через NuGet: Install-Package SecurePages

Документы здесь: https://github.com/webadvanced/Secure-Page-manager-for-asp.net#secure-pages

Простое использование:

SecurePagesConfiguration.Urls.AddUrl("/cart");

или

SecurePagesConfiguration.Urls.AddRegex(@"(.*)account", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...