如何修复Azure文件上传中的‘RestError: 请求认证失败’错误
我用Hono、NeDB和TypeScript搭建后端实现文件上传功能,前端选择文件后发送请求:
const res = await axios.post( `${import.meta.env.VITE_BACKEND_URL}/files/sas?file=${encodeURIComponent( file.name )}&permission=${permission}&container=${blobStorageSettings.containerName}&timerange=${timerange}`, { headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + window.localStorage.getItem('jwt').replace(/"/g, '') } } )
后端对应端点代码:
files.post("/sas", async (c: Context) => { try { ... const fileName = c.req.query('file') || 'nonamefile'; const permissions = c.req.query('permission') || 'w'; const timerange = parseInt(c.req.query('timerange') || '10'); // 默认10分钟 const containerName = blobStorageDetails.containerName || 'anonymous'; const sasUrl = await generateSASUrl( blobStorageDetails.serviceName, blobStorageDetails.serviceKey, containerName, fileName, permissions, timerange ); ...
generateSASUrl函数代码:
export const generateSASUrl = async ( serviceName: string, serviceKey: string, containerName: string, fileName: string, // 文件夹层级和文件名: 'folder1/folder2/filename.ext' permissions = 'r', // 默认只读 timerange = 1 // 默认1分钟 ): Promise<string> => { if (!serviceName || !serviceKey || !fileName || !containerName) { return 'Generate SAS function missing parameters'; } const blobServiceClient = getBlobServiceClient(serviceName, serviceKey); const containerClient = await createContainer( containerName, blobServiceClient ); const blockBlobClient = await containerClient.getBlockBlobClient(fileName); // 最佳实践:设置时间限制 const SIXTY_MINUTES = timerange * 60 * 1000; const NOW = new Date(); // 创建SAS URL const accountSasTokenUrl = await blockBlobClient.generateSasUrl({ startsOn: NOW, expiresOn: new Date(new Date().valueOf() + SIXTY_MINUTES), permissions: BlobSASPermissions.parse(permissions), // Blob只读权限 protocol: SASProtocol.Https // 仅允许HTTPS访问Blob }); return accountSasTokenUrl; };
我认为错误出在调用createContainer创建容器的环节:
async function createContainer( containerName: string, blobServiceClient: BlobServiceClient ): Promise<ContainerClient> { const containerClient = blobServiceClient.getContainerClient(containerName); console.log("containerClient", containerClient); await containerClient.createIfNotExists(); console.log("Container created"); return containerClient; }
containerClient已创建,但执行await containerClient.createIfNotExists()时出现错误:
Error: RestError: Server failed to authenticate the request. Please refer to the information in the www-authenticate header.
www-authenticate头信息:
"www-authenticate": "Bearer authorization_uri=https://login.microsoftonline.com/75df096c-8b72-48e4-9b91-cbf79d87ee3a/oauth2/authorize resource_id=https://storage.azure.com",
我参考了微软官方文件上传教程,尝试跳过containerClient.createIfNotExists()但问题仍存在,请问怎么修复这个认证错误?
核对存储账户密钥与名称
确认serviceName是Azure存储账户的完整名称(不含后缀),serviceKey是存储账户的主/次访问密钥(可在Azure门户存储账户的「访问密钥」页面获取),检查是否有复制错误(比如多余空格、特殊字符缺失)。不要使用SAS令牌或Azure AD密钥替代账户访问密钥。检查存储账户的认证策略
如果你的存储账户启用了Azure AD强制认证(即禁用了账户密钥访问),使用账户密钥生成SAS会直接失败。此时有两种方案:- 在Azure门户存储账户的「配置」页面,开启「允许使用账户密钥进行访问」;
- 改用Azure AD身份验证生成SAS:比如使用服务主体、托管身份获取令牌,再调用生成SAS的接口。
验证容器名称合法性
Azure存储容器名称必须符合规则:全部小写,只能包含字母、数字、短横线,且短横线不能作为开头或结尾,长度在3-63字符之间。如果containerName不符合规则,可能会触发看似认证错误的异常。同步服务器时间
Azure Storage对请求的时间戳有严格要求,若后端服务器时间与UTC时间偏差超过15分钟,会直接拒绝请求并返回认证错误。检查服务器系统时间是否正确,必要时开启自动时间同步。确认权限参数有效性
确保permissions参数是BlobSASPermissions支持的字符(比如r读、w写、d删除等),避免传入无效字符导致请求解析失败。
内容的提问来源于stack exchange,提问作者Hollow Dev

