添加Azure Function读取队列后,Service Bus写入代码报401错误求助
问题分析与解决方案
401 InvalidSignature异常排查
出现该异常的核心原因是写入代码使用的身份凭证签名无效,结合你的场景,优先排查以下几点:
- 确认写入身份(本地开发为当前登录Azure的用户,Azure部署为托管身份)已被分配Service Bus Data Sender角色(需在Service Bus命名空间层级或队列层级配置)
- 本地开发环境中,若存在多个Azure身份(如Azure CLI、Visual Studio、Azure PowerShell),可能导致
DefaultAzureCredential获取到错误的身份,需显式指定身份来源 - 清除本地Token缓存:删除
%USERPROFILE%\.azure\accessTokens.json文件后重新运行写入代码
修改后的消息写入代码(修复401问题)
以下是调整后的无密码写入代码,增加了身份指定和Token配置,避免签名异常:
using Azure.Messaging.ServiceBus; using Azure.Identity; // 配置Service Bus命名空间和队列名称 string fullyQualifiedNamespace = "<你的Service Bus命名空间>.servicebus.windows.net"; string queueName = "<你的队列名称>"; // 显式指定使用Visual Studio身份(可根据实际环境替换为AzureCliCredential、ManagedIdentityCredential等) var credential = new VisualStudioCredential(); // 创建ServiceBusClient,配置Token刷新选项 var clientOptions = new ServiceBusClientOptions { TokenCredentialOptions = new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud } }; await using var client = new ServiceBusClient(fullyQualifiedNamespace, credential, clientOptions); ServiceBusSender sender = client.CreateSender(queueName); // 构造并发送消息 string messageBody = "测试消息"; var message = new ServiceBusMessage(messageBody); await sender.SendMessageAsync(message); Console.WriteLine($"消息已发送: {messageBody}");
Azure Function读取成功后发送消息的实现
使用Service Bus触发的Function,读取消息处理完成后,再向指定队列发送确认消息:
1. 安装NuGet包
确保Function项目安装以下包:
Azure.Messaging.ServiceBus Microsoft.Azure.Functions.Extensions Microsoft.Azure.WebJobs.Extensions.ServiceBus Azure.Identity
2. Function代码实现
using Azure.Messaging.ServiceBus; using Azure.Identity; using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Logging; namespace ServiceBusFunctionDemo { public class ServiceBusReadAndSendFunction { private readonly ServiceBusClient _serviceBusClient; private readonly string _targetQueueName = "<发送确认消息的队列名称>"; // 可复用原队列或新队列 public ServiceBusReadAndSendFunction() { // 使用托管身份(Azure部署)或本地身份(开发环境)创建ServiceBusClient string fullyQualifiedNamespace = "<你的Service Bus命名空间>.servicebus.windows.net"; var credential = new DefaultAzureCredential(); _serviceBusClient = new ServiceBusClient(fullyQualifiedNamespace, credential); } [FunctionName("ServiceBusReadAndSend")] public async Task Run( [ServiceBusTrigger("<原读取队列名称>", Connection = "ServiceBusConnection")] ServiceBusReceivedMessage message, ServiceBusMessageActions messageActions, ILogger log) { log.LogInformation($"收到消息: {message.Body}"); try { // 处理消息逻辑(此处省略业务代码) // 处理成功后发送确认消息 var sender = _serviceBusClient.CreateSender(_targetQueueName); var confirmMessage = new ServiceBusMessage($"消息 {message.MessageId} 已成功处理"); await sender.SendMessageAsync(confirmMessage); log.LogInformation($"已发送确认消息"); // 完成消息,从队列移除 await messageActions.CompleteMessageAsync(message); } catch (Exception ex) { log.LogError(ex, "处理消息失败"); // 异常时放弃消息,重新入队 await messageActions.AbandonMessageAsync(message); } } } }
3. 配置文件(local.settings.json)
本地开发时,配置无密码连接(无需连接字符串):
{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "dotnet", "ServiceBusConnection": "<你的Service Bus命名空间>.servicebus.windows.net" } }
关键注意事项
- Azure部署Function时,需为Function的托管身份分配Service Bus Data Receiver(读取原队列)和Service Bus Data Sender(发送确认消息)角色
- 本地开发时,确保当前登录Azure的用户拥有上述对应角色
内容的提问来源于stack exchange,提问作者Siegfried
相关产品推荐
相关产品推荐

