Scala AJAX上传期间Amazon S3签名不匹配
去装配一个AJAX上传到S3,但是请求返回SignatureDesNotMatch。在仔细检查了访问密钥ID和密码之后,我对这个问题感到不知所措。我可以确认我确实也设置了CORS策略文件 以下是AJAX请求:Scala AJAX上传期间Amazon S3签名不匹配,scala,amazon-s3,base64,Scala,Amazon S3,Base64,去装配一个AJAX上传到S3,但是请求返回SignatureDesNotMatch。在仔细检查了访问密钥ID和密码之后,我对这个问题感到不知所措。我可以确认我确实也设置了CORS策略文件 以下是AJAX请求: $.ajax({ url: 'https://my-bucket.s3.amazonaws.com/', type: 'POST', contentType: false, da
$.ajax({
url: 'https://my-bucket.s3.amazonaws.com/',
type: 'POST',
contentType: false,
data: formData,
success: function() {
self.unblockUI($('#body'));
},
error: function() {
self.unblockUI($('#body'));
},
cache: false,
processData: false
});
在Scala中执行策略编码/签名。代码如下:
val policy = """
|{"expiration": "2020-01-01T00:00:00Z",
|"conditions": [
|{"bucket": "my-bucket"},
|["starts-with", "$key", "uploads/"],
|{"acl": "public-read"},
|{"success_action_redirect": "http://example.com/"},
|["starts-with", "$Content-Type", ""],
|["starts-with","$Filename",""],
|["content-length-range", 0, 5242880]
|]
|}
""".stripMargin.stripLineEnd.replaceAll("\n", "").replaceAll("\r","")
val policyEncoded = (new BASE64Encoder()).encode(policy.getBytes("UTF-8")).stripLineEnd.replaceAll("\n", "").replaceAll("\r","")
val hmac = Mac.getInstance("HmacSHA1")
hmac.init(new SecretKeySpec(AWS_SECRET.getBytes("UTF-8"), "HmacSHA1"))
val policySignature = (new BASE64Encoder()).encode(hmac.doFinal(policy.getBytes("UTF-8"))).stripLineEnd.replaceAll("\n", "").replaceAll("\r","")
正在发送的表格如下:
------WebKitFormBoundaryTNKMpdRiJxhC39QF
Content-Disposition: form-data; name="key"
uploads/reward/img/example_02820838f08sd083k.jpeg
------WebKitFormBoundaryTNKMpdRiJxhC39QF
Content-Disposition: form-data; name="AWSAccessKeyId"
<redacted>
------WebKitFormBoundaryTNKMpdRiJxhC39QF
Content-Disposition: form-data; name="acl"
public-read
------WebKitFormBoundaryTNKMpdRiJxhC39QF
Content-Disposition: form-data; name="success_action_redirect"
http://example.com/
------WebKitFormBoundaryTNKMpdRiJxhC39QF
Content-Disposition: form-data; name="policy"
eyJleHBpcmF0aW9uIjogIjIwMjAtMDEtMDFUMDA6MDA6MDBaIiwiY29uZGl0aW9ucyI6IFsgeyJidWNrZXQiOiAicGxhdGZvcm0zLWNsaWVudC1pbWFnZXMifSwgWyJzdGFydHMtd2l0aCIsICIka2V5IiwgInVwbG9hZHMvIl0seyJhY2wiOiAicHVibGljLXJlYWQifSx7InN1Y2Nlc3NfYWN0aW9uX3JlZGlyZWN0IjogImh0dHA6Ly8za3Vkb3MuY29tLyJ9LFsic3RhcnRzLXdpdGgiLCAiJENvbnRlbnQtVHlwZSIsICIiXSxbInN0YXJ0cy13aXRoIiwiJEZpbGVuYW1lIiwiIl0sWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDAsIDUyNDI4ODBdXX0gICAg
------WebKitFormBoundaryTNKMpdRiJxhC39QF
Content-Disposition: form-data; name="signature"
9jj1hW8pGpS32Ka4KA2R0MwYKTQ=
------WebKitFormBoundaryTNKMpdRiJxhC39QF
Content-Disposition: form-data; name="Content-Type"
image/jpeg
------WebKitFormBoundaryTNKMpdRiJxhC39QF
Content-Disposition: form-data; name="file"; filename="youtube_bg.jpg"
Content-Type: image/jpeg
------WebKitFormBoundaryTNKMpdRiJxhC39QF--
你知道为什么这会失败吗?我想我已经用尽了所有可能的办法。谢谢 签名有一些问题,但其中之一是我没有正确编码字符串。为了帮助不想使用AmazonSDK的未来Scala用户,这里是我的Scala S3Policy对象,它生成了正确的签名 注意:您不需要使用该游戏!除非您正在使用Play!框架
import play.api.Logger
import sun.misc.BASE64Encoder
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import com.codahale.jerkson.Json._
object S3Policy {
val AWS_ACCESS_KEY_ID = "<your access key ID goes here>"
val AWS_SECRET = "<your secret goes here>"
val AWS_ALGO = "HmacSHA1"
val policy = {
val policyMap = Map(
"expiration" -> "2014-01-01T12:00:00.000Z'",
"conditions" -> List(
Map("bucket" -> "<your bucket goes here>"),
Map("success_action_status" -> "201"),
Map("acl" -> "public-read"),
Array("starts-with", "$key", "uploads/"),
Array("starts-with", "$Content-Type", ""),
Array("starts-with", "$x-amz-meta-clientid", ""),
List("content-length-range", 0, 5242880)
)
)
val generated = generate(policyMap)
Logger.debug("AWS S3 POLICY: "+generated)
generated
}
val policyEncoded = (new BASE64Encoder()).encode(policy.getBytes("UTF-8")).replaceAll("\n", "").replaceAll("\r","")
val policySignature = signAndBase64Encode(policyEncoded, AWS_ALGO)
/**
* method to sign an AWS request
*/
def signAndBase64Encode(stringToSign: String, algo: String) = {
try {
val mac = Mac.getInstance(algo)
mac.init(new SecretKeySpec(AWS_SECRET.getBytes("UTF-8"), algo))
val signature = mac.doFinal(stringToSign.getBytes("UTF-8"))
val encoded = (new BASE64Encoder()).encode(signature)
Logger.debug("AWS S3 SIGNATURE: "+encoded)
encoded
} catch {
case e => Logger.error("Unable to calculate a request signature: " + e.getMessage(), e); "ERRORSTRINGNOTCALCULATED"
}
}
}
在上面的策略中,您会注意到我使用的是x-amz-meta-field。如果您使用的是S3 metas,则需要以这种或那种方式定义它。签名有一些问题,但其中之一是我没有正确编码字符串。为了帮助不想使用AmazonSDK的未来Scala用户,这里是我的Scala S3Policy对象,它生成了正确的签名 注意:您不需要使用该游戏!除非您正在使用Play!框架
import play.api.Logger
import sun.misc.BASE64Encoder
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import com.codahale.jerkson.Json._
object S3Policy {
val AWS_ACCESS_KEY_ID = "<your access key ID goes here>"
val AWS_SECRET = "<your secret goes here>"
val AWS_ALGO = "HmacSHA1"
val policy = {
val policyMap = Map(
"expiration" -> "2014-01-01T12:00:00.000Z'",
"conditions" -> List(
Map("bucket" -> "<your bucket goes here>"),
Map("success_action_status" -> "201"),
Map("acl" -> "public-read"),
Array("starts-with", "$key", "uploads/"),
Array("starts-with", "$Content-Type", ""),
Array("starts-with", "$x-amz-meta-clientid", ""),
List("content-length-range", 0, 5242880)
)
)
val generated = generate(policyMap)
Logger.debug("AWS S3 POLICY: "+generated)
generated
}
val policyEncoded = (new BASE64Encoder()).encode(policy.getBytes("UTF-8")).replaceAll("\n", "").replaceAll("\r","")
val policySignature = signAndBase64Encode(policyEncoded, AWS_ALGO)
/**
* method to sign an AWS request
*/
def signAndBase64Encode(stringToSign: String, algo: String) = {
try {
val mac = Mac.getInstance(algo)
mac.init(new SecretKeySpec(AWS_SECRET.getBytes("UTF-8"), algo))
val signature = mac.doFinal(stringToSign.getBytes("UTF-8"))
val encoded = (new BASE64Encoder()).encode(signature)
Logger.debug("AWS S3 SIGNATURE: "+encoded)
encoded
} catch {
case e => Logger.error("Unable to calculate a request signature: " + e.getMessage(), e); "ERRORSTRINGNOTCALCULATED"
}
}
}
在上面的策略中,您会注意到我使用的是x-amz-meta-field。如果您使用的是S3元,则需要以这种或那种方式定义此方法。您是否遗漏了该策略对象中的generate方法?generate来自Jerkson:您遗漏了该策略对象中的generate方法?generate来自Jerkson: