笨蛋ovo

笨蛋ovo

為 Cloudreve 添加 Backblaze B2 支持

image.png

目前最新的配置教程已同步到 Cloudreve 官方文档
如果你需要更简略的版本请直接查阅官方文档
官方文档那个也是我写的

問題分析#

首先按照 Cloudreve 官方文档 進行配置,然後你大概率會發現配置完之後上傳依然會報錯 (廢話,要是不報錯也不會寫這篇文章)

打開 F12 看一下請求,控制台這邊有一個跨域報錯

Access to XMLHttpRequest at 'https://s3.us-east-001.backblazeb2.com/xxx' from origin 'https://demo.cloudreve.org' 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.

然後檢查下響應標頭

Cache-Control: max-age=0, no-cache, no-store
Connection: keep-alive
Content-Length: 216
Content-Type: application/xml
Date: Wed, 19 Jun 2024 15:54:31 GMT
Server: nginx
Strict-Transport-Security: max-age=63072000
X-Amz-Id-2: aM+Y1ZDJYZBU2hn2JYjDlOMNkuWF2
X-Amz-Request-Id: 4c38if3n9n98732

很明顯,缺了跨域頭

這裡我們再拿 Cloudflare R2 的響應標頭對比下

Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: ETag
Cf-Ray: 89649ob992b2d0f-LAX
Connection: keep-alive
Content-Length: 0
Date: Wed, 19 Jun 2024 15:56:54 GMT
Etag: "264f5757014d2dn3ij3ij2fc90cd7b"
Server: cloudflare
Vary: Origin, Accept-Encoding

發現缺了什麼沒有,重點在於

Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: ETag

上面那個是跨域,下面那個是斷點續傳需要的

解決方案#

首先先在 Backblaze 後台配置 CORS 規則
2024-06-19T16:57:09.png

然後你會發現並沒有什麼用,由於 Backblaze 極為 簡潔 (jian lou) 的後台頁面,你沒法直接在 Web 後台進行響應頭的修改(這裡改的是讀取文件的請求頭,上傳的沒法改)
所以我們得在 B2 CLI 進行修改

首先先去 Application Keys 新建一個登錄密鑰(這裡用 Master Application Key 或者 Application Key 應該都行,Application Key 的話自己給下權限)
然後下載 B2 CLI

如果你是 Linux 用戶,你可以運行以下的命令來下載 B2 CLI

# 下載最新二進制
wget https://github.com/Backblaze/B2_Command_Line_Tool/releases/latest/download/b2-linux
# 给予可执行权限
chmod +x ./b2-linux

執行 b2 account authorize 進行賬號登錄,根據提示填入 keyIDapplicationKey
當你看到輸出了類似下面的一大坨東西,就說明登錄成功了

$ ./b2-linux account authorize
Backblaze application key ID: <keyID>
Backblaze application key: 
{
    "accountAuthToken": "<Token>",
    "accountFilePath": "/home/bakaArch/.config/b2/account_info",
    "accountId": "<accountID>",
    "allowed": {
        "bucketId": null,
        "bucketName": null,
        "capabilities": [
            "bypassGovernance",
            "deleteBuckets",
            "deleteFiles",
            "deleteKeys",
            "listAllBucketNames",
            "listBuckets",
            "listFiles",
            "listKeys",
            "readBucketEncryption",
            "readBucketNotifications",
            "readBucketReplications",
            "readBucketRetentions",
            "readBuckets",
            "readFileLegalHolds",
            "readFileRetentions",
            "readFiles",
            "shareFiles",
            "writeBucketEncryption",
            "writeBucketNotifications",
            "writeBucketReplications",
            "writeBucketRetentions",
            "writeBuckets",
            "writeFileLegalHolds",
            "writeFileRetentions",
            "writeFiles",
            "writeKeys"
        ],
        "namePrefix": null
    },
    "apiUrl": "https://api001.backblazeb2.com",
    "applicationKey": "<applicationKey>",
    "applicationKeyId": "<applicationKeyId>",
    "downloadUrl": "https://f001.backblazeb2.com",
    "isMasterKey": true,
    "s3endpoint": "https://s3.us-east-001.backblazeb2.com"
}

首先,執行 b2 bucket get <bucketName> 列出一下存儲桶詳情

{
    "accountId": "<accountID>",
    "bucketId": "<bucketID>",
    "bucketInfo": {},
    "bucketName": "<bucketName>",
    "bucketType": "allPrivate",
    "corsRules": [
        {
            "allowedHeaders": [
                "authorization",
                "range"
            ],
            "allowedOperations": [
                "b2_download_file_by_id",
                "b2_download_file_by_name"
            ],
            "allowedOrigins": [
                "*"
            ],
            "corsRuleName": "downloadFromAnyOrigin",
            "exposeHeaders": null,
            "maxAgeSeconds": 3600
        },
        {
            "allowedHeaders": [
                "authorization",
                "range"
            ],
            "allowedOperations": [
                "s3_head",
                "s3_get"
            ],
            "allowedOrigins": [
                "*"
            ],
            "corsRuleName": "s3DownloadFromAnyOrigin",
            "exposeHeaders": null,
            "maxAgeSeconds": 3600
        }
    ],
    "defaultRetention": {
        "mode": null
    },
    "defaultServerSideEncryption": {
        "mode": "none"
    },
    "isFileLockEnabled": false,
    "lifecycleRules": [],
    "options": [
        "s3"
    ],
    "replication": {
        "asReplicationDestination": null,
        "asReplicationSource": null
    },
    "revision": 7
}

注意這裡 corsRules,可以看到這裡的 allowedOperations 只有 s3_heads3_get 方法(如果你沒有在 Web 端配置跨域,那這兩條顯然你也是見不到的)
而為了能夠在 Cloudreve 中正常操作文件,我們還需要為其添加 s3_put s3_post s3_delete 方法
同時,為了能夠在 S3 兼容 API 中正常進行分塊上傳,我們還需要允許 B2 返回 ETag
我們在前面複製的存儲桶詳情中,修改 corsRules 中的 allowedOperations,在 exposeHeaders 中添加 ETag,在 allowedHeaders 中添加 content-type
修改完之後應該是長這樣

"corsRules": [
    {
        "allowedHeaders": [
            "authorization",
            "range",
            "content-type"
        ],
        "allowedOperations": [
            "s3_head",
            "s3_get",
            "s3_put",
            "s3_post",
            "s3_delete"
        ],
        "allowedOrigins": [
            "*"
        ],
        "corsRuleName": "s3DownloadFromAnyOriginWithUpload",
        "exposeHeaders": ["ETag"],
        "maxAgeSeconds": 3600
    }
]

因為通過 Cloudreve 上傳文件只需要用到 S3 兼容 API,所以我這邊直接刪去了 B2 的部分

如果你希望得到更好的安全性,可以將 allowedOrigins 中的星號換成你 Cloudreve 的域名

修改完之後,使用命令 b2 bucket update <bucketName> --cors-rules '配置json' 更新配置
更新完之後會重新輸出一遍完整配置,檢查一下是否正確

$ ./b2-linux bucket update <bucketName> --cors-rules '[
    {
        "allowedHeaders": [
            "authorization",
            "range",
            "content-type"
        ],
        "allowedOperations": [
            "s3_head",
            "s3_get",
            "s3_put",
            "s3_post",
            "s3_delete"
        ],
        "allowedOrigins": [
            "*"
        ],
        "corsRuleName": "s3DownloadFromAnyOriginWithUpload",
        "exposeHeaders": ["ETag"],
        "maxAgeSeconds": 3600
    }
]'

{
    "accountId": "<accountID>",
    "bucketId": "<bucketID>",
    "bucketInfo": {},
    "bucketName": "<bucketName>",
    "bucketType": "allPrivate",
    "corsRules": [
        {
            "allowedHeaders": [
                "authorization",
                "range",
                "content-type"
            ],
            "allowedOperations": [
                "s3_head",
                "s3_put",
                "s3_delete",
                "s3_post",
                "s3_get"
            ],
            "allowedOrigins": [
                "*"
            ],
            "corsRuleName": "s3DownloadFromAnyOriginWithUpload",
            "exposeHeaders": [
                "etag"
            ],
            "maxAgeSeconds": 3600
        }
    ],
    "defaultRetention": {
        "mode": null
    },
    "defaultServerSideEncryption": {
        "mode": "none"
    },
    "isFileLockEnabled": false,
    "lifecycleRules": [],
    "options": [
        "s3"
    ],
    "replication": {
        "asReplicationDestination": null,
        "asReplicationSource": null
    },
    "revision": 9
}

到這裡,應該就沒有問題了
再次嘗試上傳文件,問題解決
2024-06-19T17:43:57.png

此文由 Mix Space 同步更新至 xLog
原始鏈接為 https://blog.baka.plus/posts/tech/Add-Backblaze-B2-support-to-Cloudreve


載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。