J'ai cherché partout pour cela et je ne pouvais pas trouver un seul code décent. Comment puis-je accéder au service Amazon AWS S3 en utilisant GSOAP?Comment puis-je accéder à Amazon AWS S3 à l'aide de GSOAP pour C et C++?
Répondre
Le code ci-dessous provient de l'OP. À l'origine, le poste contenait à la fois la question et la réponse et je la transforme en Q & Un format.
La signature doit être au format
base64encode((HMAC-SHA1(ActionName+"AmazonS3"+XMLTimestamp)))
Le HMAC, utils SHA1and B64 sont disponibles dans openssl. Le format des demandes SOAP est donné par le wsdl.
L'interface REST est différente.
Après wsdl2h
pour générer l'en-tête et soapcpp2 pour générer le code client gSOAP ce qui suit sera le code pour accéder au service:
Exigences: OpenSSL, GSOAP. Construit avec la directive WITH_OPENSSL
du préprocesseur du compilateur. Lier avec les bibliothèques libeay32
et 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;
}
}
Comment puis-je accéder à Amazon AWS S3 en utilisant gSOAP pour C et C++?
Étape 1
Utilisez l'outil de wsd2lh de gSOAP pour convertir le WSDL Amazon S3 dans un fichier d'en-tête d'interface aws-s3.h:
wsdl2h -t typemap.dat -o aws-s3.h http://doc.s3.amazonaws.com/2006-03-01/AmazonS3.wsdl
option Utiliser -c
pour générer du code source C au lieu de code source C++ par défaut. Le fichier typemap.dat
se trouve dans le répertoire gsoap de la distribution gSOAP.
Étape 2
Utilisez l'outil de soapcpp2 sur le fichier d'en-tête créé à partir de l'outil de wsdl2h.
soapcpp2 -C -j aws-s3.h
Ceci génère le code côté client (en option -C
) avec proxys de service C++ et les objets (option -j
) à partir de l'en-tête de AWS-s3.h. Omettre -j
pour le code C.
Etape 3
Utilisez les méthodes proxy générées automatiquement AmazonS3SoapBindingProxy
pour accéder à AWS S3 et créer une base64, signature HMAC-SHA1 haché pour AWS S3.La signature est une chaîne avec la version codée en base64 de la chaîne hachée HMAC-SHA1 "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;
}
Le code C se ressemblent, avec la principale différence étant l'utilisation de la fonction des appels au lieu d'invocations de méthode, à savoir soap_call___s3__CreateBucket(&createBucketReq, &createBucketRes)
. Tout cela est expliqué dans le fichier généré aws-s4.h.
Compile les fichiers générés avec votre code source:
c++ -DSOAP_MAXDIMESIZE=104857600 -DWITH_OPENSSL -o createbucket createbucket.cpp soapAmazonS3SoapBindingProxy.cpp soapC.cpp stdsoap2.cpp -lssl -lcrypto
Le SOAP_MAXDIMESIZE=104857600
assure que la taille des pièces jointes DIME peuvent être assez grand, tout en empêchant des attaques par déni de service à l'aide DIME. L'en-tête DIME a la taille de la pièce jointe, de sorte qu'un attaquant pourrait définir ce grand arbitrairement pour épuiser les ressources mémoire. D'autres messages ont omis de le mentionner.
Exécutez createbucket
et un nouveau compartiment sera créé.
Dans le fichier .cpp final, notez que nous vérifions les arguments de ligne de commande (argv) lors de la définition de credentialsFile et de bucketName. Cela permet au programme d'être appelé avec des arguments:
./createbucket BucketName path_to_credentials_file
Pour plus de détails sur tout cela, je vous suggère de lire l'excellent article sur CodeProject How to use AWS S3 in C++ with gSOAP par Chris Moutsos dont les parties de cette explication lance.
- 1. Accéder aux services Amazon S3 avec le client GSOAP C++
- 2. Accéder à la vidéo à partir de aws s3
- 3. code C# pour GZip et télécharger une chaîne Amazon S3
- 4. Connexion à Amazon S3
- 5. Rails Serveur paperokip Heroku Amazon S3 - AWS :: S3 :: Errors :: RequestTimeout
- 6. Amazon EC2 et s3
- 7. Comment combiner JS/CSS pour Amazon S3?
- 8. S3 Amazon C# (SOAP vs REST)
- 9. Déployer mon css et javascripts avec capistrano à amazon S3
- 10. Récupération et affichage d'une image stockée dans Amazon S3 à l'aide de iOS AWS SDK
- 11. Ecrire directement à Amazon S3
- 12. Annulation de téléversements AWS S3
- 13. Amazon AWS S3 comment suivre les téléchargements à partir de Java
- 14. Déployer l'application client C# (S3) avec la clé secrète Amazon AWS?
- 15. Ruby et Amazon S3 comment ouvrir le fichier et s'authentifier?
- 16. Didacticiels Amazon AWS?
- 17. ClickOnce et Amazon S3
- 18. Amazon S3 et swfaddress
- 19. Carrierwave et amazon s3
- 20. Amazon S3 et PHP
- 21. Paperclip et Amazon S3 Édition
- 22. Seau sécurisé Amazon S3
- 23. Amazon AWS (EC2/S3) at-il le port 2195 activé?
- 24. Limitation Amazon AWS Cloudfront
- 25. git et Amazon s3
- 26. Postfix et Amazon S3
- 27. fichiers de AWS S3 Comparaison - AWS :: S3 :: NoConnectionEstablished
- 28. Amazon S3 - Réglez la région sur UE à l'aide de Java AWS SDK
- 29. aws-s3 et European Buckets
- 30. Comment diffuser de l'audio sur Amazon S3?
Je sais que ce n'est pas vraiment une question, mais je me suis aussi posé des questions sur gsoap + aws pour créer une application c/C++ amazon. Merci pour cela, même si elle est verrouillée/downvoted/tos'd: \ –
pouvez-vous s'il vous plaît formater cela en une paire de questions/réponses? Voir http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/ –
Il y a un article sur ce sujet publié sur [CodeProject à propos de gSOAP et AWS S3 ] (https://www.codeproject.com/Articles/1108296/Comment-Utiliser-Amazon-Simple-Storage-Service-S-in-Cplu) plus en détail. Une copie de cet article apparaît également sur le site Web des développeurs gSOAP. Je ne sais pas pourquoi le modérateur a supprimé ma réponse avec ces pointeurs. –