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

AWS Gateway V2 WebSocket $connect路径返回要求及Lambda授权器格式问题

兄弟,我之前踩过一模一样的坑!AWS API Gateway V2的WebSocket授权器返回格式要求特别严格,还有$connect路由的规则也容易搞混,我给你梳理清楚:

一、REQUEST类型Lambda授权器的正确返回格式

你之前试的返回claims或者{"statusCode":200}都不符合要求——REQUEST类型的授权器必须返回包含principalId和policyDocument的JSON结构,这是Gateway用来判断是否允许连接的核心依据。

正确的返回示例(验证通过时):

{
  "principalId": "your-cognito-user-sub", // 用Cognito令牌里的sub字段最合理
  "policyDocument": {
    "Version": "2012-10-17", // 固定值,不能改
    "Statement": [
      {
        "Action": "execute-api:Invoke", // 固定值
        "Effect": "Allow", // 允许连接用Allow,拒绝用Deny
        "Resource": "arn:aws:execute-api:us-east-1:1234567890:abc123/prod/$connect" // 必须是当前请求的$connect路径ARN
      }
    ]
  },
  "context": { // 可选,用来传递自定义数据给后端集成
    "username": "johndoe",
    "customAttr": "value"
  }
}

验证失败时,只要把Effect改成Deny就行,Gateway会直接返回403给客户端。

为什么你的之前返回无效?

  • 直接返回claims对象:Gateway完全不识别这个格式,会抛出500错误
  • 返回{"statusCode":200}:同样不符合授权器的规范,Gateway无法解析,导致500
  • 出现403:要么是你返回了Deny策略,要么是Resource的ARN写错了(必须精确匹配当前的API、阶段和$connect路径)
二、WebSocket $connect路径的返回要求

当授权器通过后,$connect路由的后端集成(比如你的Lambda)返回格式很宽松:

  • 只要返回{"statusCode":200}就行,Gateway会忽略返回内容的其他部分,直接建立WebSocket连接
  • 如果授权器返回Deny,Gateway会直接返回403,根本不会调用你的后端集成
  • 注意:$connect路由必须配置授权器,否则默认是拒绝所有连接(除非你开了无授权访问)
三、给你的完整Lambda授权器示例(Node.js)

结合你用Cognito JWKS验证令牌的场景,给你写个可复用的示例:

const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');

// 替换成你的Cognito用户池JWKS地址
const client = jwksClient({
  jwksUri: 'https://cognito-idp.你的区域.amazonaws.com/你的用户池ID/.well-known/jwks.json'
});

function getSigningKey(header, callback) {
  client.getSigningKey(header.kid, (err, key) => {
    const signingKey = key.getPublicKey();
    callback(null, signingKey);
  });
}

exports.handler = async (event) => {
  try {
    // 从headers提取Bearer令牌
    const authHeader = event.headers.Auth;
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return generateAuthResponse('unauthorized', 'Deny', event.routeArn);
    }
    const token = authHeader.split(' ')[1];

    // 验证JWT签名和内容
    const decoded = await new Promise((resolve, reject) => {
      jwt.verify(token, getSigningKey, {
        audience: '你的Cognito应用客户端ID',
        issuer: 'https://cognito-idp.你的区域.amazonaws.com/你的用户池ID'
      }, (err, decoded) => {
        if (err) reject(err);
        else resolve(decoded);
      });
    });

    // 验证通过,返回允许策略
    return generateAuthResponse(decoded.sub, 'Allow', event.routeArn);
  } catch (err) {
    console.error('授权失败:', err);
    // 验证失败返回拒绝策略
    return generateAuthResponse('unauthorized', 'Deny', event.routeArn);
  }
};

// 生成标准授权响应的工具函数
function generateAuthResponse(principalId, effect, resource) {
  return {
    principalId,
    policyDocument: {
      Version: '2012-10-17',
      Statement: [{
        Action: 'execute-api:Invoke',
        Effect: effect,
        Resource: resource
      }]
    }
  };
}
四、Terraform配置的关键检查点

确保你的aws_apigatewayv2_authorizer配置正确:

resource "aws_apigatewayv2_authorizer" "websocket_auth" {
  api_id                     = aws_apigatewayv2_api.your_websocket_api.id
  name                       = "websocket-request-authorizer"
  type                       = "REQUEST"
  authorizer_type            = "REQUEST"
  authorizer_uri             = aws_lambda_function.your_auth_lambda.invoke_arn
  identity_source            = ["$request.header.Auth"] // 对应你取令牌的header字段
  authorizer_payload_format_version = "1.0" // WebSocket授权器必须用1.0,2.0是给HTTP API的
}

// 别忘了给Lambda加允许Gateway调用的权限
resource "aws_lambda_permission" "gateway_auth_invocation" {
  statement_id  = "AllowAPIGatewayInvoke"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.your_auth_lambda.function_name
  principal     = "apigateway.amazonaws.com"
  source_arn    = "${aws_apigatewayv2_api.your_websocket_api.execution_arn}/*/$connect"
}

按这个配置走,wscat的连接应该就能正常通过授权了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 16:32:31