Microsoft Bot Framework 应用程序在尝试使用“在网络聊天中测试”发送消息时抛出错误“未经授权的访问。请求未授权”

问题描述 投票:0回答:1

我正在尝试使用 Python 机器人框架 SDK 构建一个简单的 echo 机器人。我的机器人使用模拟器在本地运行没有问题。我使用 ngrok 创建到我的应用程序的 https 隧道,然后使用 azure 机器人服务(机器人类型:多租户)注册机器人。我将 bot 服务中的 app_id 和密钥添加到我的应用程序中,当我使用“在网络聊天中测试”功能测试从 bot 服务发送消息时,我在应用程序日志中收到错误“未经授权的访问。请求未授权”。

我在没有凭据的模拟器上进行了测试,它可以工作,当我使用以下命令进行测试时,我也可以使用相同的 app_id 和密码成功获取令牌:“curl -k -X POST https://login.microsoftonline.com/botframework.com/ oauth2/v2.0/token -d“grant_type=client_credentials&client_id=my_app_id_here&client_secret=my_app_secret_here&scope=https%3A%2F%2Fapi.botframework.com%2F.default”

但是,当我尝试在网络聊天中从机器人服务的测试发送消息时,我在应用程序上收到“未经授权的访问。请求未授权”。

堆栈跟踪:

    [2024-05-23 22:27:15,827] ERROR in app: Exception on /api/messages [POST]
    Traceback (most recent call last):
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/flask/app.py", line 1473, in wsgi_app
        response = self.full_dispatch_request()
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/flask/app.py", line 882, in full_dispatch_request
        rv = self.handle_user_exception(e)
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/flask/app.py", line 880, in full_dispatch_request
        rv = self.dispatch_request()
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/flask/app.py", line 865, in dispatch_request
        return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/app.py", line 30, in messages
        loop.run_until_complete(task)
    File "/home/metalmlover/.pyenv/versions/3.8.16/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
        return future.result()
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/botbuilder/core/bot_framework_adapter.py", line 442, in process_activity
        identity = await self._authenticate_request(activity, auth_header)
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/botbuilder/core/bot_framework_adapter.py", line 551, in _authenticate_request
        claims = await JwtTokenValidation.authenticate_request(
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/botframework/connector/auth/jwt_token_validation.py", line 49, in authenticate_request
        raise PermissionError("Unauthorized Access. Request is not authorized")
    PermissionError: Unauthorized Access. Request is not authorized
    127.0.0.1 - - [23/May/2024 22:27:15] "POST /api/messages HTTP/1.1" 500 -
    127.0.0.1 - - [23/May/2024 22:27:25] "OPTIONS /api/messages HTTP/1.1" 200 -
    127.0.0.1 - - [23/May/2024 22:34:59] "OPTIONS /api/messages HTTP/1.1" 200 -
    127.0.0.1 - - [23/May/2024 22:35:04] "OPTIONS /api/messages HTTP/1.1" 200 -
    [2024-05-23 22:35:08,763] ERROR in app: Exception on /api/messages [POST]
    Traceback (most recent call last):
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/flask/app.py", line 1473, in wsgi_app
        response = self.full_dispatch_request()
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/flask/app.py", line 882, in full_dispatch_request
        rv = self.handle_user_exception(e)
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/flask/app.py", line 880, in full_dispatch_request
        rv = self.dispatch_request()
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/flask/app.py", line 865, in dispatch_request
        return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/app.py", line 30, in messages
        loop.run_until_complete(task)
    File "/home/metalmlover/.pyenv/versions/3.8.16/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
        return future.result()
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/botbuilder/core/bot_framework_adapter.py", line 442, in process_activity
        identity = await self._authenticate_request(activity, auth_header)
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/botbuilder/core/bot_framework_adapter.py", line 551, in _authenticate_request
        claims = await JwtTokenValidation.authenticate_request(
    File "/home/metalmlover/dev/microsoft bot framework/BotTutorialSample/Python_tutorial/01-EchoBot/venv/lib/python3.8/site-packages/botframework/connector/auth/jwt_token_validation.py", line 49, in authenticate_request
        raise PermissionError("Unauthorized Access. Request is not authorized")
    PermissionError: Unauthorized Access. Request is not authorized

我的应用程序代码:

    from flask import Flask,request,Response
    from botbuilder.schema import Activity
    from botbuilder.core import BotFrameworkAdapter,BotFrameworkAdapterSettings
    import asyncio    
    from echobot import EchoBot    
    app = Flask(__name__)
    loop = asyncio.get_event_loop()    
    botadaptersettings = BotFrameworkAdapterSettings("my_app_id_here","my_app_secret_here")
    botadapter = BotFrameworkAdapter(botadaptersettings)    
    ebot = EchoBot()    
    @app.route("/api/messages",methods=["POST"])
    def messages():    
        if "application/json" in request.headers["content-type"]:
        jsonmessage = request.json
        else:
        return Response(status=415)
    
        activity = Activity().deserialize(jsonmessage)
    
        async def turn_call(turn_context):
            await ebot.on_turn(turn_context)
    
        task = loop.create_task(botadapter.process_activity(activity,"",turn_call))
        loop.run_until_complete(task)
        return "200"
    
    if __name__ == '__main__':
        app.run('localhost',3978)

我的机器人:

    from botbuilder.core import TurnContext

    class EchoBot:
        async def on_turn(self,turn_context:TurnContext):
            await turn_context.send_activity(turn_context.activity.text)

Azure 机器人配置: enter image description here

botframework azure-bot-service
1个回答
0
投票

请参阅MSDOC。使用Python框架sdk创建一个echo Bot。

app.py
:

import sys
import traceback
from datetime import datetime

from aiohttp import web
from aiohttp.web import Request, Response, json_response
from botbuilder.core import (BotFrameworkAdapter, BotFrameworkAdapterSettings,
                             TurnContext)
from botbuilder.core.integration import aiohttp_error_middleware
from botbuilder.schema import Activity, ActivityTypes

from bot import MyBot
from config import DefaultConfig

CONFIG = DefaultConfig()

SETTINGS = BotFrameworkAdapterSettings(CONFIG.APP_ID, CONFIG.APP_PASSWORD)
ADAPTER = BotFrameworkAdapter(SETTINGS)

async def on_error(context: TurnContext, error: Exception):

    print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr)
    traceback.print_exc()

    await context.send_activity("The bot encountered an error or bug.")
    await context.send_activity(
        "To continue to run this bot, please fix the bot source code."
    )

    if context.activity.channel_id == "emulator":

        trace_activity = Activity(
            label="TurnError",
            name="on_turn_error Trace",
            timestamp=datetime.utcnow(),
            type=ActivityTypes.trace,
            value=f"{error}",
            value_type="https://www.botframework.com/schemas/error",
        )

        await context.send_activity(trace_activity)


ADAPTER.on_turn_error = on_error

# Create the Bot
BOT = MyBot()

# Listen for incoming requests on /api/messages
async def messages(req: Request) -> Response:
    # Main bot message handler.
    if "application/json" in req.headers["Content-Type"]:
        body = await req.json()
    else:
        return Response(status=415)

    activity = Activity().deserialize(body)
    auth_header = req.headers["Authorization"] if "Authorization" in req.headers else ""

    response = await ADAPTER.process_activity(activity, auth_header, BOT.on_turn)
    if response:
        return json_response(data=response.body, status=response.status)
    return Response(status=201)


def init_func(argv):
    APP = web.Application(middlewares=[aiohttp_error_middleware])
    APP.router.add_post("/api/messages", messages)
    return APP
if __name__ == "__main__":
    APP = init_func(None)

    try:
        web.run_app(APP, host="0.0.0.0", port=CONFIG.PORT)
    except Exception as error:
        raise error

config.py:

  • 更新 Microsoft 应用程序 ID 和密码。
class DefaultConfig:
    """ Bot Configuration """

    PORT = 3978
    APP_ID = os.environ.get("MicrosoftAppId", "<AppID>")
    APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "<Password>")
  • 使用 ngrok 命令创建新隧道。
ngrok http 3978 --host-header rewrite
  • 网页界面
    http://127.0.0.1:4040
  • 转发
    https://b437-2402-8100-2844-2f53-1181-ffb7-df6c-560d.ngrok-free.app
    ->
    http://localhost:3978  

导航到 Azure Bot=>Settings 中的

Configuration
,通过在 URL 末尾添加“/api/messages”将生成的
ngrok forwarding URL
粘贴到 Messaging endpoint 字段中。

enter image description here

在网络聊天中测试机器人:

enter image description here

控制台输出:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.