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

PHP环境下如何合理使用Microsoft Graph API的Access Token

Microsoft Graph API(客户端凭据流)Access Token的使用优化

问题核心

你当前每次页面加载都调用getAccessToken()请求新的Access Token,功能可行但效率低下,完全没必要这么做,下面是具体的优化方案和相关细节:

1. Access Token的有效期

客户端凭据流(client_credentials)获取的Microsoft Graph Access Token,默认有效期是3600秒(1小时),这个值会在token请求的响应体expires_in字段里返回,你可以直接读取该值计算过期时间。

2. 当前实现的问题

每次页面加载都请求新token,会:

  • 增加Azure AD的请求次数,可能触发限流
  • 浪费服务器和网络资源,完全没必要重复获取未过期的token

3. 最佳实践:缓存Access Token

因为你用的是客户端凭据流,这个token是应用级别的(非用户专属),所以应该在服务器端全局缓存,而非存在用户Session里(Session是用户会话级,不同用户共享同一个应用token即可)。

优化后的代码示例(带文件缓存)

// 带缓存的Access Token获取函数
function getAccessToken() {
    $cacheFile = __DIR__ . '/ms_graph_token_cache.json';
    $clientId = "";
    $clientSecret = "";
    $tenant_id = "";
    $grantType = "client_credentials";
    $resource = "https://graph.microsoft.com";
    $tokenEndpoint = "https://login.microsoftonline.com/$tenant_id/oauth2/token";

    // 检查缓存是否存在且未过期(提前5分钟刷新,避免刚好过期的情况)
    if (file_exists($cacheFile)) {
        $cacheData = json_decode(file_get_contents($cacheFile), true);
        if (time() < $cacheData['expires_at'] - 300) {
            return $cacheData['access_token'];
        }
    }

    // 缓存失效,请求新token
    $requestBody = "client_id=$clientId&client_secret=$clientSecret&grant_type=$grantType&resource=$resource";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $tokenEndpoint);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // 建议开启SSL验证,关闭有安全风险
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    $response = curl_exec($ch);
    curl_close($ch);

    $responseJson = json_decode($response, true);
    if (!isset($responseJson['access_token'])) {
        // 处理token请求失败的情况,比如抛出异常或返回错误
        throw new Exception("Failed to get access token: " . json_encode($responseJson));
    }

    // 计算过期时间并缓存
    $cacheData = [
        'access_token' => $responseJson['access_token'],
        'expires_at' => time() + $responseJson['expires_in']
    ];
    file_put_contents($cacheFile, json_encode($cacheData));

    return $responseJson['access_token'];
}

缓存方案选择

  • 单服务器部署:可以用文件缓存、APC/uopz等内存缓存
  • 多服务器部署:建议用Redis、Memcached等分布式缓存,确保所有服务器共享同一个token缓存

4. 关键注意事项

  • 不要把token暴露给前端:客户端凭据流的token拥有应用级权限,权限很高,泄露后会导致租户数据风险
  • 开启SSL验证:你原来的代码关闭了CURLOPT_SSL_VERIFYPEER,这会有中间人攻击风险,建议开启(默认是true,可直接去掉关闭验证的代码)
  • 错误处理:加入token请求失败的处理逻辑,避免因为token获取失败导致整个功能崩溃
  • 定期轮换Client Secret:在Azure AD里定期更新应用的Client Secret,避免泄露风险

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:05:18