[英]Is it safe to access/update Azure Blob storage from browser using SAS token?
[英]Azure blob storage sas token generation using js
我在azure函数中运行此函数,以获取用于浏览器应用程序的sas令牌,以上传到azure blob存储:
var azure = require('azure-storage');
module.exports = function(context, req) {
if (req.body.container) {
// The following values can be used for permissions:
// "a" (Add), "r" (Read), "w" (Write), "d" (Delete), "l" (List)
// Concatenate multiple permissions, such as "rwa" = Read, Write, Add
context.res = generateSasToken(
context,
req.body.container,
req.body.blobName,
req.body.permissions
);
} else {
context.res = {
status: 400,
body: "Specify a value for 'container'"
};
}
context.done(null, context);
};
function generateSasToken(context, container, blobName, permissions) {
var connString = process.env.AzureWebJobsStorage;
var blobService = azure.createBlobService(connString);
// Create a SAS token that expires in an hour
// Set start time to five minutes ago to avoid clock skew.
var startDate = new Date();
startDate.setMinutes(startDate.getMinutes() - 5);
var expiryDate = new Date(startDate);
expiryDate.setMinutes(startDate.getMinutes() + 60);
permissions = azure.BlobUtilities.SharedAccessPermissions.READ +
azure.BlobUtilities.SharedAccessPermissions.WRITE +
azure.BlobUtilities.SharedAccessPermissions.DELETE +
azure.BlobUtilities.SharedAccessPermissions.LIST;
var sharedAccessPolicy = {
AccessPolicy: {
Permissions: permissions,
Start: startDate,
Expiry: expiryDate
}
};
var sasToken = blobService.generateSharedAccessSignature(
container,
blobName,
sharedAccessPolicy
);
context.log(sasToken);
return {
token: sasToken,
uri: blobService.getUrl(container, blobName, sasToken, true)
};
}
然后,我在客户端调用此url,然后尝试使用以下代码上传:
const search = new URLSearchParams(`?${token}`);
const sig = encodeURIComponent(search.get('sig'));
const qs = `?sv=${search.get('sv')}&ss=b&srt=sco&sp=rwdlac&se=${search.get('sv')}&st=${search.get(
'st'
)}&spr=https&sig=${sig}`;
return `${url}/${containerName}/${filename}${qs}`;
会生成如下网址:
哪个返回此错误:
403(服务器无法验证请求。确保正确构成了包括签名的Authorization标头的值。)
如果我从azure门户生成sas令牌,则它可以正常工作,因此生成的url如下所示:
但我的网址看起来像这样:
我不知道该怎么做才能使这个工作
您的Azure函数代码正确,并且
var sasToken = blobService.generateSharedAccessSignature(
container,
blobName,
sharedAccessPolicy
);
正是您需要上传blob的sasToken。 无需像第二个代码片段中那样再次处理令牌(实际上是错误处理)。
预期Azure门户(Account SAS)中的sas令牌与代码(Service SAS)中生成的sas令牌不同。 看一下doc 。
总而言之,
确保连接字符串属于您要连接的存储。 您可以避免麻烦,直接替换为var connString = process.env.AzureWebJobsStorage;
与var connString = "connectionStringGotFromPortal";
如果确认为1,则您的Azure函数代码正确,并按预期返回令牌
{ token: sasToken, uri: blobService.getUrl(container, blobName, sasToken, true) };
根据您提供的第二个代码段,您只需要
return `${url}/${containerName}/${filename}?${token}`;
如果令牌与返回的函数相同。
问题在于,在服务器端代码中,您正在创建Service SAS
,然后仅获取代码的签名部分( sig
),并在客户端上创建Account SAS
。
由于用于创建令牌的参数现已更改(在原始参数中,您没有ss
, srt
等参数,但是在创建自己的URL时将插入这些参数),修改SAS URL,您将得到403错误。 发生这种情况是因为服务器再次基于URL参数计算签名,并将其与URL中传递的签名进行比较。 由于两个签名不匹配,因此出现403错误。
由于返回的是blob的SAS URL,因此无需在客户端上创建URL。 您可以简单地使用从客户端API层返回的uri
,并使用该uri
进行上传。
正如Jerry Liu的答案所解释的那样,您的Azure函数会生成正确的令牌,并且已经为您提供了正确的uri使用,其中包括您的Blob名称和令牌。
在您的客户端,您还可以使用azure-sdk-for-js
// This is the response from your api with token and uri
const uri = response.uri;
const pipeline = StorageURL.newPipeline(new AnonymousCredential());
// Your uri already includes the full blob url with SAS signature
const blockBlobURL = BlockBlobURL.fromBlobURL(new BlobURL(uri, pipeline));
const uploadBlobResponse = await blockBlobURL.upload(
Aborter.none,
file,
file.size,
{ blobHTTPHeaders: { blobContentType: `${mime}; charset=utf-8`} }
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.