-
-
Save saturngod/01ca507ee0134c38f85874cc4061b320 to your computer and use it in GitHub Desktop.
BunnyCDN VOD HLS Token Authentication V2 with directory tokens
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
VOD HLS streaming for BunnyCDN | |
Token authentication V2 | |
> Tested with VideoJS 7.5.5, silvermine/videojs-chromecast 1.2.1, silvermine/videojs-quality-selector 1.2.3 | |
> Thanks to Dejan from BunnyCDN Support for the token authentication V2 PHP snippet | |
*/ | |
function sign_bcdn_url($url, $securityKey, $expiration_time = 3600, $user_ip = NULL, $path_allowed = NULL, $countries_allowed = NULL, $countries_blocked = NULL) | |
{ | |
if(!is_null($countries_allowed)) | |
{ | |
$url .= (parse_url($url, PHP_URL_QUERY) == "") ? "?" : "&"; | |
$url .= "token_countries={$countries_allowed}"; | |
} | |
if(!is_null($countries_blocked)) | |
{ | |
$url .= (parse_url($url, PHP_URL_QUERY) == "") ? "?" : "&"; | |
$url .= "token_countries_blocked={$countries_blocked}"; | |
} | |
$url_scheme = parse_url($url, PHP_URL_SCHEME); | |
$url_host = parse_url($url, PHP_URL_HOST); | |
$url_path = parse_url($url, PHP_URL_PATH); | |
$url_query = parse_url($url, PHP_URL_QUERY); | |
$parameters = array(); | |
parse_str($url_query, $parameters); | |
// Check if the path is specified and ovewrite the default | |
$signature_path = $url_path; | |
if(!is_null($path_allowed)) | |
{ | |
$signature_path = $path_allowed; | |
$parameters["token_path"] = $signature_path; | |
} | |
// Expiration time | |
$expires = time() + $expiration_time; | |
// Construct the parameter data | |
ksort($parameters); // Sort alphabetically, very important | |
$parameter_data = ""; | |
$parameter_data_url = ""; | |
if(sizeof($parameters) > 0) | |
{ | |
foreach ($parameters as $key => $value) | |
{ | |
if(strlen($parameter_data) > 0) | |
$parameter_data .= "&"; | |
$parameter_data_url .= "&"; | |
$parameter_data .= "{$key}=" . $value; | |
$parameter_data_url .= "{$key}=" . $value; | |
} | |
} | |
// Generate the toke | |
$hashableBase = $securityKey.$signature_path.$expires.$parameter_data; | |
// If using IP validation | |
if(!is_null($user_ip)) | |
{ | |
$hashableBase .= $user_ip; | |
} | |
// Generate the token | |
$token = hash('sha256', $hashableBase, true); | |
$token = base64_encode($token); | |
$token = strtr($token, '+/', '-_'); | |
$token = str_replace('=', '', $token); | |
//$url_path = str_replace("%2F", "/", urlencode($url_path)); // URL encode everything but slashes for the URL data | |
$query_string = "?token={$token}{$parameter_data_url}&expires={$expires}&token_ver=2"; | |
return [$query_string, "{$url_scheme}://{$url_host}{$url_path}{$query_string}"]; | |
} | |
list($query_string, $secure_url) = sign_bcdn_url("https://mydomain.b-cdn.net/test/bigbuck.m3u8", "a1b2c3d4-e5f6-g7h8-i9j1-k2l3m4n5o6p7", 3600, NULL, "/test/"); | |
?> | |
<html> | |
<head> | |
<link href="./videojs-7.5.5.css" rel="stylesheet" type="text/css"> | |
<link href="./videojs-quality-selector.css" rel="stylesheet" type="text/css"> | |
<link href="./videojs-chromecast.css" rel="stylesheet" type="text/css"> | |
</head> | |
<body> | |
<video | |
id="MyPlayer" | |
class="video-js vjs-16-9 vjs-big-play-centered" | |
controls | |
preload="auto" | |
poster="" | |
data-title="" | |
data-poster="" | |
> | |
<source src="<?php echo $secure_url; ?>" type="application/x-mpegURL" label="" /> | |
<p class="vjs-no-js"> | |
To view this video please enable JavaScript, and consider upgrading to a | |
web browser that | |
<a href="https://videojs.com/html5-video-support/" target="_blank" | |
>supports HTML5 video</a | |
> | |
</p> | |
</video> | |
</body> | |
<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script> | |
<script src="./videojs-7.5.5.js"></script> | |
<script src="./videojs-quality-selector.min.js"></script> | |
<script src="./videojs-chromecast.min.js"></script> | |
<script> | |
// current source | |
csource = $('#MyPlayer source').attr('src') | |
titles = { | |
csource: $('#MyPlayer').attr('data-title') | |
} | |
// options for chromecast | |
options = { | |
controls: true, | |
techOrder: [ 'chromecast', 'html5' ], | |
chromecast: { | |
requestTitleFn: function(source) { | |
return titles[source.url]; | |
} | |
}, | |
plugins: { | |
chromecast: {} | |
} | |
}; | |
// append the token query string to the TS segments | |
videojs.Hls.xhr.beforeRequest = function(options) { | |
if(options.uri.includes('.ts')) options.uri += '<?php echo $query_string; ?>'; | |
return options; | |
}; | |
var vjplayer = videojs("MyPlayer", options); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hmm I saw your comment and decided to check this out.
Directory tokens should be available for version 2, so why don't I see aThis new script works with directory tokens indeed. The only issue with IP validation is that users with IPv6 will not work, as BunnyCDN only supports IPv4 for IP validation. So you should use a service like this for that.&token_ver=2
in the query parameters? I'm just wondering if this will actually work without that 🤔