Google cloud platform 谷歌云CDN使用URL前缀签名URL

Google cloud platform 谷歌云CDN使用URL前缀签名URL,google-cloud-platform,google-cloud-cdn,Google Cloud Platform,Google Cloud Cdn,我无法为Google Cload CDN获取带有URL前缀的签名URL 我已经设置了一个bucket,它是我的云CDN实例的后端bucket。我已经成功地设置了URL签名密钥,并为特定路径生成了一个有效的签名URL,所有这些都使用在中找到的指令 使用下面的signCdnUrl2函数,我可以为特定资源生成一个有效的签名url,例如 我想避免“需要为每个不同的URL创建新的签名”,所以我按照的说明添加URL前缀选项 我无法成功生成带有前缀的工作签名url。我目前的尝试如下 export funct

我无法为Google Cload CDN获取带有URL前缀的签名URL

我已经设置了一个bucket,它是我的云CDN实例的后端bucket。我已经成功地设置了URL签名密钥,并为特定路径生成了一个有效的签名URL,所有这些都使用在中找到的指令

使用下面的signCdnUrl2函数,我可以为特定资源生成一个有效的签名url,例如

我想避免“需要为每个不同的URL创建新的签名”,所以我按照的说明添加URL前缀选项

我无法成功生成带有前缀的工作签名url。我目前的尝试如下

export function signCdnUrl3(fileName: string, opts: SignedUrlOptions, urlPrefix?: string) {

    const expireVal = '' + new Date().getTime() + opts.expires;

    const urlPrefixCombined = `${opts.baseUrl}${urlPrefix}`;
    // UrlPrefix param if provided otherwise empty string
    const urlPrefixEncoded = urlPrefix ? Base64urlUtil.encode(urlPrefixCombined) : '';

    // Param string to be signed with key
    const paramsToSign = `URLPrefix=${urlPrefixEncoded}&Expires=${expireVal}&KeyName=${opts.keyName}`;

    // Compute signature
    const keyBuffer = Buffer.from(opts.keyBase64, 'base64');
    let signature = createHmac('sha1', keyBuffer).update(paramsToSign).digest('base64');
    signature = Base64urlUtil.escape(signature);

    // Add signature to url
    return `${opts.baseUrl}/${fileName}?${paramsToSign}&Signature=${signature}`;
}
如果我尝试访问给定前缀下的任何资源(以bucket的根为例),我将从CloudCDN获得403响应

来自负载平衡器的日志条目显示它正在将其检测为无效签名

说明中是否有我解释错误的地方,或者我只是在实现中遗漏了什么?任何指导都将不胜感激

添加Base64Util代码以确保完整性

export class Base64urlUtil {

    public static encode(str: string, encoding: any = 'utf8'): string {
        const buffer: Buffer = Buffer.from(str, encoding);
        const encodedStr: string = buffer.toString('base64');
        const final: string = Base64urlUtil.escape(encodedStr);
        return final;
    }

    public static decode(str: string, encoding?: string): string {
        return Buffer.from(Base64urlUtil.unescape(str), 'base64').toString(encoding || 'utf8');
    }

    public static escape(str: string): string {
        return str.replace(/\+/g, '-')
            .replace(/\//g, '_')
            .replace(/=/g, '');
    }

    public static unescape(str: string): string {
        return (str + '==='.slice((str.length + 3) % 4))
            .replace(/-/g, '+')
            .replace(/_/g, '/');
    }
}
更新

使用@elithrar提供的实现,我将signedParams中的his示例值替换为我自己的live值

let signedParams = signURLPrefix(
  "https://<my-server>/sample/360p/",
  1588291200,
  "<my-key>",
  "<valid-key>"
)
让signedParams=signURLPrefix(
"https:///sample/360p/",
1588291200,
"",
""
)
结果是:

URLPrefix=AHR0CHM6LY9ZCHLUYWWUCMNMC29MDHDHCMUUAW8VC2FTCGXLLZM2HAV&Expires=1588291200&KeyName=my key name&Signature=wrbOloT+m31ZnQZei2Csqq0XaGY=

然后,当我附加这些查询参数以调用此地址处的云cdn端点时:

我在cdn日志中得到相同的403响应和匹配的无效签名


尝试使用两个不同的签名密钥,这两个密钥对没有url前缀的单个特定url进行签名效果很好。

不完全清楚问题出在哪里-我怀疑您可能对签名进行了双基64编码,但您提供的代码段中未包含
Base64urlUtil

以下是一个工作版本,该版本生成与测试相同的签名:

const crypto=require(“加密”)
导出函数signURLPrefix(
URL前缀:字符串,
过期日期:第,
关键字名称:字符串,
关键字:字符串
) {
const expireVal=expires
常量urlprefexencoded=Buffer.from(urlPrefix)
.toString(“base64”)
.替换(/_/g,“/”)
.替换(/-/g,“+”)
//要使用密钥签名的参数字符串
const paramsToSign=`URLPrefix=${urlprefexencoded}&Expires=${expireVal}&KeyName=${KeyName}`
//计算签名
const keyBytes=Buffer.from(键“base64”)
//应为键:[]字节{0x9d,0x9b,0x51,0xa2,0x17,0x4d,0x17,0xd9,
//0xb7、0x70、0xa3、0x36、0xe0、0x87、0x0a、0xe3}
let签名=加密
.createHmac(“sha1”,keyBytes)
.更新(参数符号)
.摘要(“base64”)
.替换(/_/g,“/”)
.替换(/-/g,“+”)
返回`${paramsToSign}&Signature=${Signature}`
}
设signedParams=signURLPrefix(
"https://media.example.com/segments/",
1558131350,
“我的钥匙”,
“nZtRohdNF9m3cKM24IcK4w==”
)
想不到=
“URLPrefix=aHR0cHM6Ly9tZWRpYS5leGFtcGxlLmNvbS9zZWdtZW50cy8=&Expires=1558131350&KeyName=my key&Signature=hwe5tbtzgnyvozvlg7btrnosgk=”
如果(signedParams===预期值){
控制台日志(“✔️ 签名匹配“)
}否则{
控制台错误(
`❌ 不匹配:\n\tgot${signedParams},\n\twant${expected}`
)
}
输出:

➜  ts-node signed_prefix.ts
✔️ Signature matches

我也有同样的问题。带有url前缀的已签名url和已签名cookie都不起作用。我曾尝试使用Golang/Ruby实现,我确信签名逻辑与Golang示例相同

在询问谷歌支持后,他们说:“由于这项功能最近被转移到了GA,他们发现您的项目中没有正确启用。正在实施一个修复程序来解决这个问题,我预计它将在下周完全推出。一旦应用了修复程序,我将向您进行更新。”我认为您的项目也没有正确启用它

我将在下周应用修复程序后重试并更新信息

更新


我们收到谷歌支持部门的最新回复,称我们的项目已经启用了该功能。我的代码无需任何修改即可工作。

您正在构建的URL+前缀示例是什么你的前缀以什么结尾?有一个(等待合并)Python示例和一个Go示例可能会有所帮助——这两个示例都将在本周的文档中发布。我正在尝试为使用VOD dash、hls和mp4内容的客户提供url前缀。文件夹结构是这样的,为了完整性,我还添加了Base64urlUtil,但在测试示例时没有使用它。我已经用我的进度更新了这个问题。我仍然无法让服务器接受带有URL前缀的签名。作为补充说明,签名是否应该是url安全的?我不认为你的样品会这样。谢谢你的帮助,这很有帮助。我希望在不久的将来使用签名cookie。是的-base64输出应该是URL安全的。您是通过Go示例代码实现的吗?谢谢您的示例和帮助。问题似乎是直到最近我的项目才启用这些功能。它现在工作,我的代码没有任何更改。感谢您让我知道,如果您收到任何更新,我们将不胜感激。@RobertField我的项目工作正常。向所有项目展开可能需要一些时间。您可以稍后再试。谢谢您的更新,这似乎就是问题所在。现在一切似乎都在运转。
➜  ts-node signed_prefix.ts
✔️ Signature matches