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
とりあえずここまで
次はダウンロードです。