[BotFramework]:是否有办法在使用C#SDK V4开发的BOT中的英雄卡或自适应卡中显示Oauth提示?

时间:2019-05-25 14:01:49

标签: c# oauth botframework bots chatbot

enter image description here我正在使用C#中的V4开发聊天机器人;我已经使用OauthCard提示在瀑布对话框中实现了身份验证功能,我希望此oauth卡提示显示在Hero卡或Adaptive卡或任何其他合适的登录卡中,以便登录功能可在Webchat Channel中使用。

当前,由于无法登录,因此在网络聊天频道中未显示oauth卡提示,因此请考虑是否可以在Hero卡或任何合适的卡中显示oauth Prompt的登录功能,然后继续进行操作身份验证功能。

我使用下面的链接启用了Oauth提示,它在模拟器中可以正常运行:

How to fix next step navigation with oauth prompt in waterfall dialog in SDK V4 bot created using C# without typing anything?

但是无法在Webchat频道中执行此操作,因此认为如果将其保存在英雄卡中,它将可以工作。

  • 语言:C#
  • SDK:V4
  • 频道:WebChat频道

由于我对BOT和编码还很陌生,请按详细的指导方式逐步提供代码或过程,以便我解决问题。

请帮助。

感谢与问候 -ChaitayaNG

我不知道该怎么做,所以我尝试在index.html中执行以下操作: https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/18.customization-open-url

这对我也不起作用。

我也查看了以下链接,但根据我的理解,团队频道有评论,但网络聊天频道没有具体提示:

https://github.com/microsoft/botframework-sdk/issues/4768

我也研究了以下链接,但是由于它与React相关,因此我没有进行调查,因为我正在网络聊天频道和Azure C#中使用聊天机器人:

https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/10.a.customization-card-components

我还尝试在Singin卡中调用oauth提示,该提示不起作用,因为它既不在模拟器中也不在Webchannel中调用提示。

因此,我需要帮助,因为即使在遵循上述链接信息之后,oauth卡也没有加载到Web聊天频道中。因此,以为如果我们可以保留一些卡片,可以做到,但没有发现任何具体的事情也可以做。由于我是BOT和编码的新手,所以我可能错过了一些东西,因此请提供帮助或提供逐步操作指南。

预期结果:由于代码不起作用或在Webchat通道中加载oauth提示在Emulator中工作正常,因此需要在HeroCard或任何其他合适的卡中显示oauth提示。 实际结果:不知道如何实现。

根据Richardson的评论添加详细信息: 理查森,您好,

我在瀑布对话框中使用了OauthPrompt,其中 步骤1:我显示OAuthCard提示符,单击链接,它会弹出一个新窗口以输入凭据,并提供了一个神奇的代码。我在浏览器中输入魔术代码 第2步:在这里,我正在获取令牌并按照我说的那样在Emulator中工作,如下面的链接中所述:

How to fix next step navigation with oauth prompt in waterfall dialog in SDK V4 bot created using C# without typing anything?

来到网上聊天,向我显示了以下内容: [文件类型为'application / vnd.microsoft.card.oauth']

代替登录按钮或链接。

我使用的代码如下:

public class LoginDialog : WaterfallDialog
{
    public LoginDialog(string dialogId, IEnumerable<WaterfallStep> steps = null)
         : base(dialogId, steps)
    {
        AddStep(async (stepContext, cancellationToken) =>
        {
            await stepContext.Context.SendActivityAsync("Please login using below option in order to continue with other options...");

            return await stepContext.BeginDialogAsync("loginprompt", cancellationToken: cancellationToken); // This actually calls the  dialogue of OAuthPrompt whose name is  in EchoWithCounterBot.LoginPromptName.  


        });

        AddStep(async (stepContext, cancellationToken) =>
        {
            Tokenresponse = (TokenResponse)stepContext.Result;

            if (Tokenresponse != null)
            {

                await stepContext.Context.SendActivityAsync($"logged in successfully... ");


                return await stepContext.BeginDialogAsync(DisplayOptionsDialog.Id); //Here it goes To another dialogue class where options are displayed
            }
            else
            {
                await stepContext.Context.SendActivityAsync("Login was not successful, Please try again...", cancellationToken: cancellationToken);


                await stepContext.BeginDialogAsync("loginprompt", cancellationToken: cancellationToken);
            }

            return await stepContext.EndDialogAsync();
        });
    }

    public static new string Id => "LoginDialog";

    public static LoginDialog Instance { get; } = new LoginDialog(Id);
}

在称为Mainrootdialog类的maindialog中:  1.我有一个变量LoginPromptName = "loginprompt"和另一个用于连接名称的参数;  public const string ConnectionName = "conname";

  1. 然后,我有一个名为提示符的方法,该方法接受连接名称并具有与oauthprompt相关的代码,如下所示:
  private static OAuthPrompt Prompt(string connectionName)
        {
            return new OAuthPrompt(
               "loginprompt",
               new OAuthPromptSettings
               {
                   ConnectionName = connectionName,
                   Text = "signin",
                   Title = "signin",
                   Timeout = 300000, // User has 5 minutes to login (1000 * 60 * 
               });
        }
  1. 最后,此提示如下所示添加到对话框集或堆栈中:
     public MainRootDialog(UserState userState)
            : base("root")
        {
            _userStateAccessor = userState.CreateProperty<JObject>("result");

            AddDialog(Prompt(ConnectionName));
            AddDialog(LoginDialog.Instance);            
            InitialDialogId = LoginDialog.Id;
        }

如前所述,您可以从上面共享链接中的评论中看到

但是在网络聊天频道中不会加载按钮或链接,这给了我:  [文件类型为'application / vnd.microsoft.card.oauth']

我尝试了以下GitHub链接,但我无法粘贴或附加HTML文件以供参考: https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/18.customization-open-url

<!DOCTYPE html>
<html lang="en-US">
<head>
    <title>Web Chat: Customize open URL behavior</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!--
      For demonstration purposes, we are using the development branch of Web Chat at "/master/webchat.js".
      When you are using Web Chat for production, you should use the latest stable release at "/latest/webchat.js",
      or lock down on a specific version with the following format: "/4.1.0/webchat.js".
    -->
    <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
    <style>
        html, body {
            height: 100%
        }

        body {
            margin: 0
        }

        #webchat,
        #webchat > * {
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
    <div id="webchat" role="main">
        <iframe src='https://webchat.botframework.com/embed/TestBotForOauthPrompt?s=<<Given my secretkey of web chat channel>>' style='min-width: 400px; width: 100%; min-height: 500px;'></iframe>
    </div>
    <script>
      (async function () {
        // In this demo, we are using Direct Line token from MockBot.
        // To talk to your bot, you should use the token exchanged using your Direct Line secret.
        // You should never put the Direct Line secret in the browser or client app.
        // https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication
        const res = await fetch('https://testbotforoauthprompt.azurewebsites.net//directline//token', { method: 'POST' });
        const { token } = await res.json();
        window.WebChat.renderWebChat({
          directLine: window.WebChat.createDirectLine({ token }),
          // We are adding a new middleware to handle card action
          cardActionMiddleware: () => next => async ({ cardAction, getSignInUrl }) => {
            const { type, value } = cardAction;
            switch (type) {
              case 'signin':
                // For OAuth or sign-in popups, we will open the auth dialog directly.
                const popup = window.open();
                const url = await getSignInUrl();
                popup.location.href = url;
                break;
              case 'openUrl':
                if (confirm(`Do you want to open this URL?\n\n${ value }`)) {
                  window.open(value, '_blank');
                }
                break;
              default:
                return next({ cardAction, getSignInUrl });
            }
          }
        }, document.getElementById('webchat'));
        document.querySelector('#webchat > *').focus();
      })().catch(err => console.error(err));
    </script>
</body>
</html>

进入您提供的链接后,它没有打开,则显示404错误


日期:2019年5月29日 原因:有关Richardson提供的输入的进一步查询

我知道在生成令牌的控制器类中编写了一个.NET代码。有一个HTML页面可加载我们的网络聊天,其中包含必需的脚本 来存储或公开令牌,然后只要打开此HTML文件,聊天机器人就会打开。但是,我有以下查询。这些看起来很基础,但是请耐心等待,因为我是编码新手。

  1. 应该在哪里编写代码,如何调用该代码,因为我未在html脚本中指定 还是在任何地方调用Controller类的Index方法来生成令牌并使用它?或者它将自动调用控制器内部的index方法。如果没有,我应该在哪里自动指定u调用索引方法?是否可以提供完整的解决方案,例如在解决方案中包含机器人代码和控制器类,以便获得更好的画面,以便我可以询问其他任何进一步的查询(如果有)?

  2. 此.net代码是单独的解决方案还是应该在同一机器人解决方案控制器类中编写?如果是单独的解决方案,那么如何将其以蓝色发布到BOT资源?僵尸程序和新解决方案如何在不提供任何连接的情况下自动交互?

  3. 我假设它应该在Visual Studio的同一BOT代码解决方案内创建一个新类。现在,我对此有进一步的查询(基于此假设):

a。根据我对您的解释的理解,post方法不起作用,因为没有令牌生成器,因此它会给您一个错误。您可以使用下面的链接编写代码并获取令牌,该令牌再次出现在问题1中?

What is the correct way to authenticate from JavaScript in an HTML file to the Microsoft Web Chat control for Bot Framework v4?

b。在HTML文件中,如果我按照上面的链接编写了给定的脚本,那么该脚本应位于相同的异步函数中,否则我们必须删除异步函数?

c。如果保持原样,像BOT Avatar之类的样式选项是否仍然有效?其他脚本显示欢迎消息的方式是否相同?

d。在GetElementByID('')中,我们将bot作为上面链接中的值传递,但在实际示例中,我们传递了网络聊天,是否是因为我们已将POST方法更改为新脚本?

e。应该保留张贴方法还是可以将其删除?代替发布行:

const res =等待fetch('https://examplebot.azurewebsites.net/directline/token',{方法:'POST'});         编写如下所示的新脚本:下面给出的脚本(摘自上面的链接):

@model ChatConfig
@{
    ViewData["Title"] = "Home Page";
}
<link href="https://cdn.botframework.com/botframework-webchat/latest/botchat.css" rel="stylesheet" />
<div id="bot" />
<script src="https://cdn.botframework.com/botframework-webchat/latest/botchat.js"></script>
<script>
      BotChat.App({
          directLine: {
              secret: '@Model.Token'
          },
        user: { id: @Model.UserId },
        bot: { id: 'botid' },
        resize: 'detect'
      }, document.getElementById("bot"));
</script>
  1. 您还解释了为避免所有这些复杂性并使它变得简单,只需在文件中保守秘密即可: 当前:const {token} =等待res.json(); 简单起见:const {token} = <>; 我的理解对吗?

  2. 在第四个问题之上:然后,也应删除POST方法行,即行下方,而我们不必编写新的控制器类或Model config上面给出的脚本,其余保持原样: 如下所示,当我打开页面并且OAuth提示和自适应卡可以正常工作时,自动程序会加载:

        Avanade D365 F&O资产BOT     

    <!--
      For demonstration purposes, we are using development branch of Web Chat at "/master/webchat.js".
      When you are using Web Chat for production, you should use the latest stable at "/latest/webchat.js".
      Or locked down on a specific version "/4.1.0/webchat.js".
    -->
    <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
    <style>
        html, body {
            height: 100%
        }
    
        body {
            margin: 0
        }
    
        #webchat {
            height: 100%;
            width: 100%;
        }
    </style>
    

        

    </div>
    <script>
      (async function () {
        // In this demo, we are using Direct Line token from MockBot.
        // To talk to your bot, you should use the token exchanged using your Direct Line secret.
        // You should never put the Direct Line secret in the browser or client app.
        // https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication
    
          const { token } = <<Directline secret from azure portal durect line channel>>;
    
          const styleOptions = {
           botAvatarImage: 'https://docs.microsoft.com/en-us/azure/bot-service/v4sdk/media/logo_bot.svg?view=azure-bot-service-4.0',
           botAvatarInitials: 'BF',
           userAvatarImage: 'https://avatars1.githubusercontent.com/u/45868722?s=96&v=4',
           userAvatarInitials: 'WC',
           bubbleBackground: 'rgba(0, 0, 255, .1)',
           bubbleFromUserBackground: 'rgba(0, 255, 0, .1)'
      };
        // We are using a customized store to add hooks to connect event
        const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
          if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
            // When we receive DIRECT_LINE/CONNECT_FULFILLED action, we will send an event activity using WEB_CHAT/SEND_EVENT
            dispatch({
              type: 'WEB_CHAT/SEND_EVENT',
              payload: {
                name: 'webchat/join',
                value: { language: window.navigator.language }
              }
            });
          }
          return next(action);
        });
        window.WebChat.renderWebChat({
          directLine: window.WebChat.createDirectLine({ token }),
          store
        }, document.getElementById('webchat'));
        document.querySelector('#webchat > *').focus();
      })().catch(err => console.error(err));
    </script>
    

我的理解对吗?


2019年5月30日 ChaitanyaNG的评论更新: 萤幕撷取画面:供您参考,以原样使用Richardson提供的HTML档案,并以我的BOT Direct Channel机密金钥取代

1 个答案:

答案 0 :(得分:1)

真正的问题在您的评论中:

  

来到Webchat时,向我显示了以下内容:[类型为'application / vnd.microsoft.card.oauth'的文件]

其原因是:

<div id="webchat" role="main">
        <iframe src='https://webchat.botframework.com/embed/TestBotForOauthPrompt?s=<<Given my secretkey of web chat channel>>' style='min-width: 400px; width: 100%; min-height: 500px;'></iframe>
    </div>
    <script>
      (async function () {
        // In this demo, we are using Direct Line token from MockBot.
        // To talk to your bot, you should use the token exchanged using your Direct Line secret.
        // You should never put the Direct Line secret in the browser or client app.
        // https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication
        const res = await fetch('https://testbotforoauthprompt.azurewebsites.net//directline//token', { method: 'POST' });
        const { token } = await res.json();

第一个问题:您同时使用iframe(<iframe src='https://webchat...)和 WebChat(<script> (async function ()...)。

修复:删除iframe,仅使用WebChat代码。这在任何地方都没有真正记载,但是iFrame使用的是botchat,它是WebChat的较旧版本,不能与OAuth配合使用,并且会给您带来[File of type...错误。

第二个问题:您没有获得有效的令牌

  

const res =等待fetch('https://testbotforoauthprompt.azurewebsites.net//directline//token',{方法:'POST'});

该代码返回404,因为https://testbotforoauthprompt.azurewebsites.net/directline/token不存在。

您应该follow the guide linked in the code comments,这将使您在标头中带有https://directline.botframework.com/v3/directline/tokens/generate的情况下向Authorization: Bearer <YourSecretFromAzurePortal>发出POST请求。

或者,您可以直接使用const token = <YourSecretFromAzurePortal>。请注意,直接使用您的秘密不是一个好主意。您应该真正设置一个令牌服务器。 This should get you started(注意:这是我打算在上面的评论中使用的链接),但稍微复杂一些。如果您只是想要简单的东西,而又不在乎您的应用程序密码是否泄露,请使用const token = <YourSecretFromAzurePortal>方法。

I just answered a similar question, here.


关于您的更新

令牌生成器

关于:this answer

如果您想将Secret保密,则需要编写自己的令牌服务器。链接答案的前半部分说明了执行此操作的基本方法。您既可以编写自己的代码,也可以在链接的答案中使用示例,也可以使用在该答案中链接的博客文章中的代码。

将代码放置在何处取决于您希望它如何运行。 sample token server与漫游器完全分开。 blog post samples展示了如何将其集成到您的bot中(尽管您也可以单独托管它)。

WebChat客户端向该令牌服务器发出请求,令牌服务器向https://directline.botframework.com/v3/directline/tokens/generate发出请求,并返回响应,该响应是有效的DirectLine令牌。

但是,在许多情况下,您不需要编写自己的令牌服务器的额外安全性。链接的答案的下半部分说明,对于许多简单的机器人而言,暴露秘密的安全风险很小。

我建议您(因为您说过对编码很陌生),所以不要编写自己的令牌服务器,而只将秘密暴露在const token = <Directline secret from azure portal direct line channel>;中(请注意,我删除了{ {1}},因为您的令牌是{})。如果您真的想使用令牌服务器,则需要学习如何用C#编写服务器。

HTML文件

您从string获得的代码使用Angular(我认为)。老了不要使用它。

您应基于WebChat Samples之一创建HTML代码。

看起来就像您的最后一个代码块一样。既然存在很多困惑,请使用以下方法:

examplebot.azurewebsites...

回答您的问题

a。正确。 POST方法不起作用,因为您使用的链接上没有令牌服务器。

b。使用上面的代码

c。是的,您可以根据需要设置样式。由于<!DOCTYPE html> <html lang="en-US"> <head> <title>Web Chat: Custom style options</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- For demonstration purposes, we are using the development branch of Web Chat at "/master/webchat.js". When you are using Web Chat for production, you should use the latest stable release at "/latest/webchat.js", or lock down on a specific version with the following format: "/4.1.0/webchat.js". --> <script src="https://cdn.botframework.com/botframework-webchat/master/webchat.js"></script> <style> html, body { height: 100% } body { margin: 0 } #webchat { height: 100%; width: 100%; } </style> </head> <body> <div id="webchat" role="main"></div> <script> (async function () { // In this demo, we are using Direct Line token from MockBot. // To talk to your bot, you should use the token exchanged using your Direct Line secret. // You should never put the Direct Line secret in the browser or client app. // https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication // Token is found by going to Azure Portal > Your Web App Bot > Channels > Web Chat - Edit > Secret Keys - Show // It looks something like this: pD*********xI.8ZbgTHof3GL_nM5***********aggt5qLOBrigZ8 const token = '<Directline secret from azure portal durect line channel>'; // You can modify the style set by providing a limited set of style options const styleOptions = { botAvatarImage: 'https://docs.microsoft.com/en-us/azure/bot-service/v4sdk/media/logo_bot.svg?view=azure-bot-service-4.0', botAvatarInitials: 'BF', userAvatarImage: 'https://avatars1.githubusercontent.com/u/45868722?s=96&v=4', userAvatarInitials: 'WC', bubbleBackground: 'rgba(0, 0, 255, .1)', bubbleFromUserBackground: 'rgba(0, 255, 0, .1)' }; // We are using a customized store to add hooks to connect event const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => { if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') { // When we receive DIRECT_LINE/CONNECT_FULFILLED action, we will send an event activity using WEB_CHAT/SEND_EVENT dispatch({ type: 'WEB_CHAT/SEND_EVENT', payload: { name: 'webchat/join', value: { language: window.navigator.language } } }); } return next(action); }); window.WebChat.renderWebChat({ directLine: window.WebChat.createDirectLine({ token }), styleOptions }, document.getElementById('webchat')); document.querySelector('#webchat > *').focus(); })().catch(err => console.error(err)); </script> </body> </html> 代码,欢迎消息应该起作用。您可以从WebChat示例中添加其他代码来完成其他事情,是的。

d。请勿使用在'DIRECT_LINE/CONNECT_FULFILLED'中传递“ bot”的代码。使用WebChat示例中的代码或我发布的代码

e。除非使用令牌服务器,否则删除post方法。

  1. 基本上是正确的。请参阅上述回复。

  2. 是的。删除POST方法。您的代码非常接近!


确保您使用的令牌来自此处:

enter image description here