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

MuleSoft HTTP请求报403 Forbidden,PHP Curl却正常运行求助

排查MuleSoft HTTP请求403 Forbidden问题(对比PHP Curl正常代码)

正常运行的PHP Curl代码

$url="XXXXXX";
$key="XXXXXX";
$data='[{"producerNumber":"0500555"}]';
$relativeUrl = '/producer/npn';
$date = gmdate('Y-m-d\TH:i:s\Z');
$dataToSign = $relativeUrl.$data.$date.$key;
$encoded= base64_encode(
            hash_hmac('sha256', $dataToSign, base64_decode($key), true)
        );
$curl = curl_init();
curl_setopt_array($curl, array(
          CURLOPT_URL => $url,
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_ENCODING => "",
          CURLOPT_MAXREDIRS => 10,
          CURLOPT_TIMEOUT => 30,
          CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
          CURLOPT_CUSTOMREQUEST => "POST",
          CURLOPT_POSTFIELDS => $data,
          CURLOPT_HTTPHEADER => array(
            "Content-Type: application/json",
            "Accept: application/json",
            "Accept: */*",
            "REQUEST_CLIENT_ID: XXXX",
            "REQUEST_DATE: " . $date,
            "REQUEST_SIGNATURE: " . $encoded,
          ),
        ));
$response = curl_exec($curl);

报错的MuleSoft HTTP请求配置

<http:request method="POST" doc:name="Request" doc:id="82492d2a-cd5e-417d-8078-43daaa982c45" config-ref="HTTP_Request_configuration" path="/npn">
    <http:body ><![CDATA[[{"producerNumber":"0500555"}]]]></http:body>
    <http:headers><![CDATA[#[%dw 2.0
    import dw::Crypto
    import * from dw::core::Binaries
    output application/json
    ---
    {
        "Content-Type": "application/json",
        "Accept": "application/json",
        "Accept": "*/*",
        "REQUEST_CLIENT_ID": "XXXXX",
        "REQUEST_DATE": vars.datevalue,
        "REQUEST_SIGNATURE": toBase64(Crypto::HMACWith(fromBase64(vars.key as Binary),
        vars.relativeUrl ++ vars.producerNo ++ vars.datevalue ++ vars.key as Binary,"HmacSHA256"
      ))
    }]]]></http:headers>
</http:request>

错误日志

ERROR 2025-02-20 17:00:38,760 [[MuleRuntime].uber.05: [car-api].uber@org.mule.runtime.core.privileged.processor.chain.AbstractMessageProcessorChain.initialise:648 @778984a7] [processor: post:\postNpn:application\json:car-api-config/processors/5; event: 7fb0dc10-efde-11ef-852b-8a2347d95a3e] org.mule.runtime.core.internal.exception.OnErrorPropagateHandler: 

Message               : HTTP POST on resource 'His is my URL so hiding it' failed: forbidden (403).
Element               : post:\postNpn:application\json:car-event-api-config/processors/5 @ car-events-api:car-events-api.xml:221 (Request)
Element DSL           : <http:request method="POST" doc:name="Request" doc:id="82492d2a-cd5e-417d-8078-43daaa982c45" config-ref="HTTP_Request_configuration" path="/npn">

<http:body><![CDATA[
[{"producerNumber":"123456"}]
]]></http:body>
<http:headers><![CDATA[
#[%dw 2.0
import dw::Crypto
import * from dw::core::Binaries
output application/json
---
{
    "Content-Type": "application/json",
    "Accept": "application/json",
    "Accept": "*/*",
    "REQUEST_CLIENT_ID": "moo-com",
    "REQUEST_DATE": vars.datevalue,
    "REQUEST_SIGNATURE": toBase64(Crypto::HMACWith(fromBase64(vars.key as Binary),
    vars.relativeUrl ++ vars.producerNo ++ vars.datevalue ++ vars.key as Binary,"HmacSHA256"
  ))
}]
]]></http:headers>
</http:request>

Error type            : HTTP:FORBIDDEN
FlowStack             : at post:\postNpn:application\json:car-api-config(post:\postNpn:application\json:car-event-api-config/processors/5 @ car-events-api:car-events-api.xml:221 (Request))
at car-events-api-main(car-events-api-main/processors/0 @ car-events-api:car-events-api.xml:35)

  (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************

ERROR 2025-02-20 17:00:38,768 [[MuleRuntime].uber.05: [car-api].uber@org.mule.runtime.core.privileged.processor.chain.AbstractMessageProcessorChain.initialise:648 @778984a7] [processor: post:\postNpn:application\json:car-api-config/processors/5; event: 7fb0dc10-efde-11ef-852b-8a2347d95a3e] org.mule.runtime.core.internal.exception.OnErrorPropagateHandler: 


> ********************************************************************************
> Message               : HTTP POST on resource 'This is my URL so hiding it' failed: forbidden (403).
Element               : (None)
Element DSL           : (None)
Error type            : HTTP:FORBIDDEN
FlowStack             : (None)

  (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************

问题排查与修复方案

对比PHP和Mule的签名生成逻辑,核心差异导致403的原因如下:

1. 签名拼接内容不匹配

PHP中签名的原始字符串是:

$dataToSign = $relativeUrl.$data.$date.$key;

即相对路径 + 完整请求体 + UTC日期 + 密钥字符串。

而Mule中错误地用vars.producerNo(单个生产者编号)替换了完整请求体,并且把密钥转成Binary后拼接,和PHP的字符串拼接逻辑不一致。

2. 日期格式需严格对齐

PHP生成的日期是UTC时区的ISO8601格式:gmdate('Y-m-d\TH:i:s\Z'),Mule的vars.datevalue必须完全匹配该格式(包括T分隔符和末尾的Z),不能有任何时区或格式差异。

3. 相对路径需一致

PHP中$relativeUrl = '/producer/npn',但Mule请求的path是/npn,需确保vars.relativeUrl的值和PHP一致。

修正后的Mule配置(核心部分)

<http:request method="POST" doc:name="Request" doc:id="82492d2a-cd5e-417d-8078-43daaa982c45" config-ref="HTTP_Request_configuration" path="/npn">
    <http:body ><![CDATA[[{"producerNumber":"0500555"}]]]></http:body>
    <http:headers><![CDATA[#[%dw 2.0
    import dw::Crypto
    import * from dw::core::Binaries
    output application/json
    ---
    {
        "Content-Type": "application/json",
        "Accept": "application/json",
        "Accept": "*/*",
        "REQUEST_CLIENT_ID": "XXXXX",
        "REQUEST_DATE": now() >> "UTC" as String {format: "yyyy-MM-dd'T'HH:mm:ss'Z'"},
        "REQUEST_SIGNATURE": toBase64(
            Crypto::HMACWith(
                fromBase64(vars.key),
                vars.relativeUrl ++ write(payload, "application/json") ++ (now() >> "UTC" as String {format: "yyyy-MM-dd'T'HH:mm:ss'Z'"}) ++ vars.key,
                "HmacSHA256"
            )
        )
    }]]]></http:headers>
</http:request>

额外验证步骤

  • 确保vars.relativeUrl的值为/producer/npn,和PHP一致。
  • 检查请求体的字符串格式:PHP中$data是紧凑的[{"producerNumber":"0500555"}],Mule的write(payload, "application/json")需生成完全相同的字符串(无多余换行、空格)。
  • 可以临时将PHP和Mule生成的dataToSign、encoded值输出日志,对比是否完全一致,快速定位差异点。

内容的提问来源于stack exchange,提问作者Veera Raghava Prasad Govindara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:44:51