Shopware 6应用中安全获取前台客户会话及店铺信息的问询
问题描述
我需要在后端获取前台已登录客户的信息,以此为客户提供多种奖励。我开发了一个继承自plugin.class的插件,通过Store API的store-api/account/customer路由获取客户信息,将客户ID发送至我的后端;同时通过window.location.protocol和window.location.hostname解析admin api的shop_url。
但我认为这种方式既不安全也不准确(销售渠道与admin api的域名可能不同),想了解是否可以获取一个安全的唯一客户令牌,同时正确解析出shop_url和客户ID。我在官方文档中未找到相关安全方案,特此咨询。
补充的插件代码:
import Plugin from 'src/plugin-system/plugin.class'; import StoreApiClient from 'src/service/store-api-client.service'; const storeClient = new StoreApiClient(); const handleUser = (data, request) => { let unsecuredUserId = null; if (request.status === 200) { try { const user = JSON.parse(data); unsecuredUserId = user.id || null; } catch (e) {} } doSomethingWith(unsecuredUserId); } export default class SaylPlugin extends Plugin { init() { storeClient.get('store-api/account/customer', handleUser); } }
解决方案
1. 安全获取客户身份凭证
直接传递客户ID存在被篡改的风险,建议使用Shopware内置的**上下文令牌(sw-context-token)**来验证客户身份:
- 调用
store-api/account/customer接口后,可从响应头中提取sw-context-token,这是Shopware用于验证客户会话的安全令牌,无法被前端篡改。 - 将该令牌发送到你的后端,后端通过Shopware的Admin API或Store API调用验证接口,即可获取可信的客户ID及相关信息。
2. 正确获取店铺shop_url
不要依赖前端域名解析,通过后端注入的方式获取准确的店铺URL:
- 在插件的PHP后端逻辑中,订阅
FrontendRenderEvent事件,通过SystemConfigService获取当前销售渠道对应的shopUrl配置:
public function onFrontendRender(FrontendRenderEvent $event): void { $salesChannelId = $event->getSalesChannelContext()->getSalesChannel()->getId(); $shopUrl = $this->systemConfigService->get('core.shopSettings.shopUrl', $salesChannelId); $event->setParameter('saylShopUrl', $shopUrl); }
- 前端插件可直接通过
this.options.saylShopUrl获取该值,确保和销售渠道配置的店铺URL一致。
3. 完整安全流程
- 前端插件调用Store API获取客户信息,同时提取响应头中的
sw-context-token。 - 前端将
sw-context-token和后端注入的shop_url一同发送到你的后端服务。 - 你的后端使用
shop_url调用Shopware的API,通过sw-context-token验证客户身份,获取真实的客户ID。 - 验证通过后,为客户发放对应奖励。
优化后的前端插件代码
import Plugin from 'src/plugin-system/plugin.class'; import StoreApiClient from 'src/service/store-api-client.service'; export default class SaylPlugin extends Plugin { init() { const storeClient = new StoreApiClient(); storeClient.get('store-api/account/customer', (data, request) => { if (request.status !== 200) return; try { const user = JSON.parse(data); const contextToken = request.getResponseHeader('sw-context-token'); const shopUrl = this.options.saylShopUrl; if (contextToken && shopUrl) { // 发送安全凭证到你的后端 fetch('你的后端接口地址', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contextToken, shopUrl }) }); } } catch (e) { console.error('处理客户信息失败:', e); } }); } }
内容的提问来源于stack exchange,提问作者bibiseb
相关产品推荐
相关产品推荐

