Step2.トークン認証
ここはちょっと面倒くさいです。
トークン認証するには、https://radiko.jp/v2/api/auth2 に以下のHeaderでGETします。
X-Radiko-AuthToken: Step1で取得したX-Radiko-AuthToken X-Radiko-PartialKey: 何らかのデータ X-Radiko-Device: pc X-Radiko-User: dummy_user
さて、ここで問題となるのが”X-Radiko-PartialKey”で、これがないとトークン認証できません
X-Radiko-PartialKeyを求めるには、http://radiko.jp/apps/js/radikoJSPlayer.jsとhttp://radiko.jp/apps/js/playerCommon.jsにヒントが隠されています。
playerCommon.jsをよく見てみると…送っているHeader情報が見えますね
(Step1も同じファイルに情報があります)
function (t, e, n) { "use strict"; Object.defineProperty(e, "__esModule", { value: !0 }), n(90); var r = n(243), a = function () { function t(t, e) { this._authenticated = !1, this._appId = t, this._authKey = e, this._device = r.default.getDevice() } return t.prototype.auth1 = function () { var t = new Headers({ "X-Radiko-App": this._appId, "X-Radiko-App-Version": "0.0.1", "X-Radiko-User": "dummy_user", "X-Radiko-Device": this._device }); return fetch("https://" + location.host + "/v2/api/auth1", { headers: t, method: "get", credentials: "include" }).catch(function () { console.log("auth1 error") }) }, t.prototype.auth2 = function () { var t = new Headers({ "X-Radiko-AuthToken": this._token, "X-Radiko-Partialkey": <strong>this._partialKey</strong>, "X-Radiko-User": "dummy_user", "X-Radiko-Device": this._device }); return fetch("https://" + location.host + "/v2/api/auth2", { headers: t, method: "get", credentials: "include" }).catch(function () { console.log("auth2 error") }) }, t.createPartialkey = function (t, e, n) { for (var r = new Uint8Array(t, e, n), a = "", i = 0; i < r.length; i++) a += String.fromCharCode(r[i]); return btoa(a) }, Object.defineProperty(t.prototype, "areaId", { get: function () { return this._areaId }, enumerable: !0, configurable: !0 }), Object.defineProperty(t.prototype, "areaNameKanji", { get: function () { return this._areaNameKanji }, enumerable: !0, configurable: !0 }), Object.defineProperty(t.prototype, "areaNameEn", { get: function () { return this._areaNameEn }, enumerable: !0, configurable: !0 }), Object.defineProperty(t.prototype, "authenticated", { get: function () { return this._authenticated }, enumerable: !0, configurable: !0 }), Object.defineProperty(t.prototype, "token", { get: function () { return this._token }, enumerable: !0, configurable: !0 }), t.prototype.request = function () { var e = this; return this.auth1().then(function (n) { var a = n.headers.get("x-radiko-authtoken"), i = n.headers.get("x-radiko-keyoffset"), s = n.headers.get("x-radiko-keylength"); return null == a || null == i || null == s ? void console.log("not found playlist_create_url") : (e._token = a, e._partialKey = t.createPartialkey(r.default.str2Buffer(e._authKey), +i, +s), e.auth2()) }).then(function (t) { return t.text() }).then(function (t) { t = t.trim(); var n = t.split(","), r = n[0], a = n[1], i = n[2]; return e._areaId = r, e._areaNameKanji = a, e._areaNameEn = i, e._authenticated = !0, !0 }) }, t } (); e.default = a },
必要なところだけ抜き出すと、
i = n.headers.get("x-radiko-keyoffset"); s = n.headers.get("x-radiko-keylength"); e._partialKey = t.createPartialkey(r.default.str2Buffer(e._authKey), +i, +s); t.createPartialkey = function (t, e, n) { for (var r = new Uint8Array(t, e, n), a = "", i = 0; i < r.length; i++) a += String.fromCharCode(r[i]); return btoa(a); } }
“_authKey”のi文字目からs文字を抜き出して、Base64エンコードしていることがわかります
※なんでわざわざ文字列をバイト列にして抜き出し(Uint8Array)てから、再度文字列に戻してる(String.fromCharCode)んですかね???
じゃあ、肝心の_authkeyはというと、playerCommon.jsに答えがあります
player = new RadikoJSPlayer($audio[0], 'pc_html5', 'bcd151073c03b352e1ef2fd66c32209da9ca0afa', { onPlayStateChange: onPlayStateChange, onCurrentTimeChange: onCurrentTimeChange, onFragmentPlaying: onFragmentPlaying, onLoadStateReady: onLoadStateReady, onLoadStateError: onLoadStateError, onAuthFailure: onAuthFailure, isRadikoAreafree: isRadikoAreafree, isStationInArea: isStationInArea, onHLSPlaybackComplete: onHLSPlaybackComplete });
_authkeyは’bcd151073c03b352e1ef2fd66c32209da9ca0afa’です!
Step1で取得した、X-Radiko-KeyLength: 16、X-Radiko-KeyOffset: 22から、
X-Radiko-PartialKeyは、’d66c32209da9ca0a’をBASE64エンコードした、’ZDY2YzMyMjA5ZGE5Y2EwYQ==’となりました。
curlでGETすると、
curl -c cookie.txt -H 'X-Radiko-AuthToken: Zv-wZAx3hMCFEQ7dz-okdA' -H 'X-Radiko-PartialKey: ZDY2YzMyMjA5ZGE5Y2EwYQ==' -H 'X-Radiko-User: dummy_user' -H 'X-Radiko-Device: pc' -I -L https://radiko.jp/v2/api/auth2
トークン認証成功すれば、HTTP200が帰ってきます(失敗は401)
HTTP/1.1 200 OK Server: nginx Date: Sat, 23 Jun 2018 08:31:55 GMT Content-Type: text/plain Connection: keep-alive Access-Control-Expose-Headers: X-Radiko-AuthToken, X-Radiko-Partialkey, X-Radiko-AppType, X-Radiko-AuthWait, X-Radiko-Delay, X-Radiko-KeyLength, X-Radiko-KeyOffset Access-Control-Allow-Credentials: true
とりあえずここまで
次はダウンロードです。