He buscado en todas partes esto y no he podido encontrar un solo código decente. ¿Cómo puedo acceder al servicio Amazon AWS S3 usando GSOAP?¿Cómo puedo acceder a Amazon AWS S3 usando GSOAP para C y C++?
Respuesta
El siguiente código es del OP. Originalmente, la publicación contenía tanto la pregunta como la respuesta y la estoy convirtiendo en un formato Q & A.
La firma tiene que ser del formato
base64encode((HMAC-SHA1(ActionName+"AmazonS3"+XMLTimestamp)))
El HMAC, Utiles SHA1and B64 están disponibles en openssl.
El formato para las solicitudes SOAP viene dado por el wsdl.
La interfaz REST es diferente.
Después wsdl2h
para generar la cabecera y soapcpp2 para generar el código de cliente gSOAP lo siguiente será el código para acceder al servicio:
compilar con la directiva del preprocesador del compilador WITH_OPENSSL
. Enlace con las bibliotecas libeay32
y 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;
}
}
¿Cómo puedo acceder a Amazon AWS S3 usando gSOAP para C y C++?
Paso 1
herramienta wsd2lh de Uso gSOAP para convertir WSDL S3 de Amazon a un fichero de cabecera interfaz aws-s3.h:
wsdl2h -t typemap.dat -o aws-s3.h http://doc.s3.amazonaws.com/2006-03-01/AmazonS3.wsdl
opción Usar -c
para generar código fuente en C en lugar de la código fuente predeterminado de C++. El archivo typemap.dat
se encuentra en el directorio gsoap de la distribución gSOAP.
Paso 2
Utilice la herramienta soapcpp2 en el archivo de cabecera creada a partir de la herramienta wsdl2h.
soapcpp2 -C -j aws-s3.h
Esto genera código del lado del cliente (-C
opción) con C proxies ++ de servicios y objetos (-j
opcional) de la cabecera AWS-s3.h. Omita -j
para el código C.
Paso 3
Usa los AmazonS3SoapBindingProxy
métodos de proxy generados automáticamente para acceder a AWS S3 y crear una firma codificado en base 64, HMAC-SHA1 hash para AWS S3.La firma es una cadena con la versión codificado en base 64 de la HMAC-SHA1 hash cadena "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;
}
El código C parecen similares, con la diferencia principal es el uso de las llamadas a funciones en lugar de invocaciones de métodos, es decir soap_call___s3__CreateBucket(&createBucketReq, &createBucketRes)
. Todo esto se explica en el archivo aws-s4.h generado.
compilar los ficheros generados con su código fuente:
c++ -DSOAP_MAXDIMESIZE=104857600 -DWITH_OPENSSL -o createbucket createbucket.cpp soapAmazonS3SoapBindingProxy.cpp soapC.cpp stdsoap2.cpp -lssl -lcrypto
El SOAP_MAXDIMESIZE=104857600
asegura que DIME tamaños de fijación pueden ser lo suficientemente grandes, mientras que la prevención de ataques de denegación de servicio utilizando DIME. El encabezado DIME tiene el tamaño de archivo adjunto, por lo que un atacante podría establecer ese tamaño arbitrario para agotar los recursos de memoria. Otros mensajes no mencionaron esto.
Ejecutar createbucket
, y se creará un nuevo cubo.
En el archivo .cpp final, tenga en cuenta que verificamos los argumentos de línea de comandos (argv) al establecer credencialesFile y bucketName. Esto permite que el programa que se llamará con argumentos:
./createbucket BucketName path_to_credentials_file
Para más detalles sobre todo esto, sugiero leer el excelente artículo CodeProject en How to use AWS S3 in C++ with gSOAP por Chris Moutsos de la que partes de esta explicación se origina.
- 1. Subiendo a Amazon S3 usando cURL/libcurl
- 2. Acceso fuertemente tipado a Amazon S3 utilizando C#
- 3. Rails Heroku server paperclip Amazon S3 - AWS :: S3 :: Errores :: RequestTimeout
- 4. gsoap restful cliente de C++ usando streaming
- 5. ¿Cómo combinar JS/CSS para Amazon S3?
- 6. problema para acceder cubo de mi AWS S3 cuenta
- 7. Amazon AWS tutoriales?
- 8. Usando RabbitMQ con nServiceBus (para C#) frente a Amazon SQS
- 9. Usando Uploadify para POST directamente a Amazon S3
- 10. Amazon Web Services (AWS) S3 Java crear un subdirectorio (objeto)
- 11. Amazon S3 y Checksum
- 12. compilación gSoap con C++
- 13. AWS S3 par no autenticado
- 14. git y Amazon s3
- 15. Ruby AWS :: S3 :: S3Object (aws-sdk): ¿Hay algún método para transmitir datos como con aws-s3?
- 16. Amazon S3 hace que SSL funcione con C# sdk
- 17. Amazon S3 cargar archivo y obtener URL
- 18. best amazon s3 gem with rails 3.1.3
- 19. Agregar un archivo a un depósito en Amazon S3 usando C#
- 20. AWS lib3s C/C++ Código/tutoriales de muestra
- 21. ¿Cómo puedo acceder a SQLite con C#?
- 22. Despliegue del sitio web en Amazon AWS
- 23. aws sdk php para listar carpetas s3
- 24. ¿Cómo descargo un archivo con php y Amazon S3 SDK?
- 25. Amazon AWS Ec2 + Elastic IP
- 26. Carriles 3 - Amazon S3 Paperclip UE Problema
- 27. Paperclip y Amazon S3 ¿cómo hacer rutas?
- 28. Uso de Django-Storages con Amazon S3 y https
- 29. Dónde almacenar imágenes en Amazon AWS para usar en RDS
- 30. Cliente basado en web para Amazon S3
Sé que esto no es realmente una pregunta, pero también me he preguntado acerca de gsoap + aws para hacer una aplicación c/C++ amazon. Gracias por esto, incluso si se bloquea/downvoted/tos'd: \ –
¿puedes formatear esto en un par de pregunta/respuesta? Consulte http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/ –
Hay un artículo sobre este tema publicado en [CodeProject sobre gSOAP y AWS S3 ] (https://www.codeproject.com/Articles/1108296/How-to-Use-Amazon-Simple-Storage-Service-S-in-Cplu) con más detalle. Una copia de ese artículo también aparece en el sitio web para desarrolladores de gSOAP. No estoy seguro de por qué el moderador eliminó mi respuesta con estos punteros. –