公司内部开发了一个文件相关的应用,由于服务器带宽限制导致多个用户同时上传或者下载文件时速度很慢,遂将文件迁移至阿里云OSS服务器。下面是迁移的过程中遇到的部分问题。
问题1. 跨域错误
错误信息如下:
Access to XMLHttpRequest at 'http://xxx.oss-cn-hangzhou.aliyuncs.com/test/logo.jpg' from origin 'http://192.168.29.131:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
该问题按照以下步骤正确配置跨域规则。
- 登录OSS管理控制台。
- 单击Bucket 列表,然后单击目标Bucket名称。
- 在左侧导航栏,选择数据安全 > 跨域设置。
- 在跨域设置页面,单击创建规则。
- 在创建跨域规则面板,按以下说明配置各项参数,其他参数保留默认配置。
- 来源:设置为
*
。 - 允许Methods:选中
GET
、POST
、PUT
、DELETE
、HEAD
。 - 允许Headers:设置为
*
。 - 暴露Headers:设置为指定值或者不填。
- 来源:设置为
- 单击确定。
问题2. Access denied by authorizer’s policy.
具体错误代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>AccessDenied</Code>
<Message>Access denied by authorizer's policy.</Message>
<RequestId>655EED1451FCAD1916A298B4</RequestId>
<HostId>xxx.oss-cn-hangzhou.aliyuncs.com</HostId>
<AccessDeniedDetail>
<PolicyType>SessionPolicy</PolicyType>
<AuthPrincipalOwnerId>1883463381918383</AuthPrincipalOwnerId>
<AuthPrincipalType>AssumedRoleUser</AuthPrincipalType>
<AuthPrincipalDisplayName>devram:251264809289383873</AuthPrincipalDisplayName>
<NoPermissionType>ImplicitDeny</NoPermissionType>
<AuthAction>oss:PutObject</AuthAction>
</AccessDeniedDetail>
<EC>0003-00000301</EC>
<RecommendDoc>https://api.aliyun.com/troubleshoot?q=0003-00000301</RecommendDoc>
</Error>
问题解析:
Web端上传文件至OSS服务器,为避免暴露阿里云账号访问密钥(AccessKey ID和AccessKey Secret),通常临时访问凭证的方式执行OSS相关操作。
临时访问凭证包括临时访问密钥(AccessKey ID和AccessKey Secret)和安全令牌(SecurityToken)。
在获取访问密钥(AccessKey ID和AccessKey Secret)和安全令牌(SecurityToken)时,需要制定策略(Policy),而策略中则指定了权限以及资源目录等内容。如下:
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"oss:PutObject" // 上传文件权限
],
"Resource": [
"acs:oss:*:*:examplebucket/xxx/*", // examplebucket为bucket名称,其中xxx为上传文件目录
]
}
]
}
注意:需要配置Action以及Resource,并且Resource中指定的目录需要与实际目录一致
详细解决方案见:https://api.aliyun.com/troubleshoot?q=0003-00000301
问题3. The security token you provided has expired.
详细错误代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>SecurityTokenExpired</Code>
<Message>The security token you provided has expired.</Message>
<RequestId>655EED5451FCAD1916A298B4</RequestId>
<HostId>xxx.oss-cn-hangzhou.aliyuncs.com</HostId>
<SecurityToken>CAISowJ1q6Ft5B2yfSjIr5xxxx</SecurityToken>
<EC>0002-00000007</EC>
<RecommendDoc>https://api.aliyun.com/troubleshoot?q=0002-00000007</RecommendDoc>
</Error>
获取访问密钥(AccessKey ID和AccessKey Secret)和安全令牌(SecurityToken)时需要指定一个有效时间,超时即失效,再次上传文件则会报如上信息。
WEB端aliyun-oss-sdk-6.18.0.min.js
创建OSS上传对象,可以指定刷新token方法,如下:
const client = new OSS({
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,yourRegion填写为oss-cn-hangzhou。
region: "yourRegion",
// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
accessKeyId: "yourAccessKeyId",
accessKeySecret: "yourAccessKeySecret",
// 从STS服务获取的安全令牌(SecurityToken)。
stsToken: "yourSecurityToken",
// 填写Bucket名称。
bucket: "examplebucket",
retryMax: 3, // 需指定retryMax,否则refreshSTSToken无法执行
refreshSTSToken: async() => {
// 向您搭建的STS服务获取临时访问凭证。
const info = await fetch('xxx/xxxx/get-token')
return {
accessKeyId: info.accessKeyId,
accessKeySecret: info.accessKeySecret,
stsToken: info.securityToken
}
},
// 刷新临时访问凭证的时间间隔,单位为毫秒。
refreshSTSTokenInterval: 1000
})
指定refreshSTSToken
方法后,在执行文件上传时若token超时,则会自动刷新token并上传文件。值得注意的时单单指定refreshSTSToken
方法并不会达成预期效果,需要同时指定retryMax
参数才行(参考issue:https://github.com/ali-sdk/ali-oss/issues/1179)。
问题4. 部分文件无法预览、下载
部分类型文件(如pdf)文件无法在浏览器中预览或下载,错误截图如下:
登录OSS服务器后台管理平台,在文件列表查看文件,发现文件类型不是预期的类型:
出现该问题大概率是由于上传文件时指定的Content-Type
错误造成的,上传文件不指定Content-Type
即可。
问题5. 浏览器下载文件错误
通过OSS.signatureUrl
方法转换的url,通过浏览器地址栏访问下载报AccessDenied
错误。详细错误如下:
<Error>
<Code>AccessDenied</Code>
<Message>Access denied by authorizer's policy.</Message>
<RequestId>65600B6235EB2631229B98CB</RequestId>
<HostId>xxx.oss-cn-hangzhou.aliyuncs.com</HostId>
<AccessDeniedDetail>
<PolicyType>SessionPolicy</PolicyType>
<AuthPrincipalOwnerId>1883463381918303</AuthPrincipalOwnerId>
<AuthPrincipalType>AssumedRoleUser</AuthPrincipalType>
<AuthPrincipalDisplayName>devram:251264809289383873</AuthPrincipalDisplayName>
<NoPermissionType>ImplicitDeny</NoPermissionType>
<AuthAction>oss:GetObject</AuthAction>
</AccessDeniedDetail>
<EC>0003-00000301</EC>
<RecommendDoc>https://api.aliyun.com/troubleshoot?q=0003-00000301</RecommendDoc>
</Error>
由错误信息中的<AuthAction>oss:GetObject</AuthAction>
可知获取访问密钥(AccessKey ID和AccessKey Secret)和安全令牌(SecurityToken)时未配置GetObject
权限。在获取密钥和安全令牌时指定GetObject
权限即可。如下:
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"oss:PutObject", // 上传文件权限
"oss:GetObject" // 下载文件权限
],
"Resource": [
"acs:oss:*:*:examplebucket/xxx/*", // examplebucket为bucket名称,其中xxx为上传文件目录
]
}
]
}