-
阿里云oss上传使用的是服务端签名后直传;通过服务端生成上传签名,前端使用服务端生成的签名上传文件。
-
在能正常使用的情况下突然报错:
<Error>
<Code>
AccessDenied
</Code>
<Message>
Invalid according to Policy: Policy expired.
</Message>
<RequestId>
5DB65B8F5C74183230A8E048
</RequestId>
<HostId>
transnal-test.oss-cn-beijing.aliyuncs.com
</HostId>
</Error>
-
经过排查原因是服务器时间和前端时间不一致,前端时间比服务端快几分钟,所以服务端生成签名给到前端时,签名已过期。
-
后台生成签名的java代码如下:
/**
* Get请求
*/
@GetMapping
protected void doGet(HttpServletRequest request, HttpServletResponse response, String prefix)
throws ServletException, IOException {
String endpoint = this.endpoint.replace("http://", "").replace("https://", ""); // 请填写您的 endpoint。
String host = "http://" + this.bucketName + "." + endpoint; // host的格式为 bucketname.endpoint
// callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
// String callbackUrl = "http://88.88.88.88.:8888";
String dir = Constants.FILE_PREFIX; // 用户上传文件时指定的前缀。
if (StringUtils.isNotBlank(prefix)) {
dir += prefix + "_"; // 用户上传文件时指定的前缀。
}
OSS client = aliOssService.getOssClient();
try {
long expireTime = 30;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
// policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
String postPolicy = client.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = client.calculatePostSignature(postPolicy);
JSONObject ja1 = new JSONObject();
ja1.put("accessid", this.accessKeyId);
ja1.put("policy", encodedPolicy);
ja1.put("signature", postSignature);
ja1.put("dir", dir);
ja1.put("host", host);
ja1.put("expire", String.valueOf(expireEndTime / 1000));
// respMap.put("expire", formatISO8601Date(expiration));
JSONObject jasonCallback = new JSONObject();
// jasonCallback.put("callbackUrl", callbackUrl);
jasonCallback.put("callbackBody",
"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
ja1.put("callback", base64CallbackBody);
// System.out.println(ja1.toString());
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST");
response(request, response, ja1.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
- 解决方法有两种:
1.后台生成签名时,使用前端传递过来的当前时间。
2.生成签名时,官方代码中的参数expireTime
默认是30秒,改为更大的时间。