web-dev-qa-db-ja.com

PHP=でHTTPからHTTPSに切り替えるとセッションが失われます

ユーザーをチェックアウトページに送信すると、ユーザーはhttp://sitename.comからhttps://sitename.com

結果として、 $_SESSION変数は失われます。

このサイトには有効なSSL証明書がありますが、これは何らかの用途がある場合とない場合があります。

62
Allan

同じサーバー上でHTTPサービスとHTTPSサービスを切り替えると、HTTPセッションIDがHTTPSセッションに渡されません。次の3つの方法のいずれかで、HTTPページからHTTPSページにセッションIDを渡すことで設定できます。

PHPから:session_start

session_start()は、GET、POST、Cookieなどのリクエストを介して渡される現在のセッションIDに基づいて、セッションを作成するか、現在のセッションを再開します

セッションを使用している場合、通常はsession_start()でスクリプトを開始します。ブラウザにセッションID Cookieが設定されている場合、session_start()はそのセッションIDを使用します。ブラウザーにセッションID Cookieが設定されていない場合、session_start()は新しいCookieを作成します。

セッションIDが設定されていない場合(この例では、ブラウザーがHTTPSセッション用の新しいセッションID Cookieを作成している場合)、session_id()関数を使用して設定できます。 session_id()もセッションIDを文字列として便利に返します。そう

...

$currentSessionID = session_id();

...

$currentSessionID変数を現在のセッションIDと等しく設定します。

...

session_id($aSessionID);

...

ブラウザのsessionID Cookieを$aSessionIDに設定します。 from PHP:session_id

次に、2つのスクリプトの例を示します。 1つはHTTP経由でアクセスされ、もう1つは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.phphttps://www.example.com/page.php および http://example.comhttps://example.com/page.php にリンクします。

PS、私は実際にこれらのスクリプトを実行しなかったため、そのままでは正常に実行できないタイプミスがあるかもしれません。

69
Jacob

セッションCookieは安全に設定されているように聞こえます。 Cookieには "secure" フラグがあり、trueに設定されている場合、Cookieが非HTTPSサイトに送信されないことを意味します。 PHPはおそらくセッションCookieに使用しています。これを変更するには、 session_set_cookie_params 関数、または session.cookie_secure 設定を使用します。 php.ini。

16
JW.

この問題もありました。これは、PHPインストールで suhosin パッチを使用していたためです。suhosin.session.cryptdocroot = Off/etc/php.d/suhosin.iniを設定することで修正しました。

suhosin.session.cryptdocrootに関するsuhosinマニュアルについては、 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

12
Tom

次のソリューションでは、セキュアサーバーと非セキュアサーバーが同じバックエンドサービス(キャッシュ、データベースストアなど)にアクセスできることを前提としています。

ユーザーが買い物を終えたときにチェックアウトフローにユーザーを送信するときに、この同じ問題に対処する必要がありました。これを解決するために、キャッシュレイヤーを配置し、すべての関連データをキャッシュしました。たとえば、セッションIDから製品IDとユーザーIDを収集し、それらをシリアル化し、ハッシュを作成し、最後にハッシュをキーとして使用してセッションデータをキャッシュに保存します。次に、URLのハッシュを使用してユーザーを安全なサイトにリダイレクトします。

ユーザーが安全なサイトにアクセスすると、ハッシュに基づいてキャッシュからデータをプルしようとします。次に、ユーザーIDと製品IDを使用して、すべての価格設定と説明データをデータベースからロードし、最終チェックアウトレビューのためにユーザーに提示できます。

キャッシュデータが揮発性であるという継承リスクがありますが、リダイレクトが迅速に発生するため、キャッシュデータに問題はありません。

6
Mike Purcell

異なるドメイン間でセッション値を渡すことはできません。値を渡すには、http post-getまたはデータベースを使用する必要があります。セキュリティのために、文字列内のすべての値を連結して使用できます

sha1($string)

値と一緒に投稿し、他のページが取得する値のsha1を計算し、ハッシュを比較します。

異なるドメインでpostメソッドを使用すると、ブラウザーにセキュリティメッセージが表示されるため、使用しないでください。

Getメソッドにurlを使用するのは安全ではありません。システムで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

これはかなり安全です。

起こりうること:パラメータ「キー」にランダムな値を入力して、ウェブサイトがデータをメモリにロードするようにするスクリプト?

使用後にエントリを削除するため、これは発生しません。一般的な誤解は、値の取得は安全ではないため、常に回避する必要があるというものです。

パフォーマンスを完全にしたい場合は、mysqlでテーブルエンジンタイプを「メモリ」に設定できます。

1

すべてのページにHTTPSを使用することを検討してください。これがこの問題を回避する最も簡単な方法であり、サイトのセキュリティが向上します。

すべてのページのSSLを選択できない場合は、次のアプローチを使用できます。 安全なセッションCookieでHTTPページとHTTPSページを切り替える 。背後にある考え方は、セッションCookieを安全ではない(したがってHTTPおよびHTTPSページで使用可能)が、認証を処理するための2番目の安全なCookieを使用するというものです。 「セッションの維持」と「認証」の2つの懸念を区別するのに良い方法です。

1
martinstoeckli

セッションCookieはセキュアフラグで作成されているように見えますが、セッションCookieが渡されないため、チェックアウトページのURLに何かがあります。

または、おそらくセッションCookieは安全ではありません-チェックアウトページのURLが十分に異なるだけです( http://mysite.com vs http://www.mysite.com )ブラウザがCookieを送信していないこと。

Httpからhttpsへ、またはその逆への切り替えについて詳しく知りたい場合は、 selective sslに関する私の記事 :-)をご覧ください

1
Raghu

暗号化された情報の転送についてここで最も述べたことに加えて、サードパーティのAPIを介して機密情報を転送している場合と同じように見ることをお勧めします。誰かがリクエストをスプーフィングしていないことをどのように確認しますか?セットアップの機密性に応じて、リクエストの真正性を真に確認するための多くのプロトコルがあります。注意を怠ると、アカウントが危険にさらされることになります。

同じサーバー上にある場合でも、次のことを考慮してください。

誰かが暗号化されたキーを通過するリンク、フォームアクションなどをフォローしている場合、セキュリティで保護されたバージョンのサイトにアクセスする前に誰かがそれをスニッフィングするのを防ぐのは何ですか私が公共のWIFIスポットにいたとしても、それはあまりにも大げさではありません。あなたのサイトのふりをして、リクエストを自分のラップトップに転送し、トークンを取得して、訪問者を元の場所にリダイレクトすることができます。彼らはそれがグリッチであると仮定し、何も知りません。今、私は彼らとしてログインし、おそらく彼らのクレジットカードをファイルに入れて10,000ドル相当のものを買いに行き、それをどこかに出荷することができます。ここで取る注意の程度は、感度の程度と一致する必要があります。

また、トークンを期限切れにすることを確認してください(1回の使用のみ、X秒後など)。しかし、両端でPost-Redirect-Getパターンを使用することも検討します。

ページまたはセキュリティで保護されていないサイトの形式で直接リンクを表示しないでください。その後、バックエンドでリダイレクトするリンクを表示します(そしてすべてのトークン/暗号化を処理します)。セキュリティで保護されたバージョンに到達したら、同じことを行います(URLにある「?token = asdfjalksfjla」パラメーターをそのままにしないで、リダイレクトします)。

そのため、正式なトークンベースのシステムはこの問題を解決するように設計されていますが、OAuth=を実装するのはやり過ぎかもしれません。 本当に難しいトークンを推測することは不可能であることを意味しない(または衝突などがあり得ない)ので、それに応じて計画する。

また、PHPの組み込みハンドラーよりも高度なセッション管理システムが必要になる場合があります。 PHPが複数の訪問にわたってセッションを継続することを強制できるかどうかはわかりません(プロトコルの切り替えはそのように扱われます)。

1
landons

HTTPからHTTPSまたはHTTPSからHTTPの間のセッションを管理できます。

  1. GETを使用してページ間でセッションIDを送信する

  2. POSTによるPOSTセッションID

  3. ファイルを使用してセッションを保存する

  4. セッションにCookieを使用する

  5. データベースを使用してセッションを保存する

以下の例は、GET…を使用して送信するために使用できます。

ファイル:http.php……………

<?php

session_start();

$sessionID = session_id();

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

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

?>

ファイル:https.php……………

<?php

$sessionID = $_GET['session'];

session_id($sessionID);

session_start();

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

?>

IE7:このページには、安全なアイテムと安全でないアイテムの両方が含まれています

IEメッセージセキュアおよび非セキュアアイテムを回避するために、CSS、JS、画像、フラッシュなどのようなページ上のすべての静的リソースに相対パスを使用する必要があります…

IE Message IEメッセージ

1
Rohan Patil

私は同様の問題を抱えていましたが、この解決策は私にとって良いものでした。おそらく他の人にも役立つでしょう

これをphp.iniに追加します

suhosin.session.cryptdocroot =オフ

suhosin.cookie.cryptdocroot =オフ

0
Willian Santana

デフォルトでは、ブラウザはhttpとhttpsへの接続を完全に異なるセッションとして処理するはずです。慣例では http:// someUrl / および https:// someUrl / は同じページを指しますが、保証されていません。ポート80(http)とポート443(https)で実行されている完全に異なるサイトを持つことができます。

私はPHPを知りませんが、一般に、セッション変数が安全なセッションと安全でないセッションの間で自由に利用できるとは思わないでしょう。私が最後にチェックアウトしたクレジットカード番号が、次にアクセスするすべての安全でないページで利用できるとは思わないでしょう。

権威のない答えは許してください。しかし、あまり多くの答えがないので、2cを使いこなそうと思いました。

0
codybartfast

Cookieが失われているように見えるため、これは不可能な場合があります。使用しているブラウザは、まったく別のドメイン用であると考えなければなりません。

具体的にどのブラウザを使用していますか?

0
Allain Lalonde

これで解決策があります。試してください。

$_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();
0
UWU_SANDUN

専用IPを持っていますか?一部の共有環境では、httpsとhttpは異なるサーバーを経由してルーティングされるため、Cookieは異なるドメインにあるため、実際にはCookieにアクセスできなくなります。

ソリューションは次のとおりです。専用IP

すべてのページで常にhttpsを強制する

0
Brian Barrett