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

Laravel集成AWS联合登录:SignInToken生成异常排查与解决

解决AWS联合登录SignInToken生成错误的问题

你的核心错误在于直接将STS返回的SessionToken作为SignInToken使用,这不符合AWS联合登录的Token生成规范。正确的SignInToken需要经过多步编码和签名流程,具体步骤及修正后的Laravel代码如下:

正确的SignInToken生成流程

  1. 从STS的getFederationToken结果中提取临时凭证(AccessKeyId、SecretAccessKey、SessionToken),构造标准JSON结构
  2. 对该JSON进行Base64编码
  3. 使用你的AWS SecretKey对Base64编码后的凭证进行HMAC-SHA256签名,再将签名结果Base64编码
  4. 将编码后的凭证与签名用逗号拼接,再次Base64编码得到最终的SignInToken

修正后的控制器代码

use Aws\Sts\StsClient;

public function awsFederatedLogin()
{
    // 初始化STS客户端
    $client = new StsClient([
        'version' => 'latest',
        'region'  => 'us-west-2',
        'credentials' => [
            'key'    => env('AWS_ACCESS_KEY_ID'), // 建议用环境变量而非硬编码
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
        ],
    ]);

    $groupName = env('AWS_FEDERATION_GROUP'); // 从环境变量获取组名
    $policy = json_encode([
        'Version' => '2012-10-17',
        'Statement' => [
            [
                'Effect' => 'Allow',
                'Action' => '*',
                'Resource' => '*'
            ]
        ]
    ]);

    // 获取联邦凭证
    $result = $client->getFederationToken([
        'Name' => 'laravel-federated-user', // 可替换为实际用户名
        'Policy' => $policy,
        'DurationSeconds' => 3600,
        'Tags' => [
            ['Key' => 'group', 'Value' => $groupName]
        ],
    ]);

    $credentials = $result['Credentials'];
    // 1. 构造凭证JSON
    $credentialJson = json_encode([
        'sessionId' => $credentials['AccessKeyId'],
        'sessionKey' => $credentials['SecretAccessKey'],
        'sessionToken' => $credentials['SessionToken']
    ]);

    // 2. Base64编码凭证JSON
    $base64Credentials = base64_encode($credentialJson);

    // 3. 生成HMAC-SHA256签名并Base64编码
    $signature = hash_hmac('sha256', $base64Credentials, env('AWS_SECRET_ACCESS_KEY'), true);
    $base64Signature = base64_encode($signature);

    // 4. 拼接并再次Base64编码得到SignInToken
    $signInToken = base64_encode($base64Credentials . ',' . $base64Signature);

    // 构造最终登录URL
    $loginBaseUrl = 'https://signin.aws.amazon.com/federation?Action=login';
    $issuer = urlencode(env('AWS_FEDERATION_ISSUER')); // 你的应用标识,如https://your-app.com
    $destination = urlencode(env('AWS_FEDERATION_DESTINATION')); // 跳转后的AWS控制台路径,如https://console.aws.amazon.com/

    $finalUrl = sprintf(
        '%s&SigninToken=%s&Issuer=%s&Destination=%s',
        $loginBaseUrl,
        $signInToken,
        $issuer,
        $destination
    );

    return redirect()->to($finalUrl);
}

关键注意事项

  • 避免硬编码凭证:使用Laravel的环境变量(.env文件)存储AWS密钥和配置,提高安全性
  • 策略权限:如果AWS侧已通过组配置了权限,可考虑移除代码中的Policy参数,直接继承组的策略(需确保STS调用者有权限传递组关联的权限)
  • 签名算法:必须使用HMAC-SHA256,且签名时要传递true参数获取原始二进制数据,再进行Base64编码,否则签名会无效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:30:44