You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确认证Shopware 6的base-app-url请求?

我最近在基于Shopware 6 Admin SDK扩展后台功能时,踩了一个关于base-app-url请求认证的坑,折腾了好一阵才找到问题所在,分享给遇到同样问题的朋友:

问题背景

当我们借助Admin SDK扩展Shopware 6后台功能时,需要在应用的manifest文件里配置base-app-url作为入口点。所有请求都需要正确的认证,但坑点来了:base-app-url的GET请求没办法像普通模块的GET请求那样完成认证——我自己写的Node.js认证代码,验证模块请求完全正常,但一验证base-app-url的请求就抛出Signature could not be verified!错误。

问题细节

先给大家看一下相关的内容:

  1. 正常工作的模块请求示例(签名验证无问题):
GET /module/my-module?shop-id=SW12345&timestamp=1699999999&signature=abc123...&privileges=[]

对应的PHP验证代码(官方风格,可正常验证):

public function validate(Request $request): bool
{
    $query = $request->query->all();
    $signature = $query['signature'] ?? '';
    unset($query['signature']);
    
    $signedString = http_build_query($query, '', '&', PHP_QUERY_RFC3986);
    $expectedSignature = hash_hmac('sha256', $signedString, $this->secret);
    
    return hash_equals($expectedSignature, $signature);
}
  1. base-app-url请求示例(验证失败):
GET /my-app?shop-id=SW12345&timestamp=1699999999&signature=def456...&privileges=%5B%22product%3Aread%22%5D
  1. 最初的Node.js认证代码(有问题):
function validateRequest(req, secret) {
    const { signature, ...query } = req.query;
    const signedString = new URLSearchParams(query).toString();
    const expectedSignature = crypto.createHmac('sha256', secret)
        .update(signedString)
        .digest('hex');
    
    return expectedSignature === signature;
}

根因分析

问题出在Express的自动解码行为上:Express会自动把req.query里的参数进行URL解码,比如把%5B%22product%3Aread%22%5D解码成["product:read"]。但Shopware生成签名时,用的是编码后的原始query参数,如果我们用解码后的参数重新生成签名字符串,自然就和Shopware传来的签名对不上了,也就抛出了验证失败的错误。

解决方案

要解决这个问题,我们需要获取Shopware传来的原始未解码的query字符串,而不是用Express解码后的req.query。可以通过req.originalUrl来提取原始query部分,再处理:

修正后的Node.js代码:

const crypto = require('crypto');

function validateRequest(req, secret) {
    // 从原始URL中提取query部分(去掉路径和开头的?)
    const queryString = req.originalUrl.split('?')[1] || '';
    // 把query字符串拆分成键值对,排除signature参数
    const params = new URLSearchParams(queryString);
    const signature = params.get('signature');
    params.delete('signature');
    
    // 用原始的编码参数生成签名字符串
    const signedString = params.toString();
    const expectedSignature = crypto.createHmac('sha256', secret)
        .update(signedString)
        .digest('hex');
    
    return expectedSignature === signature;
}

这样就能确保我们用和Shopware生成签名时完全一致的参数字符串来做HMAC验证,自然就能通过认证了。

内容的提问来源于stack exchange,提问作者lucamario

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 10:22:54