mirror of
https://github.com/wahyd4/ruby-sdk.git
synced 2026-08-09 04:46:10 +10:00
286 lines
9.0 KiB
Ruby
Executable File
286 lines
9.0 KiB
Ruby
Executable File
# -*- encoding: utf-8 -*-
|
|
# vim: sw=2 ts=2
|
|
|
|
require 'hmac-sha1'
|
|
require 'uri'
|
|
require 'cgi'
|
|
|
|
require 'qiniu/exceptions'
|
|
|
|
module Qiniu
|
|
module Auth
|
|
DEFAULT_AUTH_SECONDS = 3600
|
|
|
|
class << self
|
|
def calculate_deadline(expires_in, deadline = nil)
|
|
### 授权期计算
|
|
if expires_in.is_a?(Integer) && expires_in > 0 then
|
|
# 指定相对时间,单位:秒
|
|
return Time.now.to_i + expires_in
|
|
elsif deadline.is_a?(Integer) then
|
|
# 指定绝对时间,常用于调试和单元测试
|
|
return deadline
|
|
end
|
|
|
|
# 默认授权期1小时
|
|
return Time.now.to_i + DEFAULT_AUTH_SECONDS
|
|
end # calculate_deadline
|
|
|
|
def calculate_hmac_sha1_digest(sk, str)
|
|
begin
|
|
sign = HMAC::SHA1.new(sk).update(str).digest
|
|
rescue RuntimeError => e
|
|
raise RuntimeError, "Please set Qiniu's access_key and secret_key before authorize any tokens."
|
|
rescue
|
|
raise
|
|
else
|
|
return sign
|
|
end
|
|
end
|
|
end # class << self
|
|
|
|
class PutPolicy
|
|
private
|
|
def initialize(bucket,
|
|
key = nil,
|
|
expires_in = DEFAULT_AUTH_SECONDS,
|
|
deadline = nil)
|
|
### 设定scope参数(必填项目)
|
|
self.scope!(bucket, key)
|
|
|
|
### 设定deadline参数(必填项目)
|
|
@expires_in = expires_in
|
|
@deadline = Auth.calculate_deadline(expires_in, deadline)
|
|
end # initialize
|
|
|
|
PARAMS = {
|
|
# 字符串类型参数
|
|
:scope => "scope" ,
|
|
:save_key => "saveKey" ,
|
|
:end_user => "endUser" ,
|
|
:return_url => "returnUrl" ,
|
|
:return_body => "returnBody" ,
|
|
:callback_url => "callbackUrl" ,
|
|
:callback_host => "callbackHost" ,
|
|
:callback_body => "callbackBody" ,
|
|
:callback_body_type => "callbackBodyType" ,
|
|
:persistent_ops => "persistentOps" ,
|
|
:persistent_notify_url => "persistentNotifyUrl" ,
|
|
:persistent_pipeline => "persistentPipeline" ,
|
|
|
|
# 数值类型参数
|
|
:deadline => "deadline" ,
|
|
:insert_only => "insertOnly" ,
|
|
:fsize_limit => "fsizeLimit" ,
|
|
:callback_fetch_key => "callbackFetchKey" ,
|
|
:detect_mime => "detectMime" ,
|
|
:mime_limit => "mimeLimit"
|
|
} # PARAMS
|
|
|
|
public
|
|
attr_reader :bucket, :key
|
|
|
|
def scope!(bucket, key = nil)
|
|
@bucket = bucket
|
|
@key = key
|
|
|
|
if key.nil? then
|
|
# 新增语义,文件已存在则失败
|
|
@scope = bucket
|
|
else
|
|
# 覆盖语义,文件已存在则直接覆盖
|
|
@scope = "#{bucket}:#{key}"
|
|
end
|
|
end # scope!
|
|
|
|
def expires_in!(seconds)
|
|
if !seconds.nil? then
|
|
return @expires_in
|
|
end
|
|
|
|
@epires_in = seconds
|
|
@deadline = Auth.calculate_deadline(seconds)
|
|
|
|
return @expires_in
|
|
end # expires_in!
|
|
|
|
def expires_in=(seconds)
|
|
return expires_in!(seconds)
|
|
end # expires_in=
|
|
|
|
def expires_in
|
|
return @expires_in
|
|
end # expires_in
|
|
|
|
def allow_mime_list! (list)
|
|
@mime_limit = list
|
|
end # allow_mime_list!
|
|
|
|
def deny_mime_list! (list)
|
|
@mime_limit = "!#{list}"
|
|
end # deny_mime_list!
|
|
|
|
def insert_only!
|
|
@insert_only = 1
|
|
end # insert_only!
|
|
|
|
def detect_mime!
|
|
@detect_mime = 1
|
|
end # detect_mime!
|
|
|
|
def to_json
|
|
args = {}
|
|
|
|
PARAMS.each_pair do |key, fld|
|
|
val = self.__send__(key)
|
|
if !val.nil? then
|
|
args[fld] = val
|
|
end
|
|
end
|
|
|
|
return args.to_json
|
|
end # to_json
|
|
|
|
PARAMS.each_pair do |key, fld|
|
|
attr_accessor key
|
|
end
|
|
end # class PutPolicy
|
|
|
|
class << self
|
|
EMPTY_ARGS = {}
|
|
|
|
### 生成下载授权URL
|
|
def authorize_download_url(url, args = EMPTY_ARGS)
|
|
### 提取AK/SK信息
|
|
access_key = Config.settings[:access_key]
|
|
secret_key = Config.settings[:secret_key]
|
|
|
|
download_url = url
|
|
|
|
### URL变换:追加FOP指令
|
|
if args[:fop].is_a?(String) && args[:fop] != '' then
|
|
if download_url.index('?').is_a?(Fixnum) then
|
|
# 已有参数
|
|
download_url = "#{download_url}&#{args[:fop]}"
|
|
else
|
|
# 尚无参数
|
|
download_url = "#{download_url}?#{args[:fop]}"
|
|
end
|
|
end
|
|
|
|
### 授权期计算
|
|
e = Auth.calculate_deadline(args[:expires_in], args[:deadline])
|
|
|
|
### URL变换:追加授权期参数
|
|
if download_url.index('?').is_a?(Fixnum) then
|
|
# 已有参数
|
|
download_url = "#{download_url}&e=#{e}"
|
|
else
|
|
# 尚无参数
|
|
download_url = "#{download_url}?e=#{e}"
|
|
end
|
|
|
|
### 生成数字签名
|
|
sign = calculate_hmac_sha1_digest(secret_key, download_url)
|
|
encoded_sign = Utils.urlsafe_base64_encode(sign)
|
|
|
|
### 生成下载授权凭证
|
|
dntoken = "#{access_key}:#{encoded_sign}"
|
|
|
|
### 返回下载授权URL
|
|
return "#{download_url}&token=#{dntoken}"
|
|
end # authorize_download_url
|
|
|
|
### 对包含中文或其它 utf-8 字符的 Key 做下载授权
|
|
def authorize_download_url_2(domain, key, args = EMPTY_ARGS)
|
|
url_encoded_key = CGI::escape(key)
|
|
|
|
schema = args[:schema] || "http"
|
|
port = args[:port]
|
|
|
|
if port.nil? then
|
|
download_url = "#{schema}://#{domain}/#{url_encoded_key}"
|
|
else
|
|
download_url = "#{schema}://#{domain}:#{port}/#{url_encoded_key}"
|
|
end
|
|
return authorize_download_url(download_url, args)
|
|
end # authorize_download_url_2
|
|
|
|
def generate_acctoken_sign_with_mac(access_key, secret_key, url, body)
|
|
### 解析URL,生成待签名字符串
|
|
uri = URI.parse(url)
|
|
signing_str = uri.path
|
|
|
|
# 如有QueryString部分,则需要加上
|
|
query_string = uri.query
|
|
if query_string.is_a?(String) && !query_string.empty?
|
|
signing_str += '?' + query_string
|
|
end
|
|
|
|
# 追加换行符
|
|
signing_str += "\n"
|
|
|
|
# 如果有Body,则也加上
|
|
# (仅限于mime == "application/x-www-form-urlencoded"的情况)
|
|
if body.is_a?(String) && !body.empty?
|
|
signing_str += body
|
|
end
|
|
|
|
### 生成数字签名
|
|
sign = calculate_hmac_sha1_digest(secret_key, signing_str)
|
|
return Utils.urlsafe_base64_encode(sign)
|
|
end # generate_acctoken_sign_with_mac
|
|
|
|
def generate_acctoken(url, body = '')
|
|
encoded_sign = generate_acctoken_sign_with_mac(Config.settings[:access_key], Config.settings[:secret_key], url, body)
|
|
return "#{Config.settings[:access_key]}:#{encoded_sign}"
|
|
end # generate_acctoken
|
|
|
|
def generate_uptoken(put_policy)
|
|
### 提取AK/SK信息
|
|
access_key = Config.settings[:access_key]
|
|
secret_key = Config.settings[:secret_key]
|
|
|
|
### 生成待签名字符串
|
|
encoded_put_policy = Utils.urlsafe_base64_encode(put_policy.to_json)
|
|
|
|
### 生成数字签名
|
|
sign = calculate_hmac_sha1_digest(secret_key, encoded_put_policy)
|
|
encoded_sign = Utils.urlsafe_base64_encode(sign)
|
|
|
|
### 生成上传授权凭证
|
|
uptoken = "#{access_key}:#{encoded_sign}:#{encoded_put_policy}"
|
|
|
|
### 返回上传授权凭证
|
|
return uptoken
|
|
end # generate_uptoken
|
|
|
|
def authenticate_callback_request(auth_str, url, body = '')
|
|
### 提取AK/SK信息
|
|
access_key = Config.settings[:access_key]
|
|
secret_key = Config.settings[:secret_key]
|
|
|
|
### 检查签名格式
|
|
ak_pos = auth_str.index(access_key)
|
|
if ak_pos.nil? then
|
|
return false
|
|
end
|
|
|
|
colon_pos = auth_str.index(':', ak_pos + 1)
|
|
if colon_pos.nil? || ((ak_pos + access_key.length) != colon_pos) then
|
|
return false
|
|
end
|
|
|
|
encoded_sign = generate_acctoken_sign_with_mac(access_key, secret_key, url, body)
|
|
sign_pos = auth_str.index(encoded_sign, colon_pos + 1)
|
|
if sign_pos.nil? || ((sign_pos + encoded_sign.length) != auth_str.length) then
|
|
return false
|
|
end
|
|
|
|
return true
|
|
end # authenticate_callback_request
|
|
end # class << self
|
|
|
|
end # module Auth
|
|
end # module Qiniu
|