Web应用集成Azure Bot:登录后传递Principal对象实现权限控制问询
Absolutely, you can pass the Principal object (or its critical identifying properties) to your Azure Bot before the conversation kicks off—this is a standard approach to ensure your bot only serves financial data tied to the authenticated user. Let’s break down how to implement this:
Web Application Side: Send Principal Data to the Bot
Since your users are already logged into your web app, you’ll have access to their Principal object (with details like user ID, account ID, username, etc.). You’ll pass this data to the Bot via the Bot Framework Web Chat component (assuming that’s how you’re embedding the bot in your web app).
Here’s a JavaScript example of initializing Web Chat with the authenticated user’s Principal data:
// Get the authenticated Principal from your web app's auth system (e.g., ASP.NET Core, Auth0) const authenticatedPrincipal = { userId: "unique-user-id-from-your-auth", accountId: "user-financial-account-identifier", username: "jane_doe" }; // Initialize Web Chat with custom user context window.WebChat.renderWebChat({ directLine: window.WebChat.createDirectLine({ token: "your-generated-direct-line-token" // Generate this securely from your backend }), userID: authenticatedPrincipal.userId, username: authenticatedPrincipal.username, // Attach Principal data to channelData for the bot to receive channelData: { userPrincipal: authenticatedPrincipal } }, document.getElementById("webchat-container"));
Bot Side: Receive and Use the Principal Data
On the bot side, you’ll extract the Principal data from the incoming activity’s channelData, store it in the conversation state (so it’s available for all subsequent messages), and use it to validate and fetch the user’s specific financial holdings.
Here’s a C# example using the Bot Framework SDK:
using Microsoft.Bot.Builder; using Microsoft.Bot.Schema; using Newtonsoft.Json.Linq; public class FinancialBot : ActivityHandler { private readonly ConversationState _conversationState; private readonly IFinancialDataService _financialDataService; public FinancialBot(ConversationState conversationState, IFinancialDataService financialDataService) { _conversationState = conversationState; _financialDataService = financialDataService; } protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken) { // Retrieve and store Principal data on the first message (or every message, if needed) if (turnContext.Activity.ChannelData != null) { var channelData = JObject.FromObject(turnContext.Activity.ChannelData); var userPrincipal = channelData["userPrincipal"].ToObject<AuthenticatedUserPrincipal>(); // Save the Principal to conversation state for future turns var principalAccessor = _conversationState.CreateProperty<AuthenticatedUserPrincipal>("UserPrincipal"); await principalAccessor.SetAsync(turnContext, userPrincipal, cancellationToken); await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken); } // Fetch the stored Principal to validate the user's request var storedPrincipal = await _conversationState .CreateProperty<AuthenticatedUserPrincipal>("UserPrincipal") .GetAsync(turnContext, () => null, cancellationToken); if (storedPrincipal == null) { await turnContext.SendActivityAsync( MessageFactory.Text("Sorry, I can't access your account details. Please ensure you're logged in to the web app."), cancellationToken); return; } // Use the Principal's account ID to fetch only the user's own holdings var userHoldings = await _financialDataService.GetUserHoldingsAsync(storedPrincipal.AccountId); await turnContext.SendActivityAsync( MessageFactory.Text($"Your current holdings:\n{string.Join("\n", userHoldings.Select(h => $"- {h.AssetName}: {h.Quantity} shares"))}"), cancellationToken); } } // Define a class to match the Principal structure sent from the web app public class AuthenticatedUserPrincipal { public string UserId { get; set; } public string AccountId { get; set; } public string Username { get; set; } }
If you’re using Node.js, the logic is similar—extract activity.channelData.userPrincipal and store it in the conversation state using conversationState.createProperty.
Key Security Notes
- Avoid sensitive data: Never pass sensitive information like passwords or full credit card details in the Principal object. Stick to non-sensitive identifiers (user ID, account ID) that the bot can use to fetch data from your secure backend.
- Secure Direct Line tokens: Generate Direct Line tokens from your web app’s backend (not hardcoded in the frontend) to prevent unauthorized access to your bot.
- Validate on the backend: Even if the bot receives a Principal object, always validate the user’s identity against your auth system before fetching financial data—don’t trust the data sent from the frontend blindly.
内容的提问来源于stack exchange,提问作者Samir Shaik

