[JAVA] Play restricted access video (HLS format) under CloudFront with Video.js using signed cookies

The title is still long (when I searched on Google, it was cut off in the middle of the title ... I thought it was the end that someone registered), but ** Set a signed cookie with custom policy (for CloudFront) using AWS SDK for Java ** HLS format video (.m3u8 file + .ts file divided into multiple files) is placed in the environment set in step 1 and read from an external application.

For HLS format video playback with Video.js, the following article (although the version of Video.js is a little old) will be helpful. ** Streaming HLS format video using Video.js (akiyoko blog) **

** 6/5 postscript: I missed the procedure for changing the Behavior settings of CloudFront, so I fixed it. ** **

0. Premise

First, ** Set a signed cookie with a custom policy (for CloudFront) using the AWS SDK for Java ** As you can see, CloudFront and S3 are set up. In addition, the test application shall be implemented in the local development environment using Spring Boot (hosts file change required).

The domain to publish the application and content should match the article in ↑. ** Application: https://hmatsu47.site/** → ** When you access "https://hmatsu47.site/set-cookie" , it will change to ** "https://hmatsu47.site/index.html" ** and the video player will be displayed. ** Video content: https://www.hmatsu47.site/ → S3 bucket ** "testmatsu signed cookie" ** Directly under ** "sample.m3u8" ** file and the split video file (** XXXXX.ts **) described in the same file are saved.

In each case, please read / rewrite according to your own environment.

1. Change the Behavior settings of CloudFront

In CloudFront, change the Behavior settings of the target distribution and save the HTTP request forwarded to the S3 bucket so that ** "Origin" ** in the request header is not excluded. cf_whitelist.jpg

2. Change the S3 bucket settings (CORS)

With S3 bucket permissions, use the CORS Configuration Editor to change the settings to allow cross-origin Script access.

CORS settings


<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>http://hmatsu47.site</AllowedOrigin>
    <AllowedOrigin>https://hmatsu47.site</AllowedOrigin>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3600</MaxAgeSeconds>
    <ExposeHeader>ETag</ExposeHeader>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

3. Change the application

In the previous article ** "[2. Implement code to set signed cookie in application](http://qiita.com/hmatsu47/items/8edd5cfde92bfd0d5a6c#2-%E3%82%A2%E3%83] % 97% E3% 83% AA% E3% 82% B1% E3% 83% BC% E3% 82% B7% E3% 83% A7% E3% 83% B3% E3% 81% AB% E7% BD% B2 % E5% 90% 8D% E4% BB% 98% E3% 81% 8Dcookie% E3% 82% 92% E3% 82% BB% E3% 83% 83% E3% 83% 88% E3% 81% 99% E3 % 82% 8B% E3% 82% B3% E3% 83% BC% E3% 83% 89% E3% 82% 92% E5% AE% 9F% E8% A3% 85% E3% 81% 99% E3% 82 % 8B) "" SetCookieController.java " Change the ** after the comment line ("* // Transition by redirect *") ** at the end to add the P3P compact policy to the response header. With (for IE11), rewrite to the form that transitions to index.html on the local side.

SetCookieController.java (changed part = end only)


		res.setHeader("P3P", "CP=\"[P3P Compact Policy]\"");
		//Transition by redirect
		res.sendRedirect("index.html");
	}
}

P3P compact policy is specified so that IE11 can send cookies from Script to another origin (site with different FQDN or different protocol / port number). Even if the content is not correct, it seems to work if an arbitrary character string is set. In addition, since it is not already functioning in browsers other than IE, it is possible to send a cookie (by Script) to another origin even if it is not specified.

4. Place the files required for video playback

Prepare Video.js, necessary .js files, etc. and index.html to call them.

Below, in the Spring Boot environment, create and place a ** "static" ** folder under ** "src / main / resources" **. Please prepare the files related to Video.js by downloading them.

index.html


<html>
  <head>
    <title>HLS test</title>
    <link href="/video-js.5.19.2/video-js.min.css" rel="stylesheet">
    <script src="/video-js.5.19.2/video.min.js"></script>
    <script src="/video-js.5.19.2/videojs-contrib-media-sources.min.js"></script>
    <script src="/video-js.5.19.2/videojs-contrib-hls.min.js"></script>
    <script>
      videojs.options.flash.swf = "/video-js.5.19.2/video-js.swf"
    </script>
  </head>
  <body>
    <video id="test" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" width="[Video player width]" height="[Same height]">
    </video>
    <script>
      var player = videojs('test', {techOrder: ['flash', 'html5']});

      player.src({
        src: 'https://www.hmatsu47.site/sample.m3u8',
        type: 'application/x-mpegURL',
        withCredentials: true
      });
    </script>    
  </body>
</html>

I set ** "with Credentials" ** to ** "true" ** to send signed cookies from Script to CloudFront.

In IE11, there is a problem in playing HLS format video by Video.js + HTML5, so it will be played using Flash. By the way, I have specified to read the local "video-js.swf", but only IE11 ignores this specification and it will be downloaded from the CDN ... As a result, it is said that this specification is provided only to prevent the external files from being read by browsers other than IE.

5. Upload the video file to your S3 bucket

Upload the "sample.m3u8" file and the split video file to the S3 bucket as well.

6. Test video playback

With the above work, you will have an environment where you can play videos protected by signed cookies.

In your local browser, open ** "https://hmatsu47.site/set-cookie" ** to display the video playback screen, and click the play button to start playing the video.

In the case of playback using Flash in IE11, the loading timing of the split video is slower than in HTML5, so the video may be jerky depending on the playback device and line speed. Please be careful.

7. Supplement / Cookies and CORS

It's complicated, but the scope of cookies and the "access control between origins" by CORS are different.

** ■ Cookie scope: Specified by Domain attribute, Secure attribute, Path attribute, HttpOnly attribute **

** ■ CORS: Controls access across origins (combination of FQDN and protocol port number) **

In other words

about it.

In this sample, the "HttpOnly" attribute is added when generating a signed cookie with Java code. This is because you don't need to refer to this cookie in the source JavaScript. As a result, it works fine even with the "HttpOnly" attribute.

Recommended Posts

Play restricted access video (HLS format) under CloudFront with Video.js using signed cookies
[Rails] Access signed / encrypted cookies with request spec