【问题标题】:Unable to download Azure blob from Java无法从 Java 下载 Azure Blob
【发布时间】:2021-07-24 23:10:59
【问题描述】:

这是一个相当奇怪的问题。我需要生成一个可以与其他人共享的签名 url,以便在一定的时间限制内下载文件。显然,既然我说的是签名,你不应该要求任何事先许可来下载。以下是我用来上传和下载的代码

  private final BlobSasPermission blobSasPermission = new BlobSasPermission()
      .setReadPermission(true);

  public String uploadAndGenerateSignedUrl(String filePath, String uploadPath) {
    BlobClient blobClient = containerClient.getBlobClient(uploadPath);
    blobClient.uploadFromFile(filePath);

    BlockBlobClient blockBlobClient = blobClient.getBlockBlobClient();
    BlobServiceSasSignatureValues blobServiceSasSignatureValues = new BlobServiceSasSignatureValues(
        OffsetDateTime.now().plusMinutes(azureConfiguration.getExpiryMin()), blobSasPermission);
    return blockBlobClient.getBlobUrl() + "?" + blockBlobClient
        .generateSas(blobServiceSasSignatureValues);
  }

  public void downloadFromUrl(String signedUrl, File file) throws IOException {
    OkHttpClient client = SharedClient.getNewSharedClientBuilder().build();

    Request request = new Request.Builder()
        .url(signedUrl)
        .build();

    okhttp3.Response response = client.newCall(request).execute();
    InputStream inputStream = response.body().byteStream();
    FileUtils.copyInputStreamToFile(inputStream, file);
  }

现在,当我在浏览器中打开生成的 url 时,文件已成功下载。同样,在 PostMan 中为此 url 运行 GET 也可以正常工作。但是,当我将相同的 url 发送到下载方法时,它会失败并出现错误 403,说明服务器无法验证请求。我对此一无所知。我尝试将 http 和 https 协议都添加到签名的 url,但这也没有帮助。

编辑:

添加错误信息
Response{protocol=http/1.1, code=403, message=Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature., url=https://{account}.blob.core.windows.net/{container}/MDConnector/MDTest/Test_16269425/2021-07-24/1627125196450/NormalFile.md?sv=2019-07-07&se=2021-07-24T12:13:18Z&sr=b&sp=r&sig=BoTaZ9iEA8Cdcbscf6zpWTol32+52rfVyLNDMBlLr1Q=}

【问题讨论】:

  • 您确定您的浏览器或邮递员中没有可用的 cookie,其中包含意外使用的身份验证详细信息。没有完整的错误,我建议您调用的端点需要某种形式的身份验证握手。
  • 并非如此。我也检查了隐身。我还注意到的一件不寻常的事情是,每当添加新文件时,它都会在下载时显示错误。但一段时间后,它开始正常工作

标签: java azure


【解决方案1】:

我能够重现此问题。本质上,问题是因为+ 登录您的 SAS 令牌签名。创建 URL 时,+ 符号被解释为空格,因此您的授权失败。

您需要做的是对您的 SAS 令牌进行 URL 编码。一旦你这样做了,你的请求应该可以正常工作。请看下面的示例代码:

package com.company;

import okhttp3.OkHttpClient;
import okhttp3.Request;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

public class Main {

    public static void main(String[] args) throws IOException {
        String url = "https://account.blob.core.windows.net/container/blob.png";
        String sasToken = "sv=2020-04-08&st=2021-07-24T14:33:27Z&se=2021-07-31T14:33:00Z&sr=b&sp=rac&sig=QytPc/+0z/eHd+u4WO0HGOFDOZjVfB+vbQdbR6FFrl4=";//Notice the "+" sign in SAS token.
        sasToken = URLEncoder.encode(sasToken, StandardCharsets.UTF_8.toString());
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(url+"?"+ sasToken).build();
        okhttp3.Response response = client.newCall(request).execute();
        InputStream inputStream = response.body().byteStream();
    }
}

【讨论】:

  • 这完美无瑕。谢谢。你是对的,关于编码。虽然,现在如果我在浏览器中路径生成的 url,由于编码,它不起作用。并不是说我对此有要求,但我们是否可以勉强提出一个替代方案,即生成的网址适用于任何一种情况?
  • 我以前使用过 s3 预签名 url,但在那里没有遇到这样的问题。我会比较生成的 url 并做一些调查,可能会在那里找到有用的东西
猜你喜欢
  • 2019-09-05
  • 2018-09-27
  • 2013-04-16
  • 1970-01-01
  • 2021-10-29
  • 2017-08-20
  • 2014-09-20
  • 2019-04-06
相关资源
最近更新 更多