我在多个域(不是子域)上运行 Opencart v2.3.0.2 多商店,并希望在主站点上结帐,该站点包含所有商店的所有产品。
由于很难在多个域上共享会话,因此认为最好在结帐过程之前强制用户登录(所有商店的登录凭据都相同,并且购物车项目是共享的)。但是,默认情况下,用户必须分别登录每个商店 -我如何为所有商店创建单一登录?登录后,我可以将它们发送到主站点进行结帐。
如果您认为单次结帐有更好的方法,请提出建议。
我在多个域(不是子域)上运行 Opencart v2.3.0.2 多商店,并希望在主站点上结帐,该站点包含所有商店的所有产品。
由于很难在多个域上共享会话,因此认为最好在结帐过程之前强制用户登录(所有商店的登录凭据都相同,并且购物车项目是共享的)。但是,默认情况下,用户必须分别登录每个商店 -我如何为所有商店创建单一登录?登录后,我可以将它们发送到主站点进行结帐。
如果您认为单次结帐有更好的方法,请提出建议。
如果它足以让您在所有商店中简单地登录您的用户(并且您不会使用相同的会话 ID),您可以
1)为您的所有商店实施登录链接锁定
2)成功登录您的一家商店后,将所有其他商店的登录链接发回给他
3)通过ajax执行每个登录链接。
因此,您将登录到一个前台,但会自动登录到所有商店
注意:最好是您的登录表单本身也是由 ajax 提供的,因此用户只需输入凭据,如果成功,您将看到更长的 ajax 负载,在此期间您将一一执行其余登录链接
你想要的是单点登录。有很多方法可以做到这一点,一种更安全的方法是使用 JSON Web Token(如https://github.com/lcobucci/jwt)。简而言之,这些是签名的 JSON 字符串,因此您可以使用异步加密的强大功能!;)
Opencart 2 设置了两个 HTTPOnly cookie PHPSESSID和默认识别客户。因此,我决定在商店中共享/同步它们。
1. 获取 Javascript 的商店列表
也许不是最好的,但在/catalog/controller/common/header.php
我分配了一个变量:
$this->load->language('setting/store');
$this->load->model('setting/store');
$this->load->model('setting/setting');
$data['multi_stores'] = array();
$data['multi_stores'][] = array(
'store_id' => 0,
'name' => 'Main Site',
'url' => 'https://mysite.co.uk/',
'is_current' => stripos('https://mysite.co.uk/', $_SERVER['SERVER_NAME']) !== false
);
$results = $this->model_setting_store->getStores();
foreach ($results as $result) {
$data['multi_stores'][] = array(
'store_id' => $result['store_id'],
'name' => $result['name'],
'url' => $result['url'],
'is_current' => stripos($result['url'], $_SERVER['SERVER_NAME']) !== false
);
}
2.比在模板中我使用它:
<script type="text/javascript">
var multiStores = <?php echo json_encode($multi_stores); ?>;
</script>
3. 创建了两个 PHP 脚本来设置和获取 cookie:
获取Cookies.php:
$cookies = array(
'PHPSESSID' => $_COOKIE['PHPSESSID'],
'default' => $_COOKIE['default'],
'currency' => $_COOKIE['currency'],
'language' => $_COOKIE['language']
);
header('Content-Type: application/json');
echo json_encode( $cookies );
设置Cookies.php:
$response = array(
'status' => 'ok'
);
/* Format: [cookie name] => [expire days] */
$cookies_to_sync = array(
'PHPSESSID' => '',
'default' => '',
'currency' => 30,
'language'=> 30
);
/* If no expire was set, than set session HTTPOnly cookie (last, 7th parameter 'true') */
foreach( $cookies_to_sync as $cname=>$cexpire ) {
if( $_POST[$cname] ) {
if( $cexpire ) {
/* 86400 seconds per day */
setcookie($cname, $_POST[$cname], time() + (86400 * $cexpire), '/', null, null, false);
} else {
setcookie($cname, $_POST[$cname], null, '/', null, null, true);
};
};
};
/* Browser requests a JSON, cross-origin enabled, with OPTIONS enabled to set cookies */
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Max-Age: 1000');
header('Content-Type: application/json');
echo json_encode( $response );
4. Javascript 部分:
- 请注意,为了跨域发送/设置 cookie,我们在 PHP 标头中设置了OPTIONS$.ajax
xhrFields
,对于 jQuery,我们添加了option withCredentials: true
。考虑到这一点,我创建了同步网站 cookie 的方法:
this.syncWebsites = function() {
if( typeof multiStores!='undefined' ) {
that.stores = multiStores;
that.synced = that.readCookie('synced');
if( !that.synced ) {
/* First get cookies */
$.getJSON( "catalog/view/theme/mytheme/javascript/getCookies.php", function( data ) {
/* Send to other sites */
$.each(that.stores, function(i, store) {
if( !store.is_current ) {
/* Send to other sites, MUST use xhrFields->withCredentials: true, to set cookies */
$.ajax({
url: store.url.replace('http://', '//') + "catalog/view/theme/mytheme/javascript/setCookies.php",
xhrFields: {
withCredentials: true
},
type: "post",
crossDomain: true,
data: data,
dataType: "json",
success:function(result){
that.echo(JSON.stringify(result));
},
error:function(xhr, status, error){
that.echo(status);
}
});
};
});
that.createCookie('synced', 'Yes', '');
});
};
};
};
请注意:我创建了synced
cookie,因此此请求仅在会话期间发生一次。
最终结果: 我们在所有网站上同步了所有 Opencart 2 客户。
安全注意事项: 所有网站都使用 SSL 加密。窃取信息的危险与访问所有这些网站的危险相同。