Laravel 9加密签名字符串提交外部URL遇400错误排查
Laravel 9中加密签名提交外部URL遇400 Bad Request排查
我的操作流程
- 拼接字符串:
$data = 'stringA' . 'stringB'; - 公钥加密字符串:
加密函数:
调用加密:// Encrypt String using Public Certificate function encrypt($plainText, $publicCertificatePath) { $cert = file_get_contents($publicCertificatePath); $cert = openssl_x509_read($cert); $publicKey = openssl_get_publickey($cert); // openssl_free_key($cert); $cipherText = ''; openssl_public_encrypt($plainText, $cipherText, $publicKey, OPENSSL_PKCS1_PADDING); return base64_encode($cipherText); }// public certificate was provided by the URL I am submitting data to $encryptedCredentials = encrypt($data, storage_path('app/certificates/public-cert.pem')); - 生成自签名证书:
function generateCertificate($commonName, $countryName, $stateOrProvinceName, $localityName, $organizationName, $organizationalUnitName, $emailAddress, $outputPath) { // Generate private key $process = new Process([ 'openssl', 'genpkey', '-algorithm', 'RSA', '-out', $outputPath . '.key.pem', '-aes256', '-pass', 'pass:password', '-outform', 'PEM' ]); $process->run(); if (!$process->isSuccessful()) { throw new ProcessFailedException($process); } // Generate CSR $process = new Process([ 'openssl', 'req', '-new', '-key', $outputPath . '.key.pem', '-out', $outputPath . '.csr.pem', '-passin', 'pass:password', '-subj', "/C=$countryName/ST=$stateOrProvinceName/L=$localityName/O=$organizationName/OU=$organizationalUnitName/CN=$commonName/emailAddress=$emailAddress" ]); $process->run(); if (!$process->isSuccessful()) { throw new ProcessFailedException($process); } // Generate self-signed certificate $process = new Process([ 'openssl', 'x509', '-req', '-days', '365', '-in', $outputPath . '.csr.pem', '-signkey', $outputPath . '.key.pem', '-out', $outputPath . '.cert.pem', '-passin', 'pass:password' ]); $process->run(); if (!$process->isSuccessful()) { throw new ProcessFailedException($process); } } generateCertificate('name', 'UG', 'state', 'Location', 'frd', 'Ecom', 'myemail@gmail.com', storage_path('app/certificates/')); - 私钥签名加密内容:
签名函数:
调用签名:// Sign String using MDA Private Certificate function signString(string $text, string $privateKeyPath, string $passphrase): string { // Load private key $privateKey = openssl_get_privatekey(file_get_contents($privateKeyPath), $passphrase); // Sign the string openssl_sign($text, $signature, $privateKey, OPENSSL_ALGO_SHA256); // Free the key from memory openssl_free_key($privateKey); // Return the signature as a base64-encoded string return base64_encode($signature); }// sign using MDA private certificate. $signedCredentials = signString($encryptedCredentials, storage_path('app/certificates/private.pem'), ''); - 发送请求到外部URL:
$url = "https://urlfromprovider";$data = []; $postData = http_build_query($data); // return $postData; $opts = array( 'http' => array( 'method' => 'POST', 'header' => "Content-Type: text/xml\r\n", 'content' => $postData ) ); $context = stream_context_create($opts); $response = file_get_contents($url, false, $context, 40000); return $response;
问题:严格按服务商要求操作,但始终返回400 Bad Request,可能的原因有哪些?
排查方向
1. 请求数据为空或格式不匹配
你定义的$data是空数组,http_build_query($data)生成空字符串,但请求头设置为Content-Type: text/xml,服务商大概率需要你提交包含加密数据和签名的XML结构内容,而非空值。需按服务商要求的XML格式填充$encryptedCredentials和$signedCredentials,示例:
$xml = <<<XML <request> <encryptedData>$encryptedCredentials</encryptedData> <signature>$signedCredentials</signature> </request> XML; $opts['http']['content'] = $xml;
2. 私钥路径与密码不匹配
生成自签名证书时,私钥文件路径是storage_path('app/certificates/.key.pem')($outputPath结尾带斜杠,拼接后文件名是.key.pem),但你签名时用的是storage_path('app/certificates/private.pem'),路径完全不符。另外生成私钥时设置了密码password,但签名时$passphrase传空字符串,导致无法正确加载私钥,签名失效。
3. 加密/签名算法不匹配
服务商可能要求特定的加密填充方式(比如OPENSSL_PKCS1_OAEP_PADDING而非当前的OPENSSL_PKCS1_PADDING)或签名哈希算法(比如OPENSSL_ALGO_SHA1),需核对服务商文档确认算法一致性。
4. 证书相关问题
- 生成的私钥是AES256加密的,加载时必须提供正确密码;
- 若服务商要求提前上传你的自签名证书公钥到他们系统,未上传会导致签名无法验证;
- 检查证书文件权限,确保Laravel进程能正常读取证书。
5. 请求头不完整
服务商可能要求额外请求头(比如Accept、自定义签名校验头、Content-Length),需补充完整符合要求的请求头。
6. 字符串拼接规则错误
服务商可能要求拼接时添加分隔符(如stringA|stringB)、按特定顺序拼接、包含其他参数,需再次核对拼接规则是否完全符合要求。
内容的提问来源于stack exchange,提问作者jonahgeek
相关产品推荐
相关产品推荐

