2011-08-10 24 views
11

Bunun için her yeri araştırdım ve tek bir iyi kod bulamadım. GSOAP kullanarak Amazon AWS S3 hizmetine nasıl erişebilirim?Amazon AWS S3'e C ve C++ için GSOAP kullanarak nasıl erişebilirim?

+0

Bunun gerçekten bir soru olmadığını biliyorum, ama c/C++ amazon uygulaması yapmak için gsoap + aws'ı da merak ettim. Bunun için teşekkür ederiz, hatta kilitlenmiş/downvoted/tos'd bile: \ –

+2

bunu uygun bir soru/cevap çiftine biçimlendirebilir misiniz? Bkz. Http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/ –

+0

Bu konuda [CodeProject hakkında gSOAP ve AWS S3 hakkında bir makale yayınlanmıştır. ] (https://www.codeproject.com/Articles/1108296/How-to-Use-Amazon-Simple-Storage-Service-S-in-Cplu) daha ayrıntılı olarak. Bu makalenin bir kopyası, gSOAP geliştirici web sitesinde de görüntülenir. Moderatörün cevabımı bu işaretçilerle neden kaldırdığından emin değil. –

cevap

3

Aşağıdaki kod, OP'den alınmıştır. Aslen yazı, hem soru hem de cevabı içeriyordu ve ben onu Q & A formatına çeviriyorum.

imza

base64encode((HMAC-SHA1(ActionName+"AmazonS3"+XMLTimestamp))) 

HMAC, SHA1and B64 utils openssl mevcuttur formatın olmak zorundadır.

SOAP istekleri için biçim wsdl tarafından verilir.

REST arabirimi farklıdır.

Gereksinimleri: OpenSSL, GSOAPwsdl2h sonra

şu kod hizmete erişmek için olacak gSOAP istemci kodu oluşturmak için başlık ve soapcpp2 üretmek için.

Derleyici önişlemcisi yönergesi WITH_OPENSSL ile oluşturun. kütüphaneleri libeay32 ve ssleay32 ile bağlantı kurun.

#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; 
    } 

} 
0

Nasıl C ve C++ için gSOAP kullanarak Amazon AWS S3 erişebilir?

Adım 1

bir arayüz başlık dosyasına aws-s3.h için Amazon'un S3 WSDL dönüştürmek Kullanım gSOAP en wsd2lh aracı: yerine C kaynak kodu oluşturmak için

wsdl2h -t typemap.dat -o aws-s3.h http://doc.s3.amazonaws.com/2006-03-01/AmazonS3.wsdl

kullanın seçeneği -c varsayılan C++ kaynak kodu. typemap.dat dosyası gSOAP dağıtımının gsoap dizininde bulunur. 2

Adım wsdl2h araçla oluşturduğunuz başlık dosyası soapcpp2 aracını kullanın.

soapcpp2 -C -j aws-s3.h

Bu aws-s3.h başlığından C++ hizmet yakınlık ve nesneler (-j seçenek) istemci tarafında kodu (-C isteğe bağlı) oluşturur. C kodu için -j'u kullanın.

Adım 3

AWS S3 erişebilir ve AWS S3 için base64 ile kodlanmış, HMAC-SHA1 karma imza oluşturmak için otomatik oluşturulan AmazonS3SoapBindingProxy vekil yöntemlerini kullanın.yani yerine metot çağrımı durumunu çağırır

/* 
    createbucket.cpp 
    Example AWS S3 CreateBucket service invocation 
*/ 

#include "soapAmazonS3SoapBindingProxy.h" 
#include "AmazonS3SoapBinding.nsmap" 
#include &lt;fstream> 

// Make allocation of primitive values quick and easy: 
template&lt;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 &lt;&lt; "Couldn't read AWS keys for user " &lt;&lt; user  
                  &lt;&lt; " from file " &lt;&lt; credentialsFile &lt;&lt; '\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 &lt;&lt; "You are the owner of bucket '" &lt;&lt; result.BucketName &lt;&lt; "'." &lt;&lt; std::endl; 
    } 

    // Delete all managed data 
    aws.destroy(); 

    return 0; 
} 

C kodu temel fark fonksiyonunun kullanımı olmak üzere benzer soap_call___s3__CreateBucket(&createBucketReq, &createBucketRes): imza HMAC-SHA1 base64 ile kodlanmış versiyonu ile bir dize dize "AmazonS3" + OPERATION_NAME + Timestamp karma olduğu . Tüm bu oluşturulan aws-s4.h dosyasında açıklanmaktadır.

kaynak kodu ile oluşturulan dosyaları derlemek:
c++ -DSOAP_MAXDIMESIZE=104857600 -DWITH_OPENSSL -o createbucket createbucket.cpp soapAmazonS3SoapBindingProxy.cpp soapC.cpp stdsoap2.cpp -lssl -lcrypto 

SOAP_MAXDIMESIZE=104857600

DIME kullanarak hizmet reddi saldırıları önlerken DIME eki boyutları kadar büyük olabilir olmasını sağlar. DIME üstbilgisi ek boyutuna sahip olduğundan, bir saldırgan, keyfi olarak büyük olan bellek kaynaklarını tüketmeye ayarlayabilir. Diğer yayınlar bundan bahsetmedi.

createbucket'u çalıştırın ve yeni bir kepçe oluşturulacak.

Nihai .cpp dosyasında, credentialsFile ve bucketName öğelerini ayarlarken komut satırı argümanlarını (argv) kontrol ettiğimizi unutmayın. Bu program argümanla sağlar: tüm bu daha fazla ayrıntı için

./createbucket BucketName path_to_credentials_file 

, bu açıklamaların bazı bölümleri kaynaklandığı Chris Moutsos tarafından How to use AWS S3 in C++ with gSOAP mükemmel CodeProject makale okumak öneririz.

İlgili konular