基本的なショッピングカートを使用して基本サイトをまとめています。今後、セッションに機密情報を保存する予定です。 。PHPショッピングカートセッションは、カスタムセッションハンドラがサイトに組み込まれた後に更新されません
function decrypt($edata, $password) {
$data = base64_decode($edata);
$salt = substr($data, 0, 16);
$ct = substr($data, 16);
$rounds = 3; // depends on key length
$data00 = $password.$salt;
$hash = array();
$hash[0] = hash('sha256', $data00, true);
$result = $hash[0];
for ($i = 1; $i < $rounds; $i++) {
$hash[$i] = hash('sha256', $hash[$i - 1].$data00, true);
$result .= $hash[$i];
}
$key = substr($result, 0, 32);
$iv = substr($result, 32,16);
return openssl_decrypt($ct, 'AES-256-CBC', $key, true, $iv);
}
function encrypt($data, $password) {
// Set a random salt
$salt = openssl_random_pseudo_bytes(16);
$salted = '';
$dx = '';
// Salt the key(32) and iv(16) = 48
while (strlen($salted) < 48) {
$dx = hash('sha256', $dx.$password.$salt, true);
$salted .= $dx;
}
$key = substr($salted, 0, 32);
$iv = substr($salted, 32,16);
$encrypted_data = openssl_encrypt($data, 'AES-256-CBC', $key, true, $iv);
return base64_encode($salt . $encrypted_data);
}
class SecureSessionHandler extends SessionHandler {
protected $name, $cookie;
private $key;
public function __construct($key, $name = 'MY_SESSION', $cookie = [])
{
$this->key = $key;
$this->name = $name;
$this->cookie = $cookie;
$this->cookie += [
'lifetime' => 0,
'path' => ini_get('session.cookie_path'),
'domain' => ini_get('session.cookie_domain'),
'secure' => isset($_SERVER['HTTPS']),
'httponly' => true
];
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-
cbc'));
$this->setup();
}
private function setup()
{
ini_set('session.use_cookies', 1);
ini_set('session.use_only_cookies', 1);
session_name($this->name);
session_set_cookie_params(
$this->cookie['lifetime'],
$this->cookie['path'],
$this->cookie['domain'],
$this->cookie['secure'],
$this->cookie['httponly']
);
}
public function start()
{
if (session_id() === '') {
if (session_start()) {
return mt_rand(45, 99) === 55 ? $this->refresh() : true; // 1/5
}
}
return false;
}
public function forget()
{
if (session_id() === '') {
return false;
}
$_SESSION = [];
setcookie(
$this->name,
'',
time() - 42000,
$this->cookie['path'],
$this->cookie['domain'],
$this->cookie['secure'],
$this->cookie['httponly']
);
return session_destroy();
}
public function refresh()
{
return session_regenerate_id(false);
}
public function write($id, $data)
{
$data = encrypt($data, $this->key);
return parent::write($id, $data);
}
public function read($id)
{
$data = parent::read($id);
if (!$data) {
return "";
} else {
return decrypt($data, $this->key);
}
}
public function isExpired($ttl = 30)
{
$last = isset($_SESSION['_last_activity'])
? $_SESSION['_last_activity']
: false;
if ($last !== false && time() - $last > $ttl * 60) {
return true;
}
$_SESSION['_last_activity'] = time();
return false;
}
public function isFingerprint()
{
$hash = md5(
$_SERVER['HTTP_USER_AGENT'] .
(ip2long($_SERVER['REMOTE_ADDR']) & ip2long('255.255.0.0'))
);
if (isset($_SESSION['_fingerprint'])) {
return $_SESSION['_fingerprint'] === $hash;
}
$_SESSION['_fingerprint'] = $hash;
return true;
}
public function isValid()
{
return ! $this->isExpired() && $this->isFingerprint();
}
public function get($name)
{
$parsed = explode('.', $name);
$result = $_SESSION;
while ($parsed) {
$next = array_shift($parsed);
if (isset($result[$next])) {
$result = $result[$next];
} else {
return null;
}
}
return $result;
}
public function put($name, $value)
{
$parsed = explode('.', $name);
$session =& $_SESSION;
while (count($parsed) > 1) {
$next = array_shift($parsed);
if (! isset($session[$next]) || ! is_array($session[$next])) {
$session[$next] = [];
}
$session =& $session[$next];
}
$session[array_shift($parsed)] = $value;
}
}
$key = file_get_contents('./key.pem', FILE_USE_INCLUDE_PATH);
$session = new SecureSessionHandler($key);
ini_set('session.save_handler', 'files');
session_set_save_handler($session, true);
session_save_path(__DIR__ . '/sessions');
$session->start('cheese');
if (! $session->isValid(5)) {
$session->destroy('cheese');
}
は、すべてが全体的に正常に動作し、完全なセッションハンドラおよび暗号化/復号化方式があるが、問題がある:
すべては、いくつかのコンテキストのためのセッション処理コードは以下の通りです、カスタムセッションハンドラなしで正常に動作しますショッピングカートのコードを見て、すべての$ _SESSION変数を$ session-> getオブジェクトに変更すると、$ _SESSIONごとに置き換えられました。最後に変更する必要があるのは致命的なエラーです:
"$ _SESSION ['cart_contents'] = $ this-> cart_contents; " から "$ session-> get( 'cart_contents')= $ this-> cart_contents;"中
結果:
致命的なエラー:Cに書き込みコンテキストでメソッドの戻り値を使用することはできません:\ xamppの\ htdocsに\ TECKライン375
重要なコードの残りの部分を上Cart.php \私は何も残されていないことを確かめました。すべての細部を欠いている小さなポストのために炎上するよりも細部まで長いポストを持つ方が良いです。
あなたが上の量を調整することができ、ページがviewcart.phpで、コードは、このページから重要なthatsの下にある:
<input type="number" class="form-control text-center" value="<?php echo
$item["qty"]; ?>" onchange="updateCartItem(this, '<?php echo
$item["rowid"]; ?>')">
とスロー同じページ(viewcart.php)上のスクリプトアラートは以下の通りです:
<script>
function updateCartItem(obj,id){
$.get("cartAction.php", {action:"updateCartItem", id:id, qty:obj.value},
function(data){
if(data == 'ok'){
location.reload();
}else{
alert('Cart update failed, please try again.');
}
});
}
</script>
ついにアクションのコードは "updatecartitem" は、以下である、cartaction.php:
}elseif($_REQUEST['action'] == 'updateCartItem' && !empty($_REQUEST['id']))
{
$itemData = array(
'rowid' => $_REQUEST['id'],
'qty' => $_REQUEST['qty']
);
$updateItem = $cart->update($itemData);
echo $updateItem?'ok':'err';die;
}
cart.phpでの
更新機能のthats:
public function update($item = array()){
if (!is_array($item) OR count($item) === 0){
return FALSE;
}else{
if (!isset($item['rowid'], $this->cart_contents[$item['rowid']])){
return FALSE;
}else{
// prep the quantity
if(isset($item['qty'])){
$item['qty'] = filter_var($item['qty'],
FILTER_VALIDATE_INT);
// remove the item from the cart, if quantity is zero
if ($item['qty'] == 0){
unset($this->cart_contents[$item['rowid']]);
return TRUE;
}
}
// find updatable keys
$keys = array_intersect(array_keys($this-
>cart_contents[$item['rowid']]), array_keys($item));
// prep the price
if(isset($item['price'])){
$item['price'] = filter_var($item['price'],
FILTER_VALIDATE_FLOAT);
}
// product id & name shouldn't be changed
foreach(array_diff($keys, array('id', 'name')) as $key){
$this->cart_contents[$item['rowid']][$key] = $item[$key];
}
// save cart data
$this->save_cart();
return TRUE;
}
}
}
そして最後にではなく、少なくとももcart.phpでsave_cart機能:
protected function save_cart(){
$this->cart_contents['total_items'] = $this->cart_contents['cart_total']
= 0;
foreach ($this->cart_contents as $key => $val){
// make sure the array contains the proper indexes
if(!is_array($val) OR !isset($val['price'], $val['qty'])){
continue;
}
$this->cart_contents['cart_total'] += ($val['price'] * $val['qty']);
$this->cart_contents['total_items'] += $val['qty'];
$this->cart_contents[$key]['subtotal'] = ($this->cart_contents[$key]
['price'] * $this->cart_contents[$key]['qty']);
}
global $key;
global $session;
// if cart empty, delete it from the session
if(count($this->cart_contents) <= 2){
$session->forget();
return FALSE;
}else{
// original code below
$_SESSION['cart_contents'] = $this->cart_contents;
// code below is what i think will clear everything up but throws the
// error.
$session->get('cart_contents') = $this->cart_contents;
return TRUE;
}
}
カートのコードは、上記と同じファイルでありますセッションハンドラ
「$ _SESSION ['cart_contents'] = $ this-> cart_contents;」という説明をもう少し詳しく説明します。
ボタンを押してカートに余分なアイテムを追加すると、テキストフィールドが1増加し、「カートの更新に失敗しました。もう一度やり直してください」というエラーアラートが表示されます。アラートが消えて何も起こらない場合、テキストボックス内のアイテムの数量は更新されたままになりますが、ページを更新するかリンクをクリックするまで、実際のカートの数量は更新されません。
標準のセッションハンドラを使用すると、これは起こりません。すべてが完全に機能します。
この$ _SESSION ['cart_contents']変数を$ session-> get( 'cart_contents')に変更する必要がありますか?
アラートを投げずにカートを適切に更新するためにスクリプトアラートを変更することはできますが、そのセッション変数を残しても私のカスタムセッションハンドラは完璧に機能しますか?
非常に残念ですが、他の人が同様の問題を抱えているかどうかについては、できる限り明確にしています。
コードはこの観点からはかなり乱雑に思えますが、サイト全体を見渡すと、すべて意味があります。
私は最大2ヶ月間phpを使い続けていますので、できるだけ多くのものを手に入れようとしていますので、私と同行してください。明らかに、コードの大部分はきれいではありません。
私はこのセッションハンドラで過去3〜4日を費やしましたが、私は本当にそれを急にして標準の_セッションに戻ってはいけません。
すべて&助言を歓迎します、建設的な批判は軽く取られます!
本当にありがとうございました。これを通過する時間がありました。ありがとうございます!
ある人は自分の質問を説明していないし、その人がいる – rak007