Filepicker转换的安全策略问题?

时间:2013-10-03 17:01:29

标签: filepicker.io

我使用Filepicker“读取”然后从客户的计算机“存储”图像。现在我想使用Filepicker调整图像大小但总是得到403错误:

POST https://www.filepicker.io/api/file/w11b6aScR1WRXKFbcXON/convert?_cacheBust=1380818787693 403 (FORBIDDEN) 

我对“读取”,“存储”和“转换”调用使用相同的安全策略和签名。这是错的吗?因为当调用“read”和“store”时,还没有文件句柄(例如InkBlob.url中的最后一个字符串部分)。但似乎必须使用“store”InkBlob返回的文件句柄生成“转换”策略/签名?如果是这种情况,在javascript中更方便的做法是什么?因为在“转换”中我无法访问生成安全策略的Python函数,除非我为此编写API调用。

我的代码片段如下(initialFpSecurityObj是使用空句柄在Python中预生成的):

filepicker.store(thumbFile, {
    policy: initialFpSecurityObj.policy, 
    signature: initialFpSecurityObj.signature,
    location: "S3",
    path: 'thumbs/' + initialFpSecurityObj.uniqueName + '/',
},function(InkBlob){
    console.log("Store successful:", JSON.stringify(InkBlob));
    processThumb(InkBlob);
}, function(FPError){
    console.error(FPError.toString());
});

var processThumb = function(InkBlob){
    filepicker.convert(InkBlob, {
        width: 800,
        height: 600,
        format: "jpg",
        policy: initialFpSecurityObj.policy, 
        signature: initialFpSecurityObj.signature,
    }, function(InkBlob){
        console.log("thumbnail converted and stored at:", InkBlob);
    }, function(FPError){
        console.error(FPError);
    };
}

非常感谢你的帮助。

---编辑---

以下是生成initialFpSecurityObj

的Python代码的代码段
def generateFpSecurityOptions(handle, userId, policyLife=DEFAULT_POLICY_LIFE):
    expiry = int(time() + policyLife)
    json_policy = json.dumps({'handle': handle, 'expiry': expiry})
    policy = base64.urlsafe_b64encode(json_policy)

    secret = 'XXXXXXXXXXXXXX'
    signature = hmac.new(secret, policy, hashlib.sha256).hexdigest()

    uniqueName = hashlib.md5()
    uniqueName.update(signature + repr(time()))
    uniqueName = uniqueName.hexdigest() + str(userId)

    return {'policy':policy, 'signature':signature, 'expiry':expiry, 'uniqueName':uniqueName}

fp_security_options = generateFpSecurityOptions(None, request.user.id)

然后在django模板中检索fp_security_options:

var initialFpSecurityObj = {{fp_security_options|as_json|safe}};

生成fp_security_options的方式对我(前同事的代码)是可疑的,因为句柄是None。

3 个答案:

答案 0 :(得分:0)

我的建议是创建两个策略:一个是句柄绑定的,允许存储文件,另一个不是转换的句柄绑定。在这种情况下,您可以设置较短的到期时间以提高安全级别,前提是您没有指定句柄。

答案 1 :(得分:0)

您的问题可能是您的政策不包含任何“通话”规范。我建议:

json_policy = json.dumps({'handle': handle, 'expiry': expiry, 'call':['pick','store','read','convert']})

但正如我们(非常忙碌;)brettcvz建议的那样,仅限转换,这已经足够了:

json_policy = json.dumps({'handle': handle, 'expiry': expiry, 'call':'convert'})

您可以在安全文档https://developers.inkfilepicker.com/docs/security/

中找到

如果您仍有问题,请使用REST呼叫,它是免费的。以下方法是JavaScript并将URL返回到filepicker的REST端点,该端点可用于检索转换后的图像。 _options对象看起来像这样

var myOptions = {
    w: 150,
    h: 150,
    fit: "crop",
    align: "faces",
    format: "jpg",
    quality: 86
};

并将使用文件选择器REST-API指定的所有参数(请查看https://developers.inkfilepicker.com/docs/web/#inkblob-images)。

function getConvertedURL(_handle, _options, _policy, _signature) {
    // basic url piece
    var url = "https://www.filepicker.io/api/file/" + _handle + "/convert?";
    // appending options
    for (var option in _options) {
        if (_options.hasOwnProperty(option)) {
            url += option + "=" + _options[option] + "&";
        }
    }
    // appending signed policy
    url += "signature=" + _signature + "&policy=" + _policy;
    return url;
}

答案 2 :(得分:0)

所以我终于弄明白了,虽然我之后看到了brettcvz的建议。关键是'转换'工作,我必须指定上传文件的确切句柄(即从'store'或'pickAndStore'调用返回的InkBlob的url属性中字符串的最后一位。

我做的第一件事就是编辑生成安全策略和签名的Python函数:

def generateFpSecurityOptions(handle, userId, policyLife=DEFAULT_POLICY_LIFE):
    expiry = int(time() + policyLife)
    json_policy = json.dumps({'handle': handle, 'expiry': expiry})
    policy = base64.urlsafe_b64encode(json_policy)

    secret = 'XXXXXXXXXXXXXX'
    signature = hmac.new(secret, policy, hashlib.sha256).hexdigest()

    if not handle == None:
        uniqueName = handle
    else:
        uniqueName = hashlib.md5()
        uniqueName.update(signature + repr(time()))
        uniqueName = uniqueName.hexdigest() + str(userId)

    return {'policy':policy, 'signature':signature, 'expiry':expiry, 'uniqueName':uniqueName}

fp_security_options = generateFpSecurityOptions(None, request.user.id)

然后我必须在我们的Django框架中建立API调用,以通过AJAX动态获取此安全策略对象。我很幸运,我的同事以前写过它。所以我只是在Javascript中调用API函数来检索特定于文件的安全策略对象:

var initialFpSecurityObj = {{fp_security_options|as_json|safe}};
filepicker.store(thumbFile, {
    policy: initialFpSecurityObj.policy, 
    signature: initialFpSecurityObj.signature,
    access: "public"
}, function(InkBlob) {
    processThumb(InkBlob);
}, function(FPError) {
    console.error(FPError.toString());
}, function(progress) {
    console.log("Loading: " + progress + "%");
});

var processThumb = function(InkBlob) {
    var fpHandle = InkBlob.url.split('/').pop();
    $.ajax({
        url: API_BASE + 'file_picker_policy',
        type: 'GET',
        data: {
            'filename': fpHandle
        },
        dataType: 'json',
        success: function(data) {
            var newFpSecurityObj = data.data;
        filepicker.convert(InkBlob, {
            width: 800,
            height: 600,
            format: "jpg",
            policy: newFpSecurityObj.policy, 
            signature: newFpSecurityObj.signature,
        }, {
            location: "S3",
            path: THUMB_FOLDER + '/' + newFpSecurityObj.uniqueName + '/', 
        }, function(fp) { // onSuccess
            console.log("successfully converted and stored!");
            // do what you want with the converted file
        }, function(FPError) { // onError
            console.error(FPError);
        }); 
        },
        failure: function() {
        alert("There was an error converting the thumbnail! Please try again.");
        }
    });

};