首页 > 解决方案 > 通过从 json 文件中提供应用程序 ID 和密码来进行机器人身份验证

问题描述

我想通过从 json 文件中提供机器人的应用程序 ID 和密码来验证我的机器人,而不是从 web.config 文件中获取详细信息。我尝试通过将详细信息作为参数传递给它来使用 bot 连接器 sdk 中的 connectorclient 类。

我收到“AADSTS7000216:‘client_credentials’授权类型需要‘client_assertion’、‘client_secret’或‘request’”。错误。

任何帮助将非常感激。

标签: c#botframework

解决方案


当前存储机器人应用程序 ID 和密码的方法已经在一个称为机器人文件的 JSON 文件中。在 Bot Builder V4 中,读取 bot 文件非常简单:

botConfig = BotConfiguration.Load(botFilePath, botFileSecret);

如果您想在 V3 中使用类似于 bot 文件的内容,并且希望将凭据保留在 Web.config 之外,您可以创建自己的凭据提供程序。你可能会做这样的事情:

using Microsoft.Bot.Connector;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace NetBot.Credentials
{
    public class BotFileCredentialProvider : SimpleCredentialProvider
    {
        private const string BotFile = "NetBot.bot";

        public BotFileCredentialProvider()
        {
            var assembly = Assembly.GetExecutingAssembly();
            var resourceName = assembly.GetManifestResourceNames().First(resource => resource.Contains(BotFile));

            using (var stream = assembly.GetManifestResourceStream(resourceName))
            {
                dynamic botConfig = JsonConvert.DeserializeObject(new StreamReader(stream).ReadToEnd());
                IEnumerable<dynamic> services = botConfig.services;
                dynamic endpoint = services.FirstOrDefault(service => service.type == "endpoint");

                if (endpoint != null)
                {
                    AppId = endpoint.appId;
                    Password = endpoint.appPassword;
                }
            }
        }
    }
}

这当然取决于我的机器人文件“NetBot.bot”是嵌入式资源。如果您的 JSON 格式与机器人文件不同,您将需要修改它。要使用此凭据提供程序,您需要修改BotAuthentication消息控制器上的属性:

[BotAuthentication(CredentialProviderType = typeof(BotFileCredentialProvider))]
public class MessagesController : ApiController

这当然只使用您的 JSON 凭据来验证传入消息。Bot Builder SDK 仍会在您的 Web.config 中查找凭据以验证传出消息。如果要使用 JSON 凭据发送消息,可以从声明身份获取凭据:

var credentials = ((ClaimsIdentity)HttpContext.Current.User.Identity).GetCredentialsFromClaims();
var connector = new ConnectorClient(new Uri(activity.ServiceUrl), credentials);

这适用于您自己构建连接器客户端时,但如果您想从对话上下文发送消息怎么办?在您的 Global.asax.cs 文件中,您可以插入以下代码以使 SDK 的连接器客户端工厂始终使用声明构造其连接器客户端,就像您在手动构造连接器客户端时所做的那样:

builder.Register(c => ((ClaimsIdentity)HttpContext.Current.User.Identity).GetCredentialsFromClaims())
    .AsSelf()
    .InstancePerLifetimeScope();

推荐阅读