英文:
Bunny.net CDN Token authentication not working ( for .m3u8 files)
问题
I am currently implementing a video streaming solution that utilizes the HTTP Live Streaming (HLS). As part of the token generation process, I am utilizing a secret key obtained from the "Token Authentication Key" section under the "Stream > Security > Token Authentication Key" in our CDN service management interface. Using this secret key, I am signing the HLS Playlist URLs in a Node.js environment.
However, despite following the prescribed procedures for URL signing, I am encountering an HTTP 403 Forbidden error when attempting to access the HLS playlist URLs (.m3u8).
Interestingly, when I apply the same signing process to the URLs of video thumbnail files (e.g., thumbnail.jpg), I am able to access the files without issue. This successful authentication with the thumbnail URLs validates the functionality of the token generation and authentication process to some extent.
I tried
- "Token Authentication Key" from the section "CDN > Security > Token Authentication Key"
- CDN Token Authentication (Basic) but still thumbnail works but .m3u8 not working
Following are codes that work for thumbnail.jpg but not for playlist.m3u8:
var crypto = require('crypto'),
securityKey = 'key_from_stream_security',
path = '/a1640499-52ef-4721-9ba9-4e659cada6f5/playlist.m3u8';
// Set the time of expiry to 4 days from now
var expires = 1688885053;
var hashableBase = securityKey + path + expires;
// Generate and encode the token
var md5String = crypto.createHash('md5').update(hashableBase).digest('binary');
var token = new Buffer(md5String, 'binary').toString('base64');
token = token.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
// Generate the URL
var url =
'https://vz-9ac10aa0-92d.b-cdn.net' +
path +
'?token=' +
token +
'&expires=' +
expires;
console.log(url);
and
var queryString = require('querystring');
var crypto = require('crypto');
var URL = require('url').URL; // require URL constructor
// ... (rest of the code)
If you need further assistance or have specific questions about this code, please let me know.
英文:
I am currently implementing a video streaming solution that utilizes the HTTP Live Streaming (HLS). As part of the token generation process, I am utilizing a secret key obtained from the "Token Authentication Key" section under the "Stream > Security > Token Authentication Key" in our CDN service management interface. Using this secret key, I am signing the HLS Playlist URLs in a Node.js environment.
However, despite following the prescribed procedures for URL signing, I am encountering an HTTP 403 Forbidden error when attempting to access the HLS playlist URLs (.m3u8).
Interestingly, when I apply the same signing process to the URLs of video thumbnail files (e.g., thumbnail.jpg), I am able to access the files without issue. This successful authentication with the thumbnail URLs validates the functionality of the token generation and authentication process to some extent.
I tried
- "Token Authentication Key" from the section "CDN > Security > Token Authentication Key"
- CDN Token Authentication (Basic) but still thumbnail works but .m3u8 not working
Following are codes that works for thumbnail.jpg but not for playlist.m3u8:
var crypto = require('crypto'),
securityKey = 'key_from_stream_security',
path = '/a1640499-52ef-4721-9ba9-4e659cada6f5/playlist.m3u8';
// Set the time of expiry to 4 days from now
var expires = 1688885053;
var hashableBase = securityKey + path + expires;
// Generate and encode the token
var md5String = crypto.createHash('md5').update(hashableBase).digest('binary');
var token = new Buffer(md5String, 'binary').toString('base64');
token = token.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
// Generate the URL
var url =
'https://vz-9ac10aa0-92d.b-cdn.net' +
path +
'?token=' +
token +
'&expires=' +
expires;
console.log(url);
and
var queryString = require('querystring');
var crypto = require('crypto');
var URL = require('url').URL; // require URL constructor
function addCountries(url, a, b) {
var tempUrl = url;
if (a != null) {
var tempUrlOne = new URL(tempUrl);
tempUrl += (tempUrlOne.search == '' ? '?' : '&') + 'token_countries=' + a;
}
if (b != null) {
var tempUrlTwo = new URL(tempUrl);
tempUrl +=
(tempUrlTwo.search == '' ? '?' : '&') + 'token_countries_blocked=' + b;
}
return tempUrl;
}
function signUrl(
url,
securityKey,
expirationTime = 3600,
userIp,
isDirectory = false,
pathAllowed,
countriesAllowed,
countriesBlocked,
) {
/*
url: CDN URL w/o the trailing '/' - exp. http://test.b-cdn.net/file.png
securityKey: Security token found in your pull zone
expirationTime: Authentication validity (default. 86400 sec/24 hrs)
userIp: Optional parameter if you have the User IP feature enabled
isDirectory: Optional parameter - "true" returns a URL separated by forward slashes (exp. (domain)/bcdn_token=...)
pathAllowed: Directory to authenticate (exp. /path/to/images)
countriesAllowed: List of countries allowed (exp. CA, US, TH)
countriesBlocked: List of countries blocked (exp. CA, US, TH)
*/
var parameterData = '',
parameterDataUrl = '',
signaturePath = '',
hashableBase = '',
token = '';
var expires = expirationTime;
var url = addCountries(url, countriesAllowed, countriesBlocked);
var parsedUrl = new URL(url);
var parameters = new URL(url).searchParams;
if (pathAllowed != '') {
signaturePath = pathAllowed;
parameters.set('token_path', signaturePath);
} else {
signaturePath = decodeURIComponent(parsedUrl.pathname);
}
console.log(parsedUrl.pathname);
parameters.sort();
if (Array.from(parameters).length > 0) {
parameters.forEach(function (value, key) {
if (value == '') {
return;
}
if (parameterData.length > 0) {
parameterData += '&';
}
parameterData += key + '=' + value;
parameterDataUrl += '&' + key + '=' + queryString.escape(value);
});
}
hashableBase =
securityKey +
signaturePath +
expires +
(userIp != null ? userIp : '') +
parameterData;
token = Buffer.from(
crypto.createHash('sha256').update(hashableBase).digest(),
).toString('base64');
token = token
.replace(/\n/g, '')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
if (isDirectory) {
return (
parsedUrl.protocol +
'//' +
parsedUrl.host +
'/bcdn_token=' +
token +
parameterDataUrl +
'&expires=' +
expires +
parsedUrl.pathname
);
} else {
return (
parsedUrl.protocol +
'//' +
parsedUrl.host +
parsedUrl.pathname +
'?token=' +
token +
parameterDataUrl +
'&expires=' +
expires
);
}
}
console.log(
signUrl(
'https://vz-9ac10aa0-92d.b-cdn.net/548789ea-d0d7-4dac-b656-cc2acedf0f5c/playlist.m3u8',
'key_from_stream_security',
1688885053,
'',
false,
'/548789ea-d0d7-4dac-b656-cc2acedf0f5c/playlist.m3u8',
),
);
答案1
得分: 1
问题出在pathAllowed和isDirectory上。
我需要从第二段代码中这样调用:
signUrl(
'https://vz-9ac10aa0-92d.b-cdn.net/548789ea-d0d7-4dac-b656-cc2acedf0f5c/playlist.m3u8',
'token_authentication_from_stream_security',
1688885053,
'',
true,
'/548789ea-d0d7-4dac-b656-cc2acedf0f5c/',
),
HLS网址是一个.m3u8文件,只包含块引用。当我们尝试在播放器中使用.m3u8网址来流式传输视频时,它会访问所有块。因此,除了签署.m3u8文件之外,我们还需要签署.m3u8所在的目录,以便令牌也适用于块。
英文:
The issue was in pathAllowed and isDirectory
I needed to make the call like this from second code:
signUrl(
'https://vz-9ac10aa0-92d.b-cdn.net/548789ea-d0d7-4dac-b656-cc2acedf0f5c/playlist.m3u8',
'token_authentication_from_stream_security',
1688885053,
'',
true,
'/548789ea-d0d7-4dac-b656-cc2acedf0f5c/',
),
The HLS url is a .m3u8 file that just contains the chunk reference. When we try to use .m3u8 url in player to stream video, it accesses all the chunks. So besides signing the .m3u8 file, we needed to sign the directory where .m3u8 is placed so the token also works for chunks too.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论