Web端自定义授权器连接AWS IoT Core失败排查
AWS IoT 自定义授权器Web端WSS连接故障问题
已完成的前置配置(已验证生效)
- 已创建专属Lambda授权函数与对应自定义授权器,执行命令
aws iot describe-authorizer --authorizer-name <authorizer-name>可查询到授权器状态为ACTIVE,返回配置如下:
{ "authorizerDescription": { "authorizerName": "<authorizer-name>", "authorizerArn": "...", "authorizerFunctionArn": "...", "tokenKeyName": "<token-key-name>", "tokenSigningPublicKeys": { "<public-key-name>": "-----BEGIN PUBLIC KEY-----\n<public-key-content>\n-----END PUBLIC KEY-----" }, "status": "ACTIVE", "creationDate": "...", "lastModifiedDate": "...", "signingDisabled": false, "enableCachingForHttp": false } }
- 执行
aws iot test-invoke-authorizer命令测试授权器可正常返回认证成功结果:
$ aws iot test-invoke-authorizer --authorizer-name '<authorizer-name>' --token '<public-key-name>' --token-signature '<private-key-content>' { "isAuthenticated": true, "principalId": "...", "policyDocuments": [ "..." ], "refreshAfterInSeconds": 600, "disconnectAfterInSeconds": 3600 } $
故障现象
使用aws-iot-device-sdk开发浏览器端接入,按照官方文档说明,因浏览器不支持自定义请求头,选择通过customAuthQueryString而非customAuthHeaders传递鉴权参数,指定连接协议为wss-custom-auth,拼接相关鉴权参数作为查询字符串,核心代码如下:
const CUSTOM_AUTHORIZER_NAME = '<authorizer-name>'; const CUSTOM_AUTHORIZER_SIGNATURE = '<private-key-content>'; const TOKEN_KEY_NAME = 'TestAuthorizerToken'; const TEST_AUTHORIZER_TOKEN = '<public-key-name>'; function f(k: string, v?: string, p: string = '&'): string { if (!v) return ''; return `${p}${encodeURIComponent(k)}=${encodeURIComponent(v)}`; } const client = new device({ region: '...', clientId: '...', protocol: 'wss-custom-auth' as any, host: '...', debug: true, // customAuthHeaders: { // 'X-Amz-CustomAuthorizer-Name': CUSTOM_AUTHORIZER_NAME, // 'X-Amz-CustomAuthorizer-Signature': CUSTOM_AUTHORIZER_SIGNATURE, // [TOKEN_KEY_NAME]: TEST_AUTHORIZER_TOKEN // }, customAuthQueryString: `${f('X-Amz-CustomAuthorizer-Name', CUSTOM_AUTHORIZER_NAME, '?')}${f('X-Amz-CustomAuthorizer-Signature', CUSTOM_AUTHORIZER_SIGNATURE)}${f(TOKEN_KEY_NAME, TEST_AUTHORIZER_TOKEN)}`, } as any);
运行代码后观测到的现象:
- 客户端向IoT端点发起携带拼接查询字符串的GET请求后,IoT端点返回
101 Switching Protocols响应 - 客户端通过Websocket发送MQTT
CONNECT指令后,连接立即被IoT Core断开,返回1000/1005关闭码 - 查看CloudWatch日志无对应Lambda函数的触发记录,鉴权请求似乎在到达Lambda前就被拦截
- 运行SDK v2提供的官方
custom_authorizer_connect浏览器示例仍无法连接成功
待确认问题
- 是否可以不依赖Cognito身份池或设备证书,仅通过自定义授权器完成MQTT over WSS连接?此前使用Cognito身份池可正常连接,当前业务需要移除Cognito依赖。
- Web场景下是否仅配置
customAuthQueryString参数即可满足自定义鉴权要求? - 各鉴权参数的正确取值规则是什么:
X-Amz-CustomAuthorizer-Name取值为授权器名称已确认,但X-Amz-CustomAuthorizer-Signature是否直接填写私钥内容?TestAuthorizerToken是否为正确的token传递键名?
解答
1. 能否仅靠自定义授权器完成MQTT over WSS连接,移除Cognito/设备证书依赖?
可以。这是AWS IoT Core官方支持的标准Web端无证书接入方案,不需要绑定Cognito身份池,也不需要预置设备证书,自定义授权器可以作为唯一鉴权链路。
2. Web场景只配customAuthQueryString能不能满足鉴权要求?
不能。你现在遇到的「101升级成功、发CONNECT就被断、Lambda无触发记录」,本质是请求在IoT Core的前置校验阶段就被拦截了,根本没走到Lambda授权逻辑,除了拼查询串,你还需要确认两个配置:
- 自定义授权器需要开启允许通过HTTP/WebSocket查询参数触发的权限,你当前配置里
enableCachingForHttp为false不影响连接,但要确认授权器没有配置为仅允许通过Header方式调用 - 你拼的查询参数取值、格式必须完全符合规范,SDK在
wss-custom-auth模式下不会自动帮你补全或转换参数,手动拼的内容错一个字符就会被前置拦截。
3. 鉴权参数正确取值规则
你现在的参数取值有两个核心错误,这是连不上的主要原因:
X-Amz-CustomAuthorizer-Name:填授权器名称,这个取值是对的。X-Amz-CustomAuthorizer-Signature:绝对不能直接填私钥内容。这个字段的正确值是使用你上传到授权器的对应私钥,对token明文做RSA-SHA256签名后,再做Base64编码生成的签名串。你之前用CLI测试时传私钥路径/内容能过,是因为CLI在本地自动帮你完成了签名步骤,浏览器端没有这个自动逻辑,直接传私钥内容会直接导致验签失败。- token键名:不能随便写
TestAuthorizerToken,必须和你创建授权器时设置的tokenKeyName字段值完全一致——就是你贴的授权器返回结果里<token-key-name>对应的实际值,这个键对应的值就是你要签名的token明文(也就是CLI测试时--token传入的内容)。
补充几个容易踩的坑:
- 你当前授权器配置
signingDisabled: false,意味着必须传合法签名,不能跳过签名校验,否则请求会被直接拦截,不会触发Lambda。 - 查询参数要做正确的URL编码,你写的编码函数逻辑没问题,但注意不要在参数里带多余的空格或换行,尤其是签名串和密钥相关的内容。
- 如果没有把该授权器设置为账户的默认授权器,必须确保
X-Amz-CustomAuthorizer-Name参数放在查询串的最前面,否则IoT Core可能识别不到这是自定义授权器请求,直接走默认鉴权逻辑拒绝连接。
内容的提问来源于stack exchange,提问作者Vito De Tullio
相关产品推荐
相关产品推荐

