如何强制用户通过HTTPS而不是HTTP访问我的页面?

时间:2008-09-17 17:51:06

标签: php apache ssl https

我只有一个页面要强制作为HTTPS页面访问(Apache上的PHP)。如何在不使整个目录需要HTTPS的情况下执行此操作?或者,如果您从HTTP页面向HTTPS页面提交表单,它是通过HTTPS而不是HTTP发送的吗?

以下是我的例子:

http://www.example.com/some-page.php

我希望它只能通过以下方式访问:

https://www.example.com/some-page.php

当然,我可以将此页面的所有链接指向HTTPS版本,但这并不能阻止某些傻瓜故意通过HTTP访问它...

我认为有一件事是在PHP文件的标题中放置重定向以检查它们是否正在访问HTTPS版本:

if($_SERVER["SCRIPT_URI"] == "http://www.example.com/some-page.php"){
  header('Location: https://www.example.com/some-page.php');
}

但这不是正确的方法,可以吗?

顺便说一句,请不要注意URL。我知道如果它实际上是一个有购物车等的页面,你会以不同的方式做到这一点。您可以将其视为一个网站,该网站以一个价格销售一件商品,您可以在其中输入您的信用卡信息,然后将其提交到外部网站上的支付网关,以便明确向您的卡收费一次。

23 个答案:

答案 0 :(得分:166)

我以前做过的方式基本上就像你写的那样,但没有任何硬编码的值:

if($_SERVER["HTTPS"] != "on")
{
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
    exit();
}

答案 1 :(得分:45)

您可以在Apache上使用指令和mod_rewrite来执行此操作:

<Location /buyCrap.php>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</Location>

如果需要,您可以使用regular expressions让位置更智能。

答案 2 :(得分:36)

您应该强制客户端始终使用HTTP Strict Transport Security(HSTS)标头请求HTTPS:

// Use HTTP Strict Transport Security to force client to use secure connections only
$use_sts = true;

// iis sets HTTPS to 'off' for non-SSL requests
if ($use_sts && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
    header('Strict-Transport-Security: max-age=31536000');
} elseif ($use_sts) {
    header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true, 301);
    // we are in cleartext at the moment, prevent further execution and output
    die();
}

请注意,HSTS在大多数现代浏览器中都受支持,但不是通用的。因此,如果用户最终使用HTTP,则上述逻辑会手动重定向用户,无论支持如何,然后设置HSTS标头,以便在可能的情况下应由浏览器重定向其他客户端请求。

答案 3 :(得分:14)

我刚刚创建了一个.htaccess文件并添加了:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

简单!

答案 4 :(得分:9)

// Force HTTPS for security
if($_SERVER["HTTPS"] != "on") {
    $pageURL = "Location: https://";
    if ($_SERVER["SERVER_PORT"] != "80") {
        $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
    } else {
        $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
    }
    header($pageURL);
}

答案 5 :(得分:7)

在负载均衡器后面运行时,必须做这样的事情。帽子提示https://stackoverflow.com/a/16076965/766172

function isSecure() {
    return (
        (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
     || $_SERVER['SERVER_PORT'] == 443
     || (
            (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
         || (!empty($_SERVER['HTTP_X_FORWARDED_SSL'])   && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on')
        )
    );
}

function requireHTTPS() {
    if (!isSecure()) {
        header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], TRUE, 301);
        exit;
    }
}

答案 6 :(得分:5)

http://www.besthostratings.com/articles/force-ssl-htaccess.html

有时您可能需要确保用户通过安全连接浏览您的网站。可以使用包含以下行的.htaccess文件来轻松地将用户重定向到安全连接(https://):

RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]

请注意,.htaccess应位于网站主文件夹中。

如果您希望为特定文件夹强制使用HTTPS,则可以使用:

RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteCond %{REQUEST_URI} somefolder 
RewriteRule ^(.*)$ https://www.domain.com/somefolder/$1 [R,L]

.htaccess文件应放在您需要强制HTTPS的文件夹中。

答案 7 :(得分:5)

好的..现在这里有很多东西,但没有人真的完成了 “安全”的问题。对我来说,使用不安全的东西是荒谬的。

除非你用它作诱饵。

$ _ SERVER传播可以根据知道如何的人的意愿进行更改。

同样,Sazzad Tushar Khan和thebigjc表示你也可以使用httaccess来做这个,这里有很多答案包含它。

只需添加:

RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://example.com/$1 [R,L]

到你的.httaccess所拥有的那一切,那就是。

我们仍然没有这两种工具那么安全。

其余的很简单。如果缺少属性,即......

if(empty($_SERVER["HTTPS"])){ // SOMETHING IS FISHY
}

if(strstr($_SERVER['HTTP_HOST'],"mywebsite.com") === FALSE){// Something is FISHY
}


另请说您已更新了httaccess文件并检查:

if($_SERVER["HTTPS"] !== "on"){// Something is fishy
}

您可以检查更多变量,即..

HOST_URI (如果有关于它的静态属性要检查)

HTTP_USER_AGENT (相同会话的不同值)

因此,当答案在一个组合中时,所有我说的不仅仅是为了解决其中一个。

有关更多httaccess重写信息,请参阅docs-&gt; http://httpd.apache.org/docs/2.0/misc/rewriteguide.html

这里的一些堆栈 - &gt; Force SSL/https using .htaccess and mod_rewrite

Getting the full URL of the current page (PHP)
说出一对夫妇。

答案 8 :(得分:3)

使用$_SERVER['HTTPS']来判断它是否为SSL,如果没有,则重定向到正确的位置。

请记住,显示表单的页面不需要通过HTTPS提供,它是最需要它的回发URL。

编辑:是的,正如下面所指出的,最好是用HTTPS完成整个过程。这让人更放心 - 我指出这个帖子是最关键的部分。此外,您需要注意任何cookie都设置为安全,因此它们只能通过SSL发送。 mod_rewrite解决方案也非常漂亮,我已经用它在我自己的网站上保护了很多应用程序。

答案 9 :(得分:3)

使用htaccess

#if domain has www. and not https://
  RewriteCond %{HTTPS} =off [NC]
  RewriteCond %{HTTP_HOST} ^(?i:www+\.+[^.]+\.+[^.]+)$
  RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=307]

#if domain has not www.
  RewriteCond %{HTTP_HOST} ^([^.]+\.+[^.]+)$
  RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=307]

答案 10 :(得分:1)

如果您使用Apache或支持.htaccess文件的LiteSpeed,您可以执行以下操作。 如果您还没有.htaccess文件,则应在根目录中创建一个新的.htaccess文件(通常是index.php所在的位置)。现在将这些行添加为.htaccess中的第一个重写规则:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

您的.htaccess中只需要一次“RewriteEngine On”指令即可获得所有重写规则,所以如果您已经拥有它,只需复制第二行和第三行。

我希望这会有所帮助。

答案 11 :(得分:1)

使用这个还不够:

  public static void setColumnOrder(int[] indices, JTable table, TableColumnModel columnModel) {

    for (int i = 0; i < indices.length; i++) {
      columnModel.moveColumn(i, table.convertColumnIndexToView(indices[i]));
    }
  }

如果您有任何http内容(如外部http图像源),浏览器将检测到可能的威胁。因此,请确保代码中的所有ref和src都是https

答案 12 :(得分:1)

对于那些使用IIS的人来说,在web.config中添加这一行会有所帮助:

<httpProtocol>
    <customHeaders>
        <add name="Strict-Transport-Security" value="max-age=31536000"/>
    </customHeaders>
</httpProtocol>
<rewrite>
    <rules>
        <rule name="HTTP to HTTPS redirect" stopProcessing="true">
              <match url="(.*)" />
              <conditions>
                 <add input="{HTTPS}" pattern="off" ignoreCase="true" />
              </conditions>
              <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
         </rule>
    </rules>
</rewrite>

完整的示例文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpProtocol>
            <customHeaders>
                <add name="Strict-Transport-Security" value="max-age=31536000"/>
             </customHeaders>
        </httpProtocol>
        <rewrite>
            <rules>
                <rule name="HTTP to HTTPS redirect" stopProcessing="true">
                      <match url="(.*)" />
                      <conditions>
                         <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                      </conditions>
                      <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
                 </rule>
            </rules>
       </rewrite>
   </system.webServer>
</configuration>

答案 13 :(得分:1)

不要在同一页面上混用HTTP和HTTPS。如果你有一个通过HTTP提供的表单页面,我会对提交数据感到紧张 - 我无法查看提交是通过HTTPS还是HTTP进行查看,而不是查看源代码并寻找它。

通过HTTPS提交表单以及提交链接对于优势来说并没有那么大的改变。

答案 14 :(得分:1)

PHP方式:

library(ggplot2)
library(Cairo)   # For nicer ggplot2 output when deployed on Linux
library(shiny)
library(readxl)

data(iris)
write.xlsx(x = iris, file = "iris.xlsx")

ui <- fluidPage(
  fluidRow(
    fileInput(inputId = "file",
              label = "Load file"),
    column(width = 6,
           plotOutput("plot1", height = 350,
                      click = "plot1_click",
                      brush = brushOpts(
                        id = "plot1_brush"
                      )
           ),
           actionButton("exclude_toggle", "Toggle points"),
           actionButton("exclude_reset", "Reset")
    )
  )
)

server <- function(input, output) {

  # Get file
  getFile <- reactive({ if (is.null(input$file)) {
    return(NULL)
  } else {
    return(input$file)
  }})

  # Read data
  data <- reactive({ if (is.null(getFile())) {
    return(NULL)
  } else {
    as.data.frame(read_excel(getFile()$datapath))
  }})

  # For storing which rows have been excluded
  vals <- reactiveValues()
  observeEvent(data(), {
    vals$keeprows <- rep(T, nrow(data()))
  })

  # Toggle points that are clicked
  observeEvent(input$plot1_click, {
    res <- nearPoints(data(), input$plot1_click, allRows = TRUE)

    vals$keeprows <- xor(vals$keeprows, res$selected_)
  })

  # Toggle points that are brushed, when button is clicked
  observeEvent(input$exclude_toggle, {
    res <- brushedPoints(data(), input$plot1_brush, allRows = TRUE)

    vals$keeprows <- xor(vals$keeprows, res$selected_)
  })

  # Reset all points
  observeEvent(input$exclude_reset, {
    vals$keeprows <- rep(TRUE, nrow(data()))
  })

  output$plot1 <- renderPlot({
    if (is.null(data())) {
      return(NULL)
    } else {

      # Indices for keep and exclude
      keep_v <- which(vals$keeprows)
      exclude_v <- which(!vals$keeprows)

      # Subset data
      keep <- data()[keep_v, , drop = F]
      exclude <- data()[exclude_v, , drop = F]

      ggplot(keep, aes(Sepal.Length, Sepal.Width)) + geom_point() +
        geom_smooth(method = lm, fullrange = TRUE, color = "black") +
        geom_point(data = exclude, shape = 21, fill = NA, color = "black", alpha = 0.25)

    }
  })

}

shinyApp(ui, server)

Apache mod_rewrite方式:

$is_https=false;
if (isset($_SERVER['HTTPS'])) $is_https=$_SERVER['HTTPS'];
if ($is_https !== "on")
{
    header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
    exit(1);
}

答案 15 :(得分:1)

如果您想使用PHP来做到这一点,那么这种方式对我来说真的很好:


<?php

if(!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] != "on") {
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"], true, 301);
    //Prevent the rest of the script from executing.
    exit;
}
?>

它检查$ _SERVER超全局数组中的HTTPS变量是否等于“ on”。如果该变量不等于on。

答案 16 :(得分:0)

出于安全原因,您不应该这样做。特别是如果饼干在这里发挥作用。它让你对基于cookie的重放攻击敞开大门。

无论哪种方式,您都应该使用Apache控制规则来调整它。

然后,您可以测试启用的HTTPS,并根据需要重定向。

您应该只使用FORM POST(没有获取)重定向到付费页面, 并且在没有POST的情况下访问页面应该返回到其他页面。 (这会让人们热闹起来。)

http://joseph.randomnetworks.com/archives/2004/07/22/redirect-to-ssl-using-apaches-htaccess/

是一个好的开始,不要提供更多的道歉。但你真的应该通过SSL推送所有内容。

这是过度保护,但至少你有更少的担忧。

答案 17 :(得分:0)

我已经通过许多解决方案来检查 $ _ SERVER [HTTPS] 的状态,但似乎它不可靠,因为有时候它没有设置或设置为on,off等等导致脚本到内部循环重定向。

如果您的服务器支持 $ _ SERVER [SCRIPT_URI]

,这是最可靠的解决方案
if (stripos(substr($_SERVER[SCRIPT_URI], 0, 5), "https") === false) {
    header("location:https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");
    echo "<meta http-equiv='refresh' content='0; url=https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]'>";
    exit;
}

请注意,根据您的安装,您的服务器可能不支持$ _SERVER [SCRIPT_URI],但如果支持,则这是更好的脚本。

您可以在此处查看:Why do some PHP installations have $_SERVER['SCRIPT_URI'] and others not

答案 18 :(得分:0)

也许这个可以帮助,你,这就是我为我的网站所做的,它就像一个魅力:

dataset

答案 19 :(得分:0)

作为替代方案,您可以使用 X-Forwarded-Proto 标头强制重定向到 HTTPS。

在 .htaccess 文件中添加这些行

### Force HTTPS
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

答案 20 :(得分:0)

if(location.protocol!=='https:'){location.replace(`https:${location.href.substring(location.protocol.length)}`);}

答案 21 :(得分:-1)

我使用过这个脚本,它在网站上运行良好。

public void blockingWaitForMessage(long sendTime, String phone) throws InterruptedException{
        final CountDownLatch latch = new CountDownLatch(1);
        while (!latch.await(5, TimeUnit.SECONDS)) {
            if (MessageHandler.getResponse(sendTime, phone)) {
                latch.countDown();
            }
        }
    }

答案 22 :(得分:-3)

<?php 
// Require https
if ($_SERVER['HTTPS'] != "on") {
    $url = "https://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
    header("Location: $url");
    exit;
}
?>

那很容易。