You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Azure Function HTTP触发器接收Azure AD B2C用户注册/登录事件

Azure AD B2C登录/注册事件触发Azure Function无数据传入的解决步骤

一、先检查Azure AD B2C的事件配置是否正确

你可能只把Function URL配到了应用里,但B2C默认不会主动把登录/注册事件发去外部端点,得通过以下两种方式配置:

  • 自定义策略方式:在用户旅程的结束步骤加一个<TechnicalProfile>,类型选Restful,指向你的Function URL,同时配置要传递的用户数据(比如用户ID、操作类型、着陆页地址这些)
  • Event Grid集成方式:给B2C租户订阅UserCreated和UserSignedIn事件,把事件推送到你的Function(注意这种方式的事件格式和自定义策略的Rest调用格式不一样)

二、你的Azure Function代码里的问题

  1. 静态Run方法用不了构造注入的IPublishEndpoint:Run是static的,而_publishEndpoint是实例字段,导致你写的PublishMessageToServiceBus方法根本调不了,而且就算能调,你代码里也没实际调用它
  2. 数据接收逻辑太粗糙:直接转成dynamic,没处理空请求或者格式错误的情况,也没对应B2C实际发的格式
  3. 消息发布逻辑没执行:代码里创建了MessageCustomer,但完全没调用发布方法把消息发出去

三、修复后的代码示例

public class MessageBrokerProducerFunction
{
    private readonly IPublishEndpoint _publishEndpoint;

    public MessageBrokerProducerFunction(IPublishEndpoint publishEndpoint)
    {
        _publishEndpoint = publishEndpoint;
    }

    // 去掉static,改成实例方法才能用构造注入的_publishEndpoint
    [FunctionName("B2CCallbackFunction")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        string requestBody;
        try
        {
            requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            if (string.IsNullOrWhiteSpace(requestBody))
            {
                log.LogWarning("Received empty request body");
                return new BadRequestObjectResult("Request body cannot be empty");
            }

            // 别用dynamic,定义强类型模型对应B2C发的事件格式,避免出错
            var b2cEventData = JsonConvert.DeserializeObject<B2cEventData>(requestBody);
            if (b2cEventData == null)
            {
                log.LogError("Failed to parse request body into expected format");
                return new BadRequestObjectResult("Invalid request body format");
            }

            // 提取需要的用户旅程信息构建消息
            var message = new MessageCustomer(
                Guid.NewGuid(),
                b2cEventData.UserId,
                b2cEventData.OperationType, // 比如是"SignIn"还是"SignUp"
                b2cEventData.LandingPageUrl,
                DateTime.UtcNow
            );

            // 调用发布方法,用用户ID作为sessionId
            await PublishMessageToServiceBus(message, log, b2cEventData.UserId);

            return new OkObjectResult($"Successfully processed event for user {b2cEventData.UserId}");
        }
        catch (Exception ex)
        {
            log.LogError(ex, "Error processing B2C event");
            return new StatusCodeResult(StatusCodes.Status500InternalServerError);
        }
    }

    private async Task PublishMessageToServiceBus(object message, ILogger logger, string sessionId)
    {
        try
        {
            await _publishEndpoint.Publish(message, context => context.SetSessionId(sessionId));
            logger.LogInformation($"Message sent successfully for session {sessionId}: {JsonConvert.SerializeObject(message)}");
        }
        catch (Exception ex)
        {
            logger.LogError(ex, $"Failed to send message for session {sessionId}, retrying...");
            await Task.Delay(TimeSpan.FromSeconds(10));
            // 建议加个重试次数限制,别无限循环
            await PublishMessageToServiceBus(message, logger, sessionId);
        }
    }

    // 强类型模型,根据B2C实际发送的字段调整
    public class B2cEventData
    {
        public string UserId { get; set; }
        public string OperationType { get; set; }
        public string LandingPageUrl { get; set; }
        // 可以再加其他需要的字段,比如Email、DisplayName之类的
    }
}

四、本地测试怎么验证

  1. 用Postman模拟B2C请求:
    • 按照B2C的事件格式写JSON请求体(比如Event Grid的事件包含eventType、data;自定义策略的Rest调用包含你配置的Claims)
    • 发POST请求到本地Function的地址(比如http://localhost:7071/api/B2CCallbackFunction),记得带上Function密钥(如果是Function级别的授权)
    • 看Function的日志,确认有没有收到数据,有没有成功发消息
  2. 本地调试:在VS里启动Function调试,打个断点看req.Body的内容,直接确认有没有数据传进来
  3. 检查授权级别:如果测试时嫌带密钥麻烦,可以暂时把AuthorizationLevel.Function改成Anonymous,生产环境改回去

五、要注意的关键点

  • 如果用Event Grid,得确保本地Function能被外网访问,测试时可以用ngrok把本地端口暴露出去
  • 如果用自定义策略,要在策略里配置<OutputClaim>把需要的用户数据传给Function,并且Rest技术配置文件的Method要设成POST
  • 生产环境一定要给PublishMessageToServiceBus加重试次数限制,不然出错会无限循环
  • 排查的时候可以先把requestBody完整打日志,看看B2C到底发的是什么格式,再调整模型

内容的提问来源于stack exchange,提问作者Laura Díaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 18:56:24