如何处理 DirectLine 连接错误

我们使用 bot 框架运行一个 bot,并使用 JS 中的直线从我们的网站连接到它。我们从自定义 API 端点获取令牌,并将令牌存储在 sessionStorage 中。然后我们使用连接到机器人


directLine = await window.WebChat.createDirectLine({

  token,

  conversationId,

  watermark: "0"

});

一切正常,但是当我让页面打开的时间过长时,sessionStorage 中的令牌会过期。页面刷新或导航到不同的页面会导致方法内部出现 403 错误createDirectLine。只要 sessionStorage 持有该令牌,就会导致聊天机器人无法连接。这种行为对我来说并不奇怪,但我不知道如何处理。


我想要的是简单地清除 sessionStorge,请求一个新令牌并在发生这种情况时开始新对话。但我不知道该怎么做。如何从该方法中获取 403 错误createDirectLine?或者有没有办法预先验证令牌?我已经尝试在该createDirectLine方法周围放置一个 try/catch 块,但是 403 错误没有出现在 catch 中。


阿波罗的战车
浏览 186回答 2
2回答

红糖糍粑

此解决方案仅用于解决令牌过期后发生的 403 错误(我认为在 30 分钟内)。更好的解决方案是将 conversationId 与令牌一起存储并使用它获取新令牌。检查官方机器人服务文档。// to shorten code, we store in sessionStorage as separate items.const expirationDuration = 1000 * 60 * 30; // 30 minutesconst currentTime = new Date().getTime();const timeTokenStored = sessionStorage.getItem("timeTokenStored") || currentTime;// if token is stored over 30 minutes ago, ignore it and get a new one. Otherwise, use it.if ((currentTime - timeTokenStored) > expirationDuration) {&nbsp; &nbsp; &nbsp; const res = await fetch('https://<yourTokenEndpoint>', { method: 'POST' });&nbsp; &nbsp; &nbsp; const { token } = await res.json();}&nbsp; &nbsp; &nbsp; const currentTime = new Date().getTime();&nbsp; &nbsp; &nbsp; sessionStorage.setItem("timeTokenStored", currentTime);&nbsp; &nbsp; &nbsp; sessionStorage.setItem('token', token);else {&nbsp; const token = sessionStorage.getItem("token")}当您使用它时,您不妨将它存储在 localStorage 中。这样,您的机器人将跟随用户。

有只小跳蛙

我找到了解决方案。我们可以通过刷新令牌来检查令牌是否有效。如果刷新导致错误,则令牌不再有效。如果刷新成功,令牌将再有效一个小时。因此,我们向后端添加了(可重用的)函数以使用https://directline.botframework.com/v3/directline/tokens/refresh. 我们更改了前端代码以调用我们新的刷新功能。前端代码:// Gets a new token from the cloud.async function requestToken() {&nbsp; if (!sessionStorage['webchatToken']) {&nbsp; &nbsp; const res = await fetch('https://' + serviceName + '.azurewebsites.net/api/token');&nbsp; &nbsp; // If the request was succesfull, store the token and userId.&nbsp; &nbsp; if (res.status == 200) {&nbsp; &nbsp; &nbsp; const jsonResult = await res.json();&nbsp; &nbsp; &nbsp; sessionStorage['webchatToken'] = jsonResult.token;&nbsp; &nbsp; &nbsp; sessionStorage['webchatUserId'] = jsonResult.userId;&nbsp; &nbsp; &nbsp; console.log(`Got token from cloud`);&nbsp; &nbsp; &nbsp; // refresh the token every 15 minutes.&nbsp; &nbsp; &nbsp; setTimeout(() => {&nbsp; &nbsp; &nbsp; &nbsp; refreshToken();&nbsp; &nbsp; &nbsp; }, 60000 * 15); // 15 minutes&nbsp; &nbsp; }&nbsp; &nbsp; // If the request was not succesfull, retry.&nbsp; &nbsp; else {&nbsp; &nbsp; &nbsp; console.log(`Tried to get token, but goterror ` + res.status + `. Retrying.`);&nbsp; &nbsp; &nbsp; await requestToken();&nbsp; &nbsp; }&nbsp; }&nbsp; // If there is already a token in storage, refresh the existing one instead of requesting a new one.&nbsp; else {&nbsp; &nbsp; console.log(`Got token from sessionStorage`);&nbsp; &nbsp; await refreshToken();&nbsp; }}// Refreshes an existing token so it doesn't expire.async function refreshToken() {&nbsp; // Refresh the token if it exists in storage.&nbsp; if (sessionStorage['webchatToken']) {&nbsp; &nbsp; const res = await fetch('https://' + serviceName + '.azurewebsites.net/api/token/refresh?token=' + sessionStorage['webchatToken'],&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; method: 'POST'&nbsp; &nbsp; });&nbsp; &nbsp; // If refresh was succesfull we are done.&nbsp; &nbsp; if (res.status == 200) {&nbsp; &nbsp; &nbsp; console.log(`Refreshed token`);&nbsp; &nbsp; }&nbsp; &nbsp; // If refresh was not succesfull, clear the token from storage and request a new one. The token is probably expired.&nbsp; &nbsp; else {&nbsp; &nbsp; &nbsp; console.log(`Tried to refresh token, but got error ` + res.status + `. Requesting new token.`);&nbsp; &nbsp; &nbsp; sessionStorage.clear();&nbsp; &nbsp; &nbsp; await requestToken();&nbsp; &nbsp; }&nbsp; }&nbsp; // If there is no token in storage, request a new token.&nbsp; else {&nbsp; &nbsp; console.log(`Tried to refresh token, but token is not defined. Requesting new token.`);&nbsp; &nbsp; sessionStorage.clear();&nbsp; &nbsp; await requestToken();&nbsp; }}后端代码:[HttpGet][Route("api/token")]public async Task<ObjectResult> GetToken(){&nbsp; HttpClient client = new HttpClient();&nbsp; HttpRequestMessage request = new HttpRequestMessage(&nbsp; &nbsp; HttpMethod.Post,&nbsp; &nbsp; $"https://directline.botframework.com/v3/directline/tokens/generate");&nbsp;&nbsp; request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _configuration.DirectLineKey);&nbsp; var userId = $"dl_{Guid.NewGuid()}";&nbsp; request.Content = new StringContent(&nbsp; &nbsp; JsonConvert.SerializeObject(new { User = new { Id = userId } }),&nbsp; &nbsp; Encoding.UTF8,&nbsp; &nbsp; "application/json");&nbsp; var response = await client.SendAsync(request);&nbsp; string token = String.Empty;&nbsp; int expiresIn = 0;&nbsp; if (response.IsSuccessStatusCode)&nbsp; {&nbsp; &nbsp; var body = await response.Content.ReadAsStringAsync();&nbsp; &nbsp; token = JsonConvert.DeserializeObject<DirectLineToken>(body).token;&nbsp; &nbsp; expiresIn = JsonConvert.DeserializeObject<DirectLineToken>(body).expires_in;&nbsp; }&nbsp; return Ok(new { token, userId, expiresIn });}[HttpPost][Route("api/token/refresh/")]public async Task<ObjectResult> RefreshToken(string token){&nbsp; HttpClient client = new HttpClient();&nbsp; HttpRequestMessage request = new HttpRequestMessage(&nbsp; &nbsp; HttpMethod.Post,&nbsp; &nbsp; $"https://directline.botframework.com/v3/directline/tokens/refresh");&nbsp; request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);&nbsp; var response = await client.SendAsync(request);&nbsp; token = String.Empty;&nbsp; int expiresIn = 0;&nbsp; if (response.IsSuccessStatusCode)&nbsp; {&nbsp; &nbsp; var body = await response.Content.ReadAsStringAsync();&nbsp; &nbsp; token = JsonConvert.DeserializeObject<DirectLineToken>(body).token;&nbsp; &nbsp; expiresIn = JsonConvert.DeserializeObject<DirectLineToken>(body).expires_in;&nbsp; }&nbsp; if (string.IsNullOrEmpty(token))&nbsp; &nbsp; return Problem("Token incorrect");&nbsp; return Ok(new { token, expiresIn });}我希望发布这个可能对某人有用。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript