From e2b3162f1fac2aca8d859f1192ca262363f3b905 Mon Sep 17 00:00:00 2001 From: Liang Tao Date: Fri, 28 Mar 2014 11:36:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0Auth.generate=5Fuptoken()?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E5=8E=98=E6=B8=85=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E6=8E=88=E6=9D=83=E5=87=AD=E8=AF=81=E7=AD=BE=E5=8F=91=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/qiniu/auth.rb | 122 ++++++++++++++++++++++++++++++++++++++ lib/qiniu/upload.rb | 22 +++++++ spec/qiniu/upload_spec.rb | 44 ++++++++++++++ 3 files changed, 188 insertions(+) diff --git a/lib/qiniu/auth.rb b/lib/qiniu/auth.rb index 04547d3..758838a 100755 --- a/lib/qiniu/auth.rb +++ b/lib/qiniu/auth.rb @@ -8,6 +8,113 @@ require 'qiniu/exceptions' module Qiniu module Auth + 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 + 3600 + end # calculate_deadline + end # class << self + + class PutPolicy + private + def initialize(bucket, key = nil, expires_in = 3600, 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_body => "callbackBody" , + :persistent_ops => "persistentOps" , + :persistent_notify_url => "persistentNotifyUrl" , + :transform => "transform" , + + :deadline => "deadline" , + :insert_only => "insertOnly" , + :fsize_limit => "fsizeLimit" , + :detect_mime => "detectMime" , + :mime_limit => "mimeLimit" , + :fop_timeout => "fopTimeout" + } + + 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 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.public_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 @@ -101,6 +208,21 @@ module Qiniu return acctoken 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 = HMAC::SHA1.new(secret_key).update(encoded_put_policy).digest + encoded_sign = Utils.urlsafe_base64_encode(sign) + + ### 生成上传授权凭证 + uptoken = "#{access_key}:#{encoded_sign}:#{encoded_put_policy}" + end # generate_uptoken end # class << self end # module Auth diff --git a/lib/qiniu/upload.rb b/lib/qiniu/upload.rb index faede91..ecb3743 100755 --- a/lib/qiniu/upload.rb +++ b/lib/qiniu/upload.rb @@ -1,4 +1,5 @@ # -*- encoding: utf-8 -*- +# vim: sw=2 ts=2 module Qiniu module Storage @@ -61,6 +62,27 @@ module Qiniu Utils.http_request url, post_data end # upload_with_token_2 + ### 授权举例 + # put_policy.bucket | put_policy.key | key | 语义 | 授权 + # :---------------- | :------------- | :------ | :--- | :--- + # trivial_bucket | | | 新增 | 允许,最终key为1)使用put_policy.save_key生成的值或2)资源内容的Hash值 + # trivial_bucket | | foo.txt | 新增 | 允许 + # trivial_bucket | | bar.jpg | 新增 | 允许 + # trivial_bucket | foo.txt | | 覆盖 | 允许,由SDK将put_policy.key赋值给key实现 + # trivial_bucket | foo.txt | foo.txt | 覆盖 | 允许 + # trivial_bucket | foo.txt | bar.jpg | 覆盖 | 禁止,put_policy.key与key不一致 + def upload_with_put_policy(put_policy, + local_file, + key = nil, + x_vars = nil) + uptoken = Auth.generate_uptoken(put_policy) + if key.nil? then + key = put_policy.key + end + + return upload_with_token_2(uptoken, local_file, key, x_vars) + end # upload_with_put_policy + private def _generate_action_params(local_file, bucket, diff --git a/spec/qiniu/upload_spec.rb b/spec/qiniu/upload_spec.rb index e344c21..f345c8e 100755 --- a/spec/qiniu/upload_spec.rb +++ b/spec/qiniu/upload_spec.rb @@ -1,4 +1,5 @@ # -*- encoding: utf-8 -*- +# vim: sw=2 ts=2 require 'spec_helper' require 'qiniu/auth' @@ -126,6 +127,49 @@ module Qiniu end end + context ".upload_with_put_policy" do + it "should works" do + pp = Qiniu::Auth::PutPolicy.new(@bucket, @key) + pp.end_user = "why404@gmail.com" + puts 'put_policy=' + pp.to_json + + code, data, raw_headers = Qiniu::Storage.upload_with_put_policy( + pp, + __FILE__, + @key + '-not-equal' + ) + code.should_not == 200 + puts data.inspect + puts raw_headers.inspect + + code, data, raw_headers = Qiniu::Storage.upload_with_put_policy( + pp, + __FILE__, + @key + ) + + code.should == 200 + puts data.inspect + puts raw_headers.inspect + end + end # .upload_with_put_policy + + context ".stat" do + it "should exists" do + code, data = Qiniu::Storage.stat(@bucket, @key) + puts data.inspect + code.should == 200 + end + end + + context ".delete" do + it "should works" do + code, data = Qiniu::Storage.delete(@bucket, @key) + puts data.inspect + code.should == 200 + end + end + ### 测试断点续上传 context ".resumable_upload_with_token" do it "should works" do