64

当将用户发送到结帐页面时,他们会从 切换http://sitename.comhttps://sitename.com

结果,$_SESSION变量丢失。

该站点具有有效的 SSL 证书,该证书可能有用也可能没有用。

4

16 回答 16

71

当您在同一服务器上的 HTTP 和 HTTPS 服务之间切换时,您的 HTTP 会话 ID 不会传递给 HTTPS 会话。您可以通过以下三种可能方式之一将会话 ID 从 HTTP 页面传递到 HTTPS 页面来设置它:

PHP: session_start

session_start()根据通过请求(例如 GET、POST 或 cookie)传递的当前会话 ID 创建会话或恢复当前会话

当您使用会话时,您通常会以session_start(). 如果浏览器设置了会话 ID cookie,session_start()将使用该会话 ID。如果浏览器没有设置会话 ID cookie,session_start()将创建一个新的。

如果未设置会话 ID(在您的示例中,浏览器正在为 HTTPS 会话创建新的会话 ID cookie),您可以使用该session_id()函数进行设置。session_id()还可以方便地将会话 ID 作为字符串返回。所以

...

$currentSessionID = session_id();

...

$currentSessionID变量设置为等于当前会话 ID,并且

...

session_id($aSessionID);

...

将浏览器中的 sessionID cookie 设置为$aSessionID. 来自PHP:session_id

这是一个包含两个脚本的示例。一种通过 HTTP 访问,另一种通过 HTTPS 访问。它们必须在同一台服务器上才能维护会话数据。

脚本 1(HTTP)

<?php

// This script will create a session and display a link to your secure server address
// to transfer your session ID. In this example, the secure page to receive the session
// ID is located at http://www.yoursite.com/safePages/securePage.php

// Start a session using the current session ID stored in a cookie, or create
// a new session if none is set.
session_start();

$currentSessionID = session_id();

// Set a variable that will be retrieved with the HTTPS script.
$_SESSION['testvariable'] = 'It worked';

// $secureServerDomain is the domain of your secure server
$secureServerDomain = 'www.yoursite.com';

// $securePagePath is the path to the page that will receive and set the session ID.
$securePagePath = '/safePages/securePage.php'

echo '<a href="https://' . $secureServerDomain . $securePagePath . '?session="' . $currentSessionID . '">Click here to transfer your session to the secure server</a>';

?>

脚本 2(HTTPS)

<?php

// Retrieve the session ID as passed via the GET method.
$currentSessionID = $_GET['session'];

// Set a cookie for the session ID.
session_id($currentSessionID);

// Start a session.
session_start();

// Test retrieval of variable set when using HTTP.
if (!empty($_SESSION['testvariable'])) {
      echo $_SESSION['testvariable'];
} else {
      echo 'It did not work.';
}

?>

为此,HTTP 和 HTTPS 服务器必须使用相同的会话数据存储基板(即,对于默认文件处理程序,运行在具有相同 php.ini 的相同物理机器上)。这里有一些安全漏洞,所以我不会使用这个代码来传输敏感信息。它只是作为一个可行的例子。

当我之前遇到这个问题时,我想出了上面的快速解决方案,但我只记得问题的原始原因。我从http://www.example.com/page.php转到https://example.com/page.php(注意缺少“www”)。确保http://www.example.com/page.php将链接到https://www.example.com/page.php并且http://example.com将链接到https://example.com /page.php

PS,我实际上并没有运行这些脚本,所以可能有一两个错字阻止它们按原样正常运行。

于 2009-01-14T03:06:10.490 回答
16

听起来会话 cookie 设置为安全的。Cookie 有一个“安全”标志,如果设置为 true,则意味着 cookie 不会发送到非 https 站点。PHP 可能将其用于其会话 cookie。您可以使用session_set_cookie_params函数或php.ini 中的session.cookie_secure设置来更改它。

于 2009-01-14T03:15:18.617 回答
12

我们也有这个问题。原来是因为我们在 PHP 安装中使用了suhosin补丁。我们通过设置suhosin.session.cryptdocroot = Off来修复它/etc/php.d/suhosin.ini

有关 suhosin 手册,suhosin.session.cryptdocroot请参阅http://www.hardened-php.net/suhosin/configuration.html#suhosin.session.cryptdocroot

我们最初从这篇博客文章中找到了修复:http ://www.yireo.com/blog/general-news/315-switch-between-http-and-https-looses-php-session 。

于 2010-07-16T20:17:43.157 回答
6

以下解决方案假定安全和非安全服务器可以访问相同的后端服务(缓存、数据库存储等)。

在用户完成购物后将其发送到我们的结帐流程时,我们必须处理同样的问题。为了解决这个问题,我们放置了一个缓存层并缓存了所有相关数据。例如,我们将从会话值中收集产品 ID 和用户 ID,将它们序列化,创建哈希,最后使用哈希作为键将会话数据存储在缓存中。然后,我们会将用户重定向到带有 url 中的哈希的安全站点。

当用户最终访问安全站点时,我们将尝试根据哈希将数据从缓存中提取出来。然后使用用户 ID 和产品 ID,我们可以从数据库中加载所有定价和描述数据并呈现给用户以供最终结帐审查。

缓存数据易失性存在继承风险,但我们从未遇到过任何问题,因为重定向发生得很快。

于 2011-11-15T20:43:56.030 回答
1

看起来您的会话 cookie 是使用安全标志创建的,但是由于会话 cookie 没有被传递,因此您的结帐页面的 url 有一些东西。

或者可能,您的会话 cookie 不安全 - 只是结帐页面的 url 不同(http://mysite.comhttp://www.mysite.com)浏览器没有发送 cookie。

如果您想阅读更多关于从 http 切换到 https 的信息,反之亦然 - 请查看我关于选择性 ssl 的文章:-)

于 2009-02-26T21:42:39.190 回答
1

您可以管理 HTTP 到 HTTPS 或 HTTPS 到 HTTP 之间的会话:

  1. 使用 GET 在页面之间传输会话 ID

  2. 通过 POST POST 会话 ID

  3. 使用文件保存会话

  4. 使用 Cookie 进行会话

  5. 使用数据库保存会话

下面的示例可用于使用 GET... 进行传输。

文件:http.php………………</p>

<?php

session_start();

$sessionID = session_id();

$_SESSION['demo'] = ‘Demo session between HTTP HTTPS’;

echo ‘&lt;a href=”https://www.svnlabs.com/https.php?session=’.$sessionID.’”&gt;Demo session from HTTP to HTTPS</a>’;

?>

文件:https.php………………</p>

<?php

$sessionID = $_GET['session'];

session_id($sessionID);

session_start();

if (!empty($_SESSION['demo'])) {
echo $_SESSION['svnlabs'];
} else {
echo ‘Demo session failed’;
}

?>

IE7:此页面包含安全和非安全项目

您必须对页面上的所有静态资源(如 css、js、图像、flash 等)使用相对路径,以避免 IE 消息安全和非安全项目...</p>

IE消息 IE消息

于 2011-11-17T09:48:23.573 回答
1

我建议,除了这里大多数人所说的关于传输加密信息的内容外,将其视为通过 3rd 方 API 传输敏感信息的方式。你怎么知道有人没有欺骗请求?有许多协议可以真正确认请求的真实性,具体取决于您的设置有多敏感。如果你不小心,你就会让自己的账户被盗。

即使它在同一台服务器上,请考虑:

当有人跟踪传递加密密钥的链接、表单操作等时,什么可以防止有人在访问您网站的安全版本之前对其进行嗅探?如果我在公共 WIFI 点,那也不会太牵强。我可以假装是您的站点,将请求重新路由到我自己的笔记本电脑,获取令牌,然后将访问者重定向回他们来的地方。他们会认为这是一个小故障,并且不知道。现在我可以以他们的身份登录,可能会用他们的信用卡购买价值 10,000 美元的东西,然后将其运送到其他地方。您在此处采取的谨慎程度应与敏感程度相匹配。

另外,请确保您的令牌过期(仅使用一次,在 X 秒后等),但我也会考虑在两端使用 Post-Redirect-Get 模式,即:

不要在页面上或以不安全站点的形式显示直接链接,而是显示一个链接,然后将在后端重定向(并处理所有令牌/加密内容)。当您到达安全版本时,请执行相同操作(不要将“?token=asdfjalksfjla”参数留在 URL 中;重定向它)。

因此,正式的基于令牌的系统旨在解决这个问题,但仅仅为此实施 OAuth 可能是矫枉过正。在执行之前花一些时间计划潜在的漏洞。仅仅因为很难猜测令牌并不意味着它是不可能的(或者不可能有冲突等),所以要相应地计划。

您可能还需要一个比 PHP 的内置处理程序更复杂的会话管理系统。我不知道您是否可以强制 PHP 在多次访问中继续会话(以这种方式处理切换协议)。

于 2011-11-16T12:14:09.217 回答
1

您不能在不同域之间传递会话值。您必须使用 http post-get 或数据库来传递您的值。为了安全起见,您可以将所有值连接到一个字符串中并使用

sha1($string)

并将其与您的值一起发布并计算其他页面获得的值的 sha1,然后比较哈希值。

不同域上的 Post 方法会导致浏览器显示安全消息,所以不要使用它。

将 url 用于 get 方法是不安全的,您需要在重定向页面上要求输入密码才能允许系统中的 get 参数。

如果您需要安全,请勿使用 cookie。

我建议的方法是,将值保存在数据库中并生成一个密钥,然后使用您的密钥创建重定向链接,使用具有密钥的 get 参数转发用户页面,然后将页面用户重定向到获取该密钥,获取数据并删除密钥。您可以使用 sha1 生成密钥

PAGE 1---
$key=sha1($allvalsconcat);
//insert your session values to a database also the key in a column
header("Location: page2.php?key=".$key);

PAGE 2---
// select from database where key=$_GET["key"];
// delete from table where key=$key

这是相当安全的。

可能发生的事情:为参数“key”输入随机值以使您的网站将数据加载到内存中的脚本?

这不会发生,因为您在使用后删除了该条目。一些常见的误解是获取值是不安全的,应始终避免。

如果您想要完美的性能,您可以在 mysql 中将表引擎类型设置为“内存”。

于 2011-11-15T19:42:13.543 回答
1

考虑对所有页面使用 HTTPS,这是避免此问题的最简单方法,它将提高您网站的安全性。

如果您不能选择所有页面的 SSL,那么您可以使用以下方法: 使用安全 session-cookie 在 HTTP 和 HTTPS 页面之间切换。背后的想法是,您让会话 cookie 不安全(因此可用于 HTTP 和 HTTPS 页面),但有第二个安全 cookie 来处理身份验证。这是将“维护会话”和“身份验证”这两个关注点分开的好方法。

于 2011-11-16T12:48:43.347 回答
0

默认情况下,我希望浏览器将与 http 和 https 的连接视为完全不同的会话。尽管约定是http://someUrl/https://someUrl/将指向同一页面,但不能保证。您可以在端口 80 (http) 和端口 443 (https) 上运行完全不同的站点。

我不知道 PHP,但通常我不希望会话变量可以在安全会话和非安全会话之间免费使用,例如,我不希望我上次结帐时的信用卡号可用于所有后续的不安全页面访问。

原谅非权威的答案,但我想我会放弃我的 2c,因为答案不多。

于 2009-01-14T02:29:10.907 回答
0

这可能是不可能的,因为 cookie 似乎正在丢失。您使用的浏览器必须认为它适用于完全不同的域。

你具体用的是什么浏览器?

于 2009-01-14T01:00:28.857 回答
0

你有专用IP吗?在某些共享环境中,https 和 http 是通过不同的服务器路由的,因此切换实际上会失去对 cookie 的访问权限,因为它们位于不同的域中。

解决方案是:专用IP

始终在所有页面上强制 https

于 2015-07-13T16:40:22.390 回答
0

我遇到了从 http 转移到 https 的问题,我能够解决这个问题,将网站 URL 从http://example.com更改为https://www.example.com

将 www 添加到 URL 为我解决了这个问题。

谢谢。

于 2020-02-11T16:37:44.943 回答
0

我有类似的问题,但是,这个解决方案对我有好处,也许将来会帮助其他人

在你的 php.ini 中添加这个

suhosin.session.cryptdocroot = 关闭

suhosin.cookie.cryptdocroot = 关闭

于 2016-07-26T19:21:07.227 回答
0

我有一个解决方案..试试看。

$_SESSION['test'] = 'test';
session_regenerate_id(true);

header("Location: /");// the header must be sent before session close
session_write_close(); // here you could also use exit();
于 2016-09-18T06:59:07.503 回答
-1

不要担心这是一种正常的行为,因为 HTTPS 是为了保证安全,它正在发挥作用。

下面是一些技巧,您可以通过这些技巧在从 HTTP 切换到 HTTPS 时保持会话。

  1. 使用 GET 在页面之间传输会话 ID

  2. 通过 POST POST 会话 ID

  3. 使用文件保存会话

  4. 使用 Cookie 进行会话

  5. 使用数据库保存会话

希望你能通过我的回复有所收获。

于 2011-11-16T11:36:05.443 回答