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

如何为嵌入的Superset仪表板实现Refresh Token功能?

Superset嵌入仪表板的Refresh Token实现方案

核心思路

要解决Access Token过期导致Guest Token失效的问题,需要复用Refresh Token自动刷新Access Token,并让前端能动态获取新的Guest Token,而非仅依赖初始生成的令牌。

步骤1:存储Refresh Token与过期时间

登录Superset获取令牌时,除了access_token,还要保存refresh_token和过期时间expires_in(单位秒),留10分钟缓冲避免提前过期:

$dataLoginToken = $this->curlRequest($urlLogin, ['Content-Type:application/json'], 'POST',  $payloadLogin);

// 存储令牌信息到session
$session = $this->get('session');
$session->set('superset_access_token', $dataLoginToken['access_token']);
$session->set('superset_refresh_token', $dataLoginToken['refresh_token']);
// 计算过期时间:当前时间 + 有效期 - 10分钟缓冲
$expiresAt = time() + $dataLoginToken['expires_in'] - 600;
$session->set('superset_access_token_expires_at', $expiresAt);

步骤2:实现Access Token刷新方法

新增方法,用Refresh Token获取新的Access Token,并更新session存储:

private function refreshSupersetAccessToken(): array
{
    $baseUrl = 'http://supersetdomain.com:8088/';
    $session = $this->get('session');
    $refreshToken = $session->get('superset_refresh_token');
    
    $urlRefresh = $baseUrl . 'api/v1/security/refresh';
    $payloadRefresh = [
        'refresh_token' => $refreshToken
    ];
    
    $dataRefresh = $this->curlRequest($urlRefresh, ['Content-Type:application/json'], 'POST', $payloadRefresh);
    
    // 更新session中的令牌信息
    $session->set('superset_access_token', $dataRefresh['access_token']);
    $session->set('superset_refresh_token', $dataRefresh['refresh_token']);
    $expiresAt = time() + $dataRefresh['expires_in'] - 600;
    $session->set('superset_access_token_expires_at', $expiresAt);
    
    return $dataRefresh;
}

步骤3:修改Guest Token生成逻辑,自动刷新Access Token

在生成Guest Token前,先检查Access Token是否过期,过期则自动刷新:

public function generateTokenAction(Request $request, $id = null): Response
{
    $baseUrl = 'http://supersetdomain.com:8088/';
    $session = $this->get('session');
    
    // 检查Access Token是否过期
    $accessToken = $session->get('superset_access_token');
    $expiresAt = $session->get('superset_access_token_expires_at');
    if (time() >= $expiresAt) {
        // 刷新Access Token
        $this->refreshSupersetAccessToken();
        $accessToken = $session->get('superset_access_token');
    }
    
    // 后续获取CSRF、生成Guest Token的逻辑不变,使用更新后的accessToken
    $dashboard = $supersetDashboardRepo->find($id);
    $dashboard_embeddedCode = $dashboard->getEmbeddedCode();
    
    $urlCsrf = $baseUrl . 'api/v1/security/csrf_token/';
    $dataCsrfToken = $this->curlRequest($urlCsrf, ['Authorization: Bearer ' . $accessToken]);
    $csrfToken = $dataCsrfToken['result'];
    
    $urlGuestToken = $baseUrl . 'api/v1/security/guest_token/';
    $payloadGuestToken= [
        'user' => [
            'username' => username,
            'first_name' => first_name,
            'last_name' => last_name,
        ],
        "resources" => [
            [
                "type" => "dashboard", 
                "id" => $dashboard_embeddedCode
            ]
        ],
        "rls" => []
    ];
    $headersGuestToken = [
        'X-CSRF-Token: '. $csrfToken,
        'Content-Type: application/json',
        'Authorization: Bearer ' . $accessToken
    ];
    $dataGuestToken = $this->curlRequest($urlGuestToken, $headersGuestToken, 'POST',  $payloadGuestToken);
    $guestToken = $dataGuestToken['token'];
    
    return new Response(json_encode([
        'embeddedCode' => $dashboard_embeddedCode,
        'guest_token' => $guestToken
    ]));
}

步骤4:前端动态获取Guest Token

将fetchGuestToken改为动态调用后端接口,SDK会在令牌过期时自动触发该方法获取新令牌:

supersetEmbeddedSdk.embedDashboard({
    id: data.embeddedCode,
    supersetDomain: "supersetdomain.com:8088/",
    mountPoint: containerDashboard,
    // 动态调用后端接口获取最新Guest Token
    fetchGuestToken: async () => {
        const response = await fetch(`/guest_token/${dashboardId}`, {
            method: 'GET',
            credentials: 'include' // 携带session信息,后端可读取存储的Refresh Token
        });
        const result = await response.json();
        return result.guest_token;
    },
    dashboardUiConfig: {}
})

额外注意事项

  • 分布式部署适配:多服务器环境下,建议用Redis等分布式存储替代默认session,避免令牌信息不一致。
  • Refresh Token过期处理:若Refresh Token也过期,后端需返回特定状态码,前端引导用户重新加载页面触发登录流程。
  • 错误捕获:在令牌刷新和生成逻辑中添加异常捕获,处理网络错误、令牌无效等场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 05:53:19