Я пытаюсь создать простой эхо-бот, используя SDK платформы ботов Python. Мой бот без проблем работает локально с помощью эмулятора. Я использовал ngrok для создания туннеля https для своего приложения, а затем зарегистрировал бота с помощью службы ботов Azure (тип бота: мультитенантный). Я добавил app_id и секрет из службы бота в свое приложение, и когда я тестирую отправку сообщений из службы бота с помощью функции «Тестирование в веб-чате», я получаю ошибку «Несанкционированный доступ. Запрос не авторизован» в журнале приложения.
Я тестировал эмулятор без учетных данных, и он работает, также я могу успешно получить токен с тем же 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"
Но когда я пытаюсь отправить сообщение из бот-сервиса Test в веб-чат, я получаю сообщение «Несанкционированный доступ. Запрос не авторизован» в приложении.
Трассировки стека:
[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:





Обратитесь в MSDOC. для создания эхо-бота с использованием SDK платформы Python.
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:
class DefaultConfig:
""" Bot Configuration """
PORT = 3978
APP_ID = os.environ.get("MicrosoftAppId", "<AppID>")
APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "<Password>")
ngrok http 3978 --host-header rewrite
http://127.0.0.1:4040https://b437-2402-8100-2844-2f53-1181-ffb7-df6c-560d.ngrok-free.app -> http://localhost:3978 Перейдите к разделу «Конфигурация» в Azure Bot=>Settings, вставьте сгенерированный ngrok forwarding URL в поле «Конечная точка обмена сообщениями», добавив «/api/messages» в конце URL-адреса.

Протестируйте бота в веб-чате:

Консольный вывод:

Я следовал инструкциям, и это сработало, большое спасибо, ура.