Home  >  Article  >  Backend Development  >  How does PHP support CURL string certificate transfer?

How does PHP support CURL string certificate transfer?

藏色散人
藏色散人forward
2019-04-25 09:27:382888browse

Background

Recently when connecting to WeChat payment, we need to use certificates at the refund point. Since we are a SAAS platform, we need to support multi-party and multi-channel payments. If we save all certificate files in the application server, it will Affected by SLB, the files on a certain machine will be out of sync and hinder the refund process. However, if the files are stored in OSS, the backend must download them from OSS to the application server to ensure consistency. After much deliberation, we finally decided to save the certificate content in the database. Different customers correspond to one certificate file. No matter how many machines are used in the cluster, the consistency of the file can be ensured and redundant downloading steps can be avoided.

Problem

But I encountered a problem just after I did it. PHP's CURL certificate does not support the transmission of strings, and can only fill in the certificate path (the following is the official statement)

Client certificates must be specified by a path expression to a certificate store.

Solution process

My first thought is to create a blank file, write the certificate content into it, and then delete the file after the certificate is used. However, the operation of creating an entity file and then deleting it consumes performance. It's very troublesome. Is there any way to create temporary files? Yes, the tmpfile() function can help us create a temporary file and get the file path, so I wrote a method to get the temporary file path

<?php
    public function getTmpPathByContent($content)
    {
        $tmpFile = tmpfile();
        fwrite($tmpFile, $content);
        $tempPemPath = stream_get_meta_data($tmpFile);
        return $tempPemPath[&#39;uri&#39;];  ///tmp/phpXZCtAO
    }
?>

What is sad is that through this The content of the path returned by the method cannot be read at all. I even thought that I had been cheated.

file_get_contents(/tmp/phpyyiOZv): failed to open stream: No such file or directory

I found the reason after reading the official documentation. Iftmpfile()the handle reference count returned is 0 If so, the temporary file will be recycled, and the temporary path will naturally become invalid. Obviously, after the method getTmpPathByContent() is executed, the life cycle of the local variable $tmpFile will end (official document As follows)

The file is automatically removed when closed (for example, by calling fclose(), or when there are no remaining references to the file handle returned by tmpfile()), or when the script ends.

After confirming the root cause, we now urgently need to find a variable type whose life cycle terminates when the process ends to save the handle. What type can meet the conditions? static variables. The difference between static variables and local variables is that memory space is allocated for them at the beginning of the PHP life cycle and stored in the global variable area. Global variables are destroyed during the module shutdown phase. In this case, declare static variables You can make $tmpFile the reference count continue to remain greater than 0, then our code can do the following processing

<?php
    public function getTmpPathByContent($content)
    {
        static $tmpFile = null;
        $tmpFile = tmpfile();
        fwrite($tmpFile, $content);
        $tempPemPath = stream_get_meta_data($tmpFile);
        return $tempPemPath[&#39;uri&#39;];
    }
?>

Execute it again and successfully read the contents of the temporary file

-----BEGIN CERTIFICATE-----
MIIEbDCCA9WgAwIBAgIEAWJKHDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC
Q04xEjAQBgNVBAgTCUd1YW5nZG9uZzERMA8GA1UEBxMIU2hlbnpoZW4xEDAOBgNV
BAoTB1RlbmNlbnQxDDAKBgNVBAsTA1dYRzETMBEGA1UEAxMKTW1wYXltY2hDQTEf
MB0GCSqGSIb3DQEJARYQbW1wYXltY2hAdGVuY2VudDAeFw0xNzA4MDcwOTIxNDda
Fw0yNzA4MDUwOTIxNDdaMIGbMQswCQYDVQQGEwJDTjESMBAGA1UECBMJR3Vhbmdk
b25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UEChMHVGVuY2VudDEOMAwGA1UE
CxMFTU1QYXkxMDAuBgNVBAMUJ+a3seWcs+W4guaYjua6kOi9r+S7tuiCoeS7veac
iemZkOWFrOWPuDERMA8GA1UEBBMIMTAyNTkyODEwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDg2D3++uOxY/yMGQPBnROvyYimnCsfGE0dnqdGUTCykqBh
yfv82zE1/St/4DQX2QDiIvLif+sMGcYwF4bkzdY+HgitYLI0k5o/5LCNZOMctuio
kdYC2bNdWHq2y9S5UWLQR1Zvq+6QyPBVBVY9yq9xtQhIlUTsZnICAp3iQLfQUR3l
aEdH9IERoRUIkbyb8oX5ONQz4P9jOeE9C5iwx0QrH4s01NFhkhr8JHlugRLpo9vA
xGgi/48fOlONj6wWal5Gt0OvvEbIwgQwya15KBX2YeGnZvYBQa+lQMeXEqZSFie3
G+wGvbtlONczQEtp+JDxLZLUS/FT7U0TQN/t8JDvAgMBAAGjggFGMIIBQjAJBgNV
HRMEAjAAMCwGCWCGSAGG+EIBDQQfFh0iQ0VTLUNBIEdlbmVyYXRlIENlcnRpZmlj
YXRlIjAdBgNVHQ4EFgQUjDJ75bu3Roog7XOH6uFAdZ6kpcIwgb8GA1UdIwSBtzCB
tIAUPgUm9iJitBVbiM1kfrDUYqflhnShgZCkgY0wgYoxCzAJBgNVBAYTAkNOMRIw
EAYDVQQIEwlHdWFuZ2RvbmcxETAPBgNVBAcTCFNoZW56aGVuMRAwDgYDVQQKEwdU
ZW5jZW50MQwwCgYDVQQLEwNXWEcxEzARBgNVBAMTCk1tcGF5bWNoQ0ExHzAdBgkq
hkiG9w0BCQEWEG1tcGF5bWNoQHRlbmNlbnSCCQC7VJcrvADoVzAOBgNVHQ8BAf8E
BAMCBsAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEA
ucJLJkkHxlqQCEapZOWmySutqNVZxFbqyG//UXxxpA/1yG4e+KmufKZWv+c+MtYI
8i0KDDCv/UE+kkFIrHYDDKsdLRpxrYOUHGoqq0c7yBJ6Dimgy6m8U8FsEv3HtUR2
8g5xrg2Tc5MPWEp9ncEw575hGk0CXLDGOkI1nU+pGqk=
-----END CERTIFICATE-----

Now you can set the generated temporary file address to CURLOPT_SSLCERT

<?php
    $sslCertPath = getTmpPathByContent($content);
    curl_setopt($ch,CURLOPT_SSLCERT, $sslCertPath);
    //......
?>

The above is the detailed content of How does PHP support CURL string certificate transfer?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:cnblogs.com. If there is any infringement, please contact admin@php.cn delete