Classic ASP amazon s3 rest authorisation

前端 未结 3 2153
夕颜
夕颜 2021-02-07 20:33

I am confused on what I am doing wrong here...



        
3条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-02-07 21:07

    I'd like to explain how S3 Rest Api works as far as I know.
    First, you need to learn what should be the string to sign Amazon accepts.

    Format :

    StringToSign = HTTP-Verb + "\n" +
        Content-MD5 + "\n" +
        Content-Type + "\n" +
        Date + "\n" +
        CanonicalizedAmzHeaders +
        CanonicalizedResource;
    

    Generating signed string :

    Signature = Base64( HMAC-SHA1( YourSecretAccessKeyID, UTF-8-Encoding-Of( StringToSign ) ) );
    

    Passing authorization header:

    Authorization = "AWS" + " " + AWSAccessKeyId + ":" + Signature;
    

    Unfortunately you'll play byte to byte since there is no any SDK released for classic asp. So, should understand by reading the entire page http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAuthentication.html

    For string to sign as you can see above in format, there are three native headers are reserved by the API. Content-Type, Content-MD5 and Date. These headers must be exists in the string to sign even your request hasn't them as empty without header name, just its value. There is an exception, Date header must be empty in string to sign if x-amz-date header is already exists in the request. Then, If request has canonical amazon headers, you should add them as key-value pairs like x-amz-headername:value. But, there is another exception need to be considered for multiple headers. Multiple headers should combine to one header with values comma separated.

    Correct

    x-amz-headername:value1,value2

    Wrong

    x-amz-headername:value1\n
    x-amz-headername:value2

    Most importantly, headers must be ascending order by its group in the string to sign. First, reserved headers with ascending order, then canonical headers with ascending order.

    I'd recommend using DomDocument functionality to generate Base64 encoded strings. Additionally instead of a Windows Scripting Component (.wsc files), you could use .Net's interops such as System.Security.Cryptography to generating keyed hashes more effectively with power of System.Text. All of these interoperabilities are available in today's IIS web servers.
    So, as an example I wrote the below script just sends a file to bucket you specified. Consider and test it.
    Assumed local file name is myimage.jpg and will be uploaded with same name to root of the bucket.

    
    
    <%
    Const AWS_BUCKETNAME = "uk-bucketname"
    Const AWS_ACCESSKEY = "GOES HERE"
    Const AWS_SECRETKEY = "SECRET"
    
    LocalFile = Server.Mappath("/test.jpg")
    
    Dim sRemoteFilePath
        sRemoteFilePath = "/files/test.jpg" 'Remote Path, note that AWS paths (in fact they aren't real paths) are strictly case sensitive
    
    Dim strNow
        strNow = GMTNow() ' GMT Date String
    
    Dim StringToSign
        StringToSign = Replace("PUT\n\nimage/jpeg\n\nx-amz-date:" & strNow & "\n/"& AWS_BUCKETNAME & sRemoteFilePath, "\n", vbLf)
    
    Dim Signature
        Signature = BytesToBase64(HMACSHA1(AWS_SECRETKEY, StringToSign))
    
    Dim Authorization
        Authorization = "AWS " & AWS_ACCESSKEY & ":" & Signature
    
    Dim AWSBucketUrl
        AWSBucketUrl = "https://" & AWS_BUCKETNAME & ".s3.amazonaws.com"
    
    With Server.CreateObject("MSXML2.ServerXMLHTTP.6.0")
        .open "PUT", AWSBucketUrl & sRemoteFilePath, False
        .setRequestHeader "Authorization", Authorization
        .setRequestHeader "Content-Type", "image/jpeg"
        .setRequestHeader "Host", AWS_BUCKETNAME & ".s3.amazonaws.com"  
        .setRequestHeader "x-amz-date", strNow
        .send GetBytes(LocalFile) 'Get bytes of local file and send
        If .status = 200 Then ' successful
            Response.Write "Uploaded File"
        Else ' an error ocurred, consider xml string of error details
            Response.ContentType = "text/xml"
            Response.Write .responseText
        End If
    End With
    
    Function GetBytes(sPath)
        With Server.CreateObject("Adodb.Stream")
            .Type = 1 ' adTypeBinary
            .Open
            .LoadFromFile sPath
            .Position = 0
            GetBytes = .Read
            .Close
        End With
    End Function
    
    Function BytesToBase64(varBytes)
        With Server.CreateObject("MSXML2.DomDocument").CreateElement("b64")
            .dataType = "bin.base64"
            .nodeTypedValue = varBytes
            BytesToBase64 = .Text
        End With
    End Function
    
    Function HMACSHA1(varKey, varValue)
        With Server.CreateObject("System.Security.Cryptography.HMACSHA1")
            .Key = UTF8Bytes(varKey)
            HMACSHA1 = .ComputeHash_2(UTF8Bytes(varValue))
        End With
    End Function
    
    Function UTF8Bytes(varStr)
        With Server.CreateObject("System.Text.UTF8Encoding")
            UTF8Bytes = .GetBytes_4(varStr)
        End With
    End Function
    %>
    


提交回复
热议问题