如何创建 AWS chime 预签名 URL 以生成前端的 Web 套接字 url?

问题描述

我正在尝试生成一个预签名的 Web 套接字 URL,以获取前端中 AWS chime 的实时消息通知,如图 here 所示。我计划使用 lambda 将其部署为单独的后端 API。我完全按照 here 所示进行操作,但是在前端连接到此生成的 URL 时出现“未经授权”错误。任何人都可以帮助我解决在 python 中生成这个预先签名的 URL 需要做些什么吗?我想我对 chime 使用了错误的主机/服务参数。

import json
import boto3
import urllib.parse
import requests
import uuid
import datetime
import sys,os,base64,datetime,hashlib,hmac
import os

def sign(key,msg):
    return hmac.new(key,msg.encode('utf-8'),hashlib.sha256).digest()

def getSignatureKey(key,dateStamp,regionName,serviceName):
    kDate = sign(('AWS4' + key).encode('utf-8'),dateStamp)
    kRegion = sign(kDate,regionName)
    kService = sign(kRegion,serviceName)
    kSigning = sign(kService,'aws4_request')
    return kSigning
    

def lambda_handler(event,context):
    method = 'GET'
    algorithm = 'AWS4-HMAC-SHA256'
    service = 'chime'
    host = client.get_messaging_session_endpoint()['Endpoint']['Url']
    region = 'us-east-1'

    #Getting the messaging endpoint using boto3
    client = boto3.client('chime',region_name='us-east-1')
    endpoint='wss://'+client.get_messaging_session_endpoint()['Endpoint']['Url']

    user_id=event['querystringparameters'].get('userId')
    session_id=event['querystringparameters'].get('sessionId')
    user_id_arn=f'arn:aws:chime:us-east-1:11******:app-instance/03457-*****-412345-b3e4-123444/user/{user_id}'

    access_key=os.environ['access_key']
    secret_key=os.environ['secret_key']

    #Following the steps as shown in the AWS documentation https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
    t = datetime.datetime.utcNow()
    amz_date = t.strftime('%Y%m%dT%H%M%sZ')
    datestamp = t.strftime('%Y%m%d')
    credential_scope=urllib.parse.quote(f'{access_key}/{datestamp}/us-east-1/chime/aws4_request',safe='')

    canonical_uri = '/connect'
    payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()
    canonical_headers = 'host:' + host + '\n'
    signed_headers = 'host'
    credential_scope=urllib.parse.quote(f'{access_key}/{datestamp}/us-east-1/chime/aws4_request',safe='')

    canonical_querystring=''
    canonical_querystring+='?X-Amz-Algorithm=AWS4-HMAC-SHA256'
    canonical_querystring+=f'&X-Amz-Credential={credential_scope}'
    canonical_querystring += '&X-Amz-Date=' + amz_date
    canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers
    canonical_querystring += '&X-Amz-Expires=3600'
    canonical_querystring += '&sessionId=' + session_id
    canonical_querystring += '&userArn=' + user_id_arn

    canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
    hashed_canonical_request=hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
    string_to_sign = algorithm + '\n' +  amz_date + '\n' +  credential_scope + '\n' +  hashed_canonical_request
    signing_key = getSignatureKey(secret_key,datestamp,region,service)
    signature = hmac.new(signing_key,(string_to_sign).encode("utf-8"),hashlib.sha256).hexdigest()
    canonical_querystring += '&X-Amz-Signature=' + signature
    request_url = endpoint  + canonical_uri+canonical_querystring

    return_dict={'wssUrl':request_url}
    return return dict       

解决方法

任何想知道问题是什么的人 - 我们必须将 user_id_arn 传递为 arn%3Aaws%3Achime%3Aus-east-1%3A123456789012%3Aapp-instance%2f5abcdefg-cc50-4a70-a88e-fd07351d3c2a%2Fuser%2Fcustom-user-id 而不是 arn:aws:chime:us-east-1:123456789012:app-instance/f5abcdefg-cc50-4a70-a88e-fd07351d3c2a/user/custom-user-id

完整的工作代码:

import json
import boto3
import urllib.parse
import requests
import uuid
import datetime
import sys,os,base64,datetime,hashlib,hmac
import os

def sign(key,msg):
    return hmac.new(key,msg.encode('utf-8'),hashlib.sha256).digest()

def getSignatureKey(key,dateStamp,regionName,serviceName):
    kDate = sign(('AWS4' + key).encode('utf-8'),dateStamp)
    kRegion = sign(kDate,regionName)
    kService = sign(kRegion,serviceName)
    kSigning = sign(kService,'aws4_request')
    return kSigning
    
def handler():
    # TODO: Replace with your info
    session_id= # <session_id>
    user_id_arn= # <user_id_arn>
    access_key= # <access_key>
    secret_key= # <secret_key>

    # Following the steps as shown in the AWS documentation https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
    t = datetime.datetime.utcnow()
    amz_date = t.strftime('%Y%m%dT%H%M%SZ')
    datestamp = t.strftime('%Y%m%d')

    # Getting the messaging endpoint using boto3
    client = boto3.client('chime',region_name='us-east-1')
    hostname = client.get_messaging_session_endpoint()['Endpoint']['Url']    

    method = 'GET'
    service = 'chime'
    region = 'us-east-1'
    canonical_uri = '/connect'
    canonical_headers = 'host:' + hostname + '\n'
    signed_headers = 'host'
    algorithm = 'AWS4-HMAC-SHA256'
    credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'

    canonical_querystring = ''
    canonical_querystring += 'X-Amz-Algorithm=AWS4-HMAC-SHA256'
    canonical_querystring += '&X-Amz-Credential=' + urllib.parse.quote_plus(access_key + '/' + credential_scope)
    canonical_querystring += '&X-Amz-Date=' + amz_date
    canonical_querystring += '&X-Amz-Expires=3600'
    canonical_querystring += '&X-Amz-Security-Token=' + urllib.parse.quote(session_token,safe='')
    canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers
    canonical_querystring += '&sessionId=' + urllib.parse.quote(session_id,safe='')
    canonical_querystring += '&userArn=' + urllib.parse.quote(user_id_arn,safe='')

    payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()
    canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
    string_to_sign = algorithm + '\n' +  amz_date + '\n' +  credential_scope + '\n' +  hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
    signing_key = getSignatureKey(secret_key,datestamp,region,service)
    signature = hmac.new(signing_key,(string_to_sign).encode('utf-8'),hashlib.sha256).hexdigest()
    canonical_querystring += '&X-Amz-Signature=' + signature
    request_url = 'wss://' + hostname + canonical_uri + '?' + canonical_querystring
    return_dict={'wssUrl':request_url}

    return return_dict

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...