Node.js使用@azure/storage-blob SDK上传Azure Blob存储时出现NoAuthenticationInformation错误求助
解决Azure Blob存储上传时的"NoAuthenticationInformation"错误
看起来你遇到的核心问题是认证方式的混淆,以及代码里的几处小错误,导致上传操作无法正确通过Azure的认证。让我们一步步拆解问题并修复:
问题分析
- 错误的认证参数传递:你的
createSharedAccessToken函数返回的是SAS令牌字符串,但在createBlob里,你把这个SAS字符串当作SharedKeyCredential实例传给了BlobServiceClient的构造函数。这是完全错误的——BlobServiceClient要么接受SharedKeyCredential对象(用账号名+密钥生成),要么接受包含SAS令牌的完整URL,而不是把SAS单独当作第二个参数。 - 未初始化的变量:
createSharedAccessToken里的expiresOn变量没有提前声明就直接调用setMinutes,这会导致运行时错误,影响SAS令牌的生成。 - 权限可能不足:你传入的权限参数是
'c'(对应Create权限),但上传Blob通常需要Create + Write权限(即权限字符'cw'),仅用'c'可能不足以完成上传操作。
修复方案
方案一:直接使用SharedKeyCredential认证(推荐,更简单)
既然你已经有存储账号的密钥,完全不需要生成SAS来完成上传操作,直接用SharedKeyCredential创建客户端即可,这样能避免SAS相关的错误:
const { BlobServiceClient, StorageSharedKeyCredential } = require("@azure/storage-blob"); module.exports.createBlob = (blobName, containerName, blobContent) => { return new Promise(async (resolve, reject) => { try { // 直接用账号名和密钥创建SharedKeyCredential const sharedKeyCredential = new StorageSharedKeyCredential( process.env.AZURE_BLOB_ACCOUNT, process.env.AZURE_BLOB_KEY ); const blobServiceClient = new BlobServiceClient( `https://${process.env.AZURE_BLOB_ACCOUNT}.blob.core.windows.net`, sharedKeyCredential ); const containerClient = blobServiceClient.getContainerClient(containerName); const blockBlobClient = containerClient.getBlockBlobClient(blobName); // 上传内容,注意blobContent如果是Buffer或字符串都可以,length参数要正确 const blobResponse = await blockBlobClient.upload(blobContent, Buffer.byteLength(blobContent)); resolve(blobResponse); } catch (err) { console.error("上传错误:", err); reject(err); } }); }; // 如果下载需要SAS,可以保留这个函数,但修复其中的错误 module.exports.createSharedAccessToken = (blobName, permission) => { return new Promise((resolve, reject) => { try { const sharedKeyCredential = new StorageSharedKeyCredential( process.env.AZURE_BLOB_ACCOUNT, process.env.AZURE_BLOB_KEY ); const containerName = process.env.AZURE_CONTAINER_NAME; const startsOn = new Date(); // 初始化expiresOn变量 const expiresOn = new Date(); expiresOn.setMinutes(expiresOn.getMinutes() + parseInt(process.env.autoLogoutDuration?.KeyValue || 60)); const blobSAS = generateBlobSASQueryParameters({ containerName, blobName, permissions: BlobSASPermissions.parse(permission), startsOn, expiresOn // 必须指定过期时间 }, sharedKeyCredential).toString(); resolve(decodeURI(blobSAS)); } catch(err) { console.error("生成SAS错误:", err); reject(err); } }); };
方案二:如果必须使用SAS上传
如果你确实需要通过SAS令牌来完成上传,需要正确构造包含SAS的URL来创建客户端:
const { BlobServiceClient, generateBlobSASQueryParameters, BlobSASPermissions, StorageSharedKeyCredential } = require("@azure/storage-blob"); module.exports.createBlob = (blobName, containerName, blobContent) => { return new Promise(async (resolve, reject) => { try { const sasToken = await this.createSharedAccessToken(blobName, 'cw'); // 确保权限包含Create和Write // 构造包含SAS的Blob服务URL const sasUrl = `https://${process.env.AZURE_BLOB_ACCOUNT}.blob.core.windows.net?${sasToken}`; const blobServiceClient = new BlobServiceClient(sasUrl); const containerClient = blobServiceClient.getContainerClient(containerName); const blockBlobClient = containerClient.getBlockBlobClient(blobName); const blobResponse = await blockBlobClient.upload(blobContent, Buffer.byteLength(blobContent)); resolve(blobResponse); } catch (err) { console.error("上传错误:", err); reject(err); } }); }; // 修复后的createSharedAccessToken module.exports.createSharedAccessToken = (blobName, permission) => { return new Promise((resolve, reject) => { try { const sharedKeyCredential = new StorageSharedKeyCredential( process.env.AZURE_BLOB_ACCOUNT, process.env.AZURE_BLOB_KEY ); const containerName = process.env.AZURE_CONTAINER_NAME; const startsOn = new Date(); const expiresOn = new Date(); expiresOn.setMinutes(expiresOn.getMinutes() + parseInt(process.env.autoLogoutDuration?.KeyValue || 60)); const blobSAS = generateBlobSASQueryParameters({ containerName, blobName, permissions: BlobSASPermissions.parse(permission), startsOn, expiresOn }, sharedKeyCredential).toString(); resolve(decodeURI(blobSAS)); } catch(err) { console.error("生成SAS错误:", err); reject(err); } }); };
关键修改说明
- 纠正认证方式:不再把SAS令牌当作
SharedKeyCredential传递,而是要么直接用账号密钥创建SharedKeyCredential,要么把SAS拼到服务URL里。 - 修复未定义变量:初始化
expiresOn变量,避免运行时错误。 - 调整权限:上传时使用
'cw'权限(Create + Write),确保有足够的权限完成上传操作。 - 正确计算内容长度:使用
Buffer.byteLength(blobContent)来获取字符串或Buffer的正确字节长度,避免上传时的长度不匹配问题。
内容的提问来源于stack exchange,提问作者Setanjan Roy
相关产品推荐
相关产品推荐

