OAuth2.0前端图片上传实践
什么是OAuth2.0?
关于OAuth(开放授权),以下为维基百科的解释:
OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。
OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth让用户可以授权第三方网站访问他们存储在另外服务提供者的某些特定信息,而非所有内容。
* 相对于1.0的Request_Token换Authorization_Code,Authorization_Code再换Access_Token的授权模式,2.0提供了一种更简洁给力的授权码方式:Authorization_Code直接换Access_Token模式。
简单来说,就是客户端需要访问资源服务器,首先请求授权服务器,授权服务器带着Authorization_Code去访问资源服务器,来认证客户端是否合法,如果合法就直接返回给客户端 Access_Token,客户端带着Access_Token就能访问资源服务器了。
适用场景说明
我们以往后端上传采用的做法是先上传到应用服务器,然后由应用服务器把文件上传到顽兔多媒体。
但这种方法有三个缺点:
1. 上传慢,先上传到应用服务器,再上传到顽兔服务,网络传送多了一倍;
2.扩展性不好,如果后续用户多了,应用服务器带宽和处理能力将成为瓶颈;
2. 费用高,文件类的应用服务器面临高昂的带宽采购成本。
针对以上三个缺点,顽兔为开发者提供了将文件数据直传到顽兔多媒体的能力。
Web端直传的请求逻辑如下图所示:
1. 网页端要上传文件时,先到应用服务器请求上传Token;
2. 应用服务器根据上传规则使用顽兔多媒体SDK生成上传Token并返回;
3. 网页端拿到上传Token后,直接通过JS SDK上传到顽兔多媒体。
其实以上就是OAuth 2.0的认证模型,开发者需要考虑的是应用服务器通过什么策略来获取Access_Token返回给客户端。
后端实现:
package com.cttq.cim.common.gwy.comm;
import com.alibaba.media.MediaConfiguration;
import com.alibaba.media.upload.UploadPolicy;
import com.alibaba.media.upload.UploadTokenClient;
import com.alibaba.media.upload.impl.DefaultUploadTokenClient;
import com.cttq.cim.utils.PropertiesUtil;
/**
* 功能描述:带失效时间的顽兔token生成.<br/>
* <p>
* #date 2017年4月7日 上午11:16:42<br/>
* #author cjbi <br/>
* #since 2.2.0<br/>
*/
public class WantuExpirationToken {
private static String TOKEN;
/**
* 阿里百川应用key
*/
private static String AK;
/**
* 阿里百川应用密钥
*/
private static String SK;
/**
* 顽兔空间名称
*/
private static String NAME_SPACE;
/**
* token过期时间
*/
private static Long EXPIRATION;
/**
* 设置零界值为1分钟
*/
private static Long ZEROZONE = 60 * 1000L;
private WantuExpirationToken() {
}
static {
initTOKEN();
}
private static void initTOKEN() {
/**
* 初始化 MediaConfiguration 配置图片服务的AK: AccessKey、AccessKeySecret
* 配置图片服务的namespace:
*/
final boolean isExist = PropertiesUtil.init("multiMedia.properties");
if (isExist) {
AK = PropertiesUtil.getReadVal("ak");
SK = PropertiesUtil.getReadVal("sk");
NAME_SPACE = PropertiesUtil.getReadVal("namespace");
}
MediaConfiguration configuration = new MediaConfiguration();
configuration.setAk(AK);
configuration.setSk(SK);
configuration.setNamespace(NAME_SPACE);
UploadTokenClient tokenClient = new DefaultUploadTokenClient(configuration);
/**
* 为用户指定上传策略 下面的上传策略指定了: 用户上传文件不允许覆盖 该用户凭证的失效时间为当前时间之后的一个小时,
* 在之后的一个小时之内Token都可以作为用户的上传凭证
*/
UploadPolicy uploadPolicy = new UploadPolicy();
uploadPolicy.setInsertOnly(UploadPolicy.INSERT_ONLY_NONE);
EXPIRATION = System.currentTimeMillis() + 3600 * 1000;
uploadPolicy.setExpiration(EXPIRATION);
/**
* 请求Token服务,为该用户申请该上传策略对应的Token
*/
TOKEN = tokenClient.getUploadToken(uploadPolicy);
}
public static String getUploadToken() {
Long currentTimeMillis = System.currentTimeMillis();
//如果失效时间减去当前时间小于零界值,说明将要过期,重新初始化TOKEN
if (EXPIRATION - currentTimeMillis < ZEROZONE) {
initTOKEN();
}
return TOKEN;
}
}
以上Token更新策略是被动触发的,也就是说只有在客户端请求上传时才会检查Token是否该更新,其实也可以写个定时任务定时更新,但是目前图片上传用的不是很多,结合业务需求,感觉没这个必要。
至于客户端上传,可以下载顽兔的jssdk,将上面提到的dataURL转换成Blob对象就能作为文件流上传到服务器了,以下就不贴代码了。