我到處搜索了這個,我找不到一個體面的代碼。如何使用GSOAP訪問Amazon AWS S3服務?如何使用適用於C和C++的GSOAP訪問Amazon AWS S3?
回答
以下代碼來自OP。最初,這篇文章包含了問題和答案,我將它轉換爲Q格式。
簽名必須是格式
base64encode((HMAC-SHA1(ActionName+"AmazonS3"+XMLTimestamp)))
的HMAC,SHA1and B64 utils的是 openssl提供。
SOAP請求的格式由 wsdl給出。
REST接口不同。
wsdl2h
後以產生報頭和soapcpp2以生成gSOAP的 客戶端代碼以下將代碼以訪問服務:
使用編譯器預處理器指令WITH_OPENSSL
進行構建。鏈接 庫libeay32
和ssleay32
。
#include "AmazonS3SoapBinding.nsmap" //generated from soapcpp2
#include "soapAmazonS3SoapBindingProxy.h" //generated from soapcpp2
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
/* convert to base64 */
std::string base64_encodestring(char* text, int len) {
EVP_ENCODE_CTX ectx;
int size = len*2;
size = size > 64 ? size : 64;
unsigned char* out = (unsigned char*)malloc(size);
int outlen = 0;
int tlen = 0;
EVP_EncodeInit(&ectx);
EVP_EncodeUpdate(&ectx,
out,
&outlen,
(const unsigned char*)text,
len
);
tlen += outlen;
EVP_EncodeFinal(&ectx, out+tlen, &outlen);
tlen += outlen;
std::string str((char*)out, tlen);
free(out);
return str;
}
/* return the utc date+time in xml format */
const char* xml_datetime() {
/*"YYYY-mm-ddTHH:MM:SS.000Z\"*/
const int MAX=25;
static char output[MAX+1];
time_t now = time(NULL);
strftime(output, MAX+1, "%Y-%m-%dT%H:%M:%S.000Z", gmtime(&now));
std::cout <<output<<std::endl;
return output;
}
/* first argument is the signing key */
/* all subsequent argumets are concatenated */
/* must end list with NULL */
char* aws_signature(char* key, ...) {
unsigned int i, len;
char *data, **list = &key;
static char hmac[EVP_MAX_MD_SIZE];
for (i = 1, len = 0; *(list+i) != NULL; ++i) {
len += strlen(*(list+i));
}
data = (char*)malloc(sizeof(char) * (len+1));
if (data) {
for (i = 1, len = 0 ; *(list+i) != NULL ; ++i) {
strncpy(data+len, *(list+i), strlen(*(list+i)));
len += strlen(*(list+i));
}
data[len]='\0';
std::cout<<data<<std::endl;
HMAC(EVP_sha1(),
key, strlen(key),
(unsigned char*)data, strlen(data),
(unsigned char*) hmac, &len
);
free(data);
}
std::string b64data=base64_encodestring(hmac, len);
strcpy(hmac,b64data.c_str());
return hmac;
};
int main(void) {
AmazonS3SoapBindingProxy client;
soap_ssl_client_context(&client,
/* for encryption w/o authentication */
SOAP_SSL_NO_AUTHENTICATION,
/* SOAP_SSL_DEFAULT | SOAP_SSL_SKIP_HOST_CHECK, */
/* if we don't want the host name checks since
* these will change from machine to machine */
/*SOAP_SSL_DEFAULT,*/
/* use SOAP_SSL_DEFAULT in production code */
NULL, /* keyfile (cert+key): required only when
client must authenticate to server
(see SSL docs to create this file) */
NULL, /* password to read the keyfile */
NULL, /* optional cacert file to store trusted
certificates, use cacerts.pem for all
public certificates issued by common CAs */
NULL, /* optional capath to directory with trusted
certificates */
NULL /* if randfile!=NULL: use a file with random
data to seed randomness */
);
/* use this if you are behind a proxy server.....
client.proxy_host="proxyserver"; // proxy hostname
client.proxy_port=4250;
client.proxy_userid="username"; // user pass if proxy
client.proxy_passwd="password"; // requires authentication
client.proxy_http_version="1.1"; // http version
*/
_ns1__ListAllMyBuckets buk_req;
_ns1__ListAllMyBucketsResponse buk_resp;
ns1__ListAllMyBucketsResult buk_res;
buk_res.soap=&client;
buk_req.AWSAccessKeyId=new std::string("ACCESSKEY");
buk_req.soap=&client;
/* ListAllMyBuckets is the method I want to call here.
* change it for other S3 services that you wish to call.*/
char *sig=aws_signature(
"SECRETKEY",
"AmazonS3",
"ListAllMyBuckets",
xml_datetime(),
NULL
);
buk_req.Signature=new std::string(sig);
buk_req.Timestamp=new time_t(time(NULL));
buk_resp.soap=&client;
buk_resp.ListAllMyBucketsResponse=&buk_res;
client.ListAllMyBuckets(&buk_req,&buk_resp);
client.soap_stream_fault(std::cout);
std::vector<ns1__ListAllMyBucketsEntry * >::iterator itr;
for(itr=buk_resp.ListAllMyBucketsResponse->Buckets->Bucket.begin();
itr!=buk_resp.ListAllMyBucketsResponse->Buckets->Bucket.end();
itr++
) {
std::cout<<(*itr)->Name<<std::endl;
}
}
我怎樣才能訪問Amazon AWS S3使用gSOAP的C和C++?
步驟1
使用gSOAP的的wsd2lh工具Amazon的S3 WSDL轉換爲接口頭文件aws-s3.h:
wsdl2h -t typemap.dat -o aws-s3.h http://doc.s3.amazonaws.com/2006-03-01/AmazonS3.wsdl
使用選項-c
生成C源代碼,而不是默認的C++源代碼。 typemap.dat
文件位於gSOAP發行版的gsoap目錄中。
步驟2
使用來自wsdl2h工具創建的頭文件中的soapcpp2工具。
soapcpp2 -C -j aws-s3.h
這產生與來自AWS-s3.h頭C++服務代理和對象(-j
選項)的客戶端代碼(-C
選項)。 C代碼省略-j
。
步驟3
使用自動生成的代理AmazonS3SoapBindingProxy
方法來訪問AWS S3和創建用於AWS S3 base64編碼,HMAC-SHA1散列簽名。簽名是使用HMAC-SHA1的base64編碼版本的字符串散列串"AmazonS3" + OPERATION_NAME + Timestamp
:
/*
createbucket.cpp
Example AWS S3 CreateBucket service invocation
*/
#include "soapAmazonS3SoapBindingProxy.h"
#include "AmazonS3SoapBinding.nsmap"
#include <fstream>
// Make allocation of primitive values quick and easy:
template<class T>
T * soap_make(struct soap *soap, T val) {
T *p = (T*)soap_malloc(soap, sizeof(T));
*p = val;
return p;
}
// Make base64-encoded, HMAC-SHA1 hashed signature for AWS S3
std::string soap_make_s3__signature(struct soap *soap, char const *operation, char const *key) {
std::string signature = "AmazonS3";
signature += operation;
char UTCstamp[40]; //to hold ISO 8601 time format
time_t now;
time(&now);
strftime(UTCstamp, sizeof UTCstamp, "%Y-%m-%dT%H:%M:%S.000Z", gmtime(&now));
signature += UTCstamp;
// Get the HMAC-SHA1 digest of the signature string
unsigned char * digest;
digest = HMAC(EVP_sha1(), key, strlen(key),
(unsigned char*)(signature.c_str()),
signature.length(), NULL, NULL);
char signatureBase64[20];
// Convert the digest to base64
soap_s2base64(soap, digest, signatureBase64, sizeof signatureBase64);
return std::string(signatureBase64);
}
// Read access keys from file generated by AWS CLI
bool getAWSKeys(std::string path, std::string user, std::string &accessKey, std::string &secretKey) {
std::ifstream credentialsFile(path.c_str());
if (!credentialsFile.is_open())
return false;
std::string line;
while (std::getline(credentialsFile, line)) {
// Keep going until we get to the desired user
if (line.find(user) == std::string::npos)
continue;
while (std::getline(credentialsFile, line)) {
// Keep going until we get to the access key lines
if (line.find("aws_access_key_id") == std::string::npos)
continue;
// Grab keys and trim whitespace
size_t first, last;
accessKey = line.substr(line.find_first_of('=')+1);
first = accessKey.find_first_not_of(' ');
if (first == std::string::npos)
return false;
last = accessKey.find_last_not_of(' ');
accessKey.substr(first, last-first+1).swap(accessKey);
std::getline(credentialsFile, line);
secretKey = line.substr(line.find_first_of('=')+1);
first = secretKey.find_first_not_of(' ');
if (first == std::string::npos)
return false;
last = secretKey.find_last_not_of(' ');
secretKey.substr(first, last-first+1).swap(secretKey);
return true;
}
}
return false;
}
int main(int argc, char **argv) {
// Load AWS keys from file
std::string accessKey, secretKey;
// Use the path to your AWS credentials file
std::string credentialsFile = (argc > 2 ? argv[2] : "path_to_aws_credentials_file");
std::string user = "default";
if (!getAWSKeys(credentialsFile, user, accessKey, secretKey)) {
std::cout << "Couldn't read AWS keys for user " << user
<< " from file " << credentialsFile << '\n';
return 0;
}
// Create a proxy to invoke AWS S3 services
AmazonS3SoapBindingProxy aws(SOAP_XML_INDENT);
// Create bucket
// Set the arguments of the CreateBucket service operation
_s3__CreateBucket createBucketReq;
std::string bucketName = (argc > 1 ? argv[1] : "BucketName");
createBucketReq.Bucket = bucketName;
createBucketReq.AWSAccessKeyId = soap_new_std__string(aws.soap);
*createBucketReq.AWSAccessKeyId = accessKey;
createBucketReq.Timestamp = soap_make(aws.soap, time(0));
createBucketReq.Signature = soap_new_std__string(aws.soap);
*createBucketReq.Signature = soap_make_s3__signature(aws.soap,
"CreateBucket",
secretKey.c_str());
// Store the result of the service
_s3__CreateBucketResponse createBucketRes;
// Create a bucket
if (aws.CreateBucket(&createBucketReq, createBucketRes)) {
aws.soap_stream_fault(std::cerr);
}
/*
NOTE: you must add the line:
_s3__CreateBucketResponse = $ s3__CreateBucketResult* CreateBucketResponse;
to the typemap.dat file because Amazon's response doesn't match
their promised schema. This adds the variable CreateBucketResponse
to the _s3__CreateBucketResponse class so we can access the response.
*/
else if (createBucketRes.CreateBucketResponse) {
s3__CreateBucketResult &result = *createBucketRes.CreateBucketResponse;
std::cout << "You are the owner of bucket '" << result.BucketName << "'." << std::endl;
}
// Delete all managed data
aws.destroy();
return 0;
}
C代碼看起來很相似,主要區別是使用的函數調用,而不是方法調用,即soap_call___s3__CreateBucket(&createBucketReq, &createBucketRes)
。所有這些都在生成的aws-s4.h文件中解釋。
編譯生成的文件與源代碼:
c++ -DSOAP_MAXDIMESIZE=104857600 -DWITH_OPENSSL -o createbucket createbucket.cpp soapAmazonS3SoapBindingProxy.cpp soapC.cpp stdsoap2.cpp -lssl -lcrypto
的SOAP_MAXDIMESIZE=104857600
確保DIME附件大小可以足夠大,同時防止使用DIME拒絕服務攻擊。 DIME頭部具有附件大小,因此攻擊者可以將該任意大小設置爲耗盡內存資源。其他職位沒有提到這一點。
運行createbucket
,將創建一個新的桶。
在最終的.cpp文件中,請注意我們在設置credentialsFile和bucketName時檢查命令行參數(argv)。這使得程序與參數調用:
./createbucket BucketName path_to_credentials_file
有關這一切的詳細信息,我建議閱讀由Chris Moutsos上How to use AWS S3 in C++ with gSOAP優秀CodeProject上的文章從這種解釋部分起源。
- 1. 使用C++ GSOAP客戶端訪問Amazon S3服務
- 2. 如何使用Amazon AWS SDK爲C#
- 3. 使用適用於JavaScript的AWS開發工具包訪問AWS S3
- 4. Amazon AWS和S3存儲使用模型
- 5. 訪問Amazon S3使用http在angular2
- 6. Amazon S3禁用桶根的訪問
- 7. AWS IAM用戶訪問S3
- 8. Amazon S3只寫訪問
- 9. 如何使用aws-sdk-php連接到amazon aws s3?
- 10. 通過適用於Android的Amazon S3的PHP應用程序
- 11. Amazon S3問題獲得SSL與c#sdk配合使用
- 12. 使用臨時憑證訪問AWS S3
- 13. 如何訪問對象從Amazon S3的使用getSignedUrl操作
- 14. 如何使用IAM訪問AWS S3上的存儲桶 - 使用Node.js(aws-sdk)?
- 15. Amazon AWS使用C#發送短信
- 16. 如何使用Amazon的新RRS for S3?
- 17. 如何使用Amazon S3
- 18. 使用C#使用AWSSDK.S3驗證Amazon S3存儲桶
- 19. AWS CLI S3訪問
- 20. 訪問AWS S3與
- 21. 使用簽名URL上傳到Amazon S3適用於curl,但不適用於javascript
- 22. 使用DeveloperCredentials在C++ AWS S3客戶
- 23. 如何在C++中隱藏我的AWS S3訪問密鑰和密鑰?
- 24. gzip不適用於aws s3資產
- 25. 適用於Linux和Windows的C和C++
- 26. 使用適用於.NET的AWS S3 SDK從Amazon S3下載並行批處理文件
- 27. 使用C/C++訪問S3/DynamoDB的選項
- 28. 使用Amazon AWS祕密密鑰部署C#客戶端應用程序(S3)?
- 29. Amazon S3的訪問被拒絕
- 30. PigStorage如何適用於S3?
我知道這不是一個真正的問題,但我也想知道gsoap + aws是如何製作c/C++ amazon應用程序的。感謝你,即使它被鎖定/ downvoted/tos'd:\ –
你能否請格式化成適當的問題/答案對?請參閱http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/ –
有關於此主題的文章發佈在[CodeProject關於gSOAP和AWS S3 ](https://www.codeproject.com/Articles/1108296/How-to-Use-Amazon-Simple-Storage-Service-S-in-Cplu)更詳細。該文章的副本也出現在gSOAP開發人員網站上。不知道爲什麼主持人用這些指針去掉了我的答案。 –