#java #azure
Вопрос:
Это довольно странная проблема. Мне нужно сгенерировать подписанный 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-адрес в браузере, файл успешно загружен. Аналогично, запуск GET in PostMan для этого URL-адреса работает нормально. Однако, когда я отправляю тот же 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-07amp;se=2021-07-24T12:13:18Zamp;sr=bamp;sp=ramp;sig=BoTaZ9iEA8Cdcbscf6zpWTol32 52rfVyLNDMBlLr1Q=}
Комментарии:
1. Вы уверены, что в вашем браузере или почтальоне не было файла cookie, доступного для авторизации, который был случайно использован. Не имея полной ошибки, я бы предположил, что вызываемая конечная точка требует подтверждения подлинности в какой-либо форме.
2. Не тот случай. Я тоже зарегистрировался инкогнито. Одна необычная вещь, которую я также заметил, заключается в том, что всякий раз, когда добавляется новый файл, он показывает ошибку при загрузке. Но через некоторое время он начинает работать нормально
Ответ №1:
Я могу воспроизвести эту проблему. По сути, проблема возникает из-за
входа в вашу подпись токена SAS. При создании URL
-адреса знак интерпретируется как пробел, и из-за этого ваша авторизация не выполняется.
Все, что вам нужно сделать, это кодировать URL-адрес вашего токена SAS. Как только вы это сделаете, ваш запрос должен сработать просто отлично. Пожалуйста, ознакомьтесь с примером кода ниже:
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-08amp;st=2021-07-24T14:33:27Zamp;se=2021-07-31T14:33:00Zamp;sr=bamp;sp=racamp;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();
}
}
Комментарии:
1. Это работает безупречно. Спасибо. Вы правы, насчет кодировки. Хотя теперь, если я использую сгенерированный URL-адрес в браузере, он не работает из-за кодировки. Не то чтобы у меня для этого были какие-то требования, но могли бы мы найти альтернативу, чтобы созданный URL-адрес работал в любом случае ?
2. Я ранее работал с URL-адресами, возглавляемыми s3, но там не сталкивался с такой проблемой. Я сопоставлю сгенерированные URL-адреса и проведу некоторое расследование, возможно, найду там что-то полезное