You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何可靠判断Microsoft Health Cloud API的过期访问令牌?

嘿,我来帮你搞定这个access token过期判断的问题!针对Microsoft Health Cloud API,其实有两种实用的方式来处理,一种是提前预判过期时间,另一种是处理API返回的错误——后者反而更可靠,毕竟token可能因为被吊销、权限变更等原因失效,不止是单纯过期。

方法1:解析JWT Token的过期时间(提前预判)

Microsoft的access token基本都是JWT格式的,你可以解码它的payload部分,直接获取exp字段(这是一个Unix时间戳,单位是秒,代表token的过期时间点)。这样你就能在发起请求前判断token是否快过期,提前触发刷新流程。

JWT由header.payload.signature三部分组成,用英文点号分隔。你只需要提取中间的payload部分,做Base64Url解码就能拿到包含exp字段的JSON对象。这里给你写个C++的实现示例(适配你用的cpprestsdk风格):

#include <nlohmann/json.hpp>
#include <cpprest/base64.h>
#include <chrono>
#include <algorithm>

// 辅助函数:处理JWT的Base64Url解码(和标准Base64有细微差异)
std::string base64url_decode(const std::string& input) {
    std::string base64_str = input;
    // 替换Base64Url特有的字符
    std::replace(base64_str.begin(), base64_str.end(), '-', '+');
    std::replace(base64_str.begin(), base64_str.end(), '_', '/');
    // 补全Base64需要的padding
    size_t padding = 4 - (base64_str.size() % 4);
    if (padding != 4) {
        base64_str.append(padding, '=');
    }
    // 用cpprestsdk的工具解码
    return utility::conversions::to_utf8string(web::base64decode(base64_str));
}

// 判断access token是否过期(可以提前30秒触发刷新,避免请求时刚好过期)
bool is_access_token_expired(const std::wstring& access_token) {
    auto token_utf8 = utility::conversions::to_utf8string(access_token);
    size_t first_dot = token_utf8.find('.');
    size_t second_dot = token_utf8.find('.', first_dot + 1);
    
    // 不是合法JWT格式,直接判定为无效
    if (first_dot == std::string::npos || second_dot == std::string::npos) {
        return true;
    }
    
    // 提取并解码payload
    std::string payload_str = token_utf8.substr(first_dot + 1, second_dot - first_dot - 1);
    std::string decoded_payload = base64url_decode(payload_str);
    
    nlohmann::json payload = nlohmann::json::parse(decoded_payload);
    // 没有exp字段,判定为无效
    if (!payload.contains("exp")) {
        return true;
    }
    
    // 获取当前Unix时间戳(秒)
    auto now = std::chrono::system_clock::now();
    auto now_seconds = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
    
    // 提前30秒刷新,避免网络延迟导致请求时刚好过期
    return (payload["exp"].get<uint64_t>() - 30) <= now_seconds;
}

注意:这里只解码了payload判断过期时间,没有验证签名——不过微软的API在接收请求时会自动验证签名的合法性,所以提前解码只是为了避免无效请求。如果需要确保token未被篡改,你还需要验证签名,但一般场景下不需要提前做这个。

方法2:处理API返回的401 Unauthorized错误(运行时可靠判断)

就算你提前判断了过期时间,也可能遇到token被提前吊销、权限变更等情况,所以最可靠的方式还是处理API返回的401错误,然后触发刷新token的流程。

结合你给出的代码,修改后可以这样处理:

fire_and_forget read_profile(int retry_count = 0) {
    // 限制重试次数,避免无限循环
    if (retry_count >= 2) {
        co_return;
    }
    
    HttpClient httpClient{};
    httpClient.DefaultRequestHeaders().Authorization({ L"bearer", access_token_ });
    try {
        auto const response{ co_await httpClient.GetAsync(L"https://your-health-cloud-api-endpoint") };
        response.EnsureSuccessStatusCode(); // 非2xx状态码会抛出http_exception
        
        // 处理正常响应
        auto response_body = co_await response.ExtractStringAsync();
        // ... 你的业务逻辑
    } catch (const web::http::http_exception& ex) {
        auto status_code = ex.status_code();
        if (status_code == web::http::status_codes::Unauthorized) {
            // 说明token无效,尝试刷新
            bool refresh_success = co_await refresh_access_token();
            if (refresh_success) {
                // 刷新成功后重试一次请求
                co_await read_profile(retry_count + 1);
            } else {
                // 刷新失败,处理错误(比如提示用户重新登录)
                // ...
            }
        } else {
            // 处理其他HTTP错误
            throw;
        }
    } catch (...) {
        // 处理其他异常
        throw;
    }
}

这里加了重试次数限制,防止刷新token失败后无限循环请求。

额外小建议
  • 刷新token时,调用微软的token端点(一般是https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token,具体以Health Cloud API文档为准),请求参数要带grant_type=refresh_token,以及你的refresh token、client_id等信息。
  • 新的access token和refresh token一定要安全存储,比如加密后存在本地,避免泄露。
  • 如果你的项目可以引入Microsoft Authentication Library (MSAL),强烈建议用它来处理token的获取、刷新和过期判断——MSAL会自动帮你处理这些细节,比手动实现更稳定可靠。

内容的提问来源于stack exchange,提问作者IInspectable

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:14:26