我正在开发一个项目,其中我通过 Azure Web PubSub 服务构建一个发布-订阅系统。 JavaScript 客户端(订阅者)通过套接字连接,能够接收 Hub 和 Group 中发布的消息。为此,我遵循了本教程:https://learn.microsoft.com/en-us/azure/azure-web-pubsub/tutorial-pub-sub-messages?tabs=javascript
一切正常,因为我还处于 POC 阶段。目前我正在通过上述教程中的 JavaScript 发布消息。但现在我开始将它集成到我现有的用 PHP 开发的应用程序中。因此,我正在考虑使用以下 Azure REST API 进行 Web PubSub 操作:https://learn.microsoft.com/en-us/rest/api/webpubsub/dataplane/web-pub-sub
在此之前,我致力于 Azure Graph API,其中我使用一些重定向 URL 在 Azure 门户上进行了应用程序注册,并分配了一些访问资源的权限。我为 Outlook Mail、Overdrive、SharePoint 执行了此操作,其非常简单的流程获取访问令牌 (JWT) 来访问资源。
但我陷入困境,无法获取 Azure Web PubSub API 的访问令牌。我需要令牌才能通过 REST API 从 PHP 端发布消息。我检查了应用程序注册的 > API 权限部分,没有 Azure Web PubSub 服务的权限。我也在企业应用程序中检查了相同的应用程序。做了一些尝试,但没有获得访问令牌。我知道问题出在许可上。
请帮助我获取此令牌,以便调用 Web PubSub API,或者如果我遗漏了某些内容,请帮助我追踪。欢迎任何建议。 谢谢。
我认为您可以使用以下 REST API 端点:
https://learn.microsoft.com/en-us/rest/api/webpubsub/dataplane/web-pub-sub/grant-permission#webpubsubpermission
https://learn.microsoft.com/en-us/rest/api/webpubsub/dataplane/web-pub-sub/generate-client-token
你尝试过这个吗?
以下是如何在 PHP 中创建 JWT 令牌。我忘记了从哪里得到这段代码...可能是从 jwt.io 那里得到的,我将它从 JavaScript 转换为 PHP...
public function getAccessToken(string $user, $expiry = 0)
{
$t0 = time();
$t1 = $t0 + 3600;
if($expiry > $t0) {
$t1 = $expiry;
}
$header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);
$payload = json_encode([
'iat' => $t0,
'exp' => $t1,
'aud' => $this->getHubUrl(),
'role' => [
"webpubsub.sendToGroup",
"webpubsub.joinLeaveGroup"
],
'sub' => $user,
]);
$primaryKey = $this->secret;
$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
$base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));
$signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, $primaryKey, true);
$base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
$jwt = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;
return $jwt;
}
此函数是从控制器调用的...
public function getAccessToken(Request $request): Response
{
$subscription = $request->query->get('user');
$pubSubService = $this->getPubSubService();
if($subscription) {
$expiry = time() + 3600;
$accessToken = $pubSubService->getAccessToken($subscription, $expiry);
return new JsonResponse(['success' => 1, 'token' => $accessToken, 'expiry' => $expiry]);
} else {
return new Response('No subscription', 400);
}
}
客户端看起来像这样...
this.openClient = function(getAccessTokenUrl, pubSubHubUrl, user, callback, error = null) {
let protocol = 'json.webpubsub.azure.v1';
let token = self.getAccessToken(getAccessTokenUrl, user);
let socketUrl = self.getSocketUrl(pubSubHubUrl, token.token);
console.log('in open client, token expiry = ' + token.expiry);
let ws = new WebSocket(socketUrl, protocol);
ws.onmessage = event => {
return callback(event.data);
}
ws.onerror = event => {
console.log('in on error for PubSub client');
console.log(event);
if(error) {
return error(event.data);
}
}
return { socket: ws, token: token.token, expiry: token.expiry };
}