注意点
下記でサブスク型サービスを一例にあげておりますが、基本的にJavaScriptは改ざん可能です。
本来であれば契約期間等の厳密な時間を比較する場合は、サーバーサイドで時間比較を行わなければいけません。
そのため、下記方法で解決で完全解決はできないです…
ご注意ください。
はじめに
new Date()で取得した時刻と現在時刻を単純比較する時は注意が必要です。
例えば下記のようなソースコードです。
※固定時刻を生成するためにnew Date(2022, 0, 1, 0, 0, 0)
を使用していますが、ここはDBから取得した時刻でもなんでもよいです。
const date1 = new Date(); // 現在時刻
const date2 = new Date(2022, 0, 1, 0, 0, 0); // 2022/1/1 00:00:00
console.log(date1 > date2? true : false);
このソースコード間違いではないんです。
ただサブスク型サービス等で単純比較すると痛い目に合います。
※私が痛い目に合いました(笑)
理由はnew Date()はクライアントの時刻を取得しているからです。
例えば、サブスク型サービスで契約期間があったとします。
その契約期間とnew Date()で取得した時刻を比較します。
通常であれば問題はありません。※PCは自動で現在時刻を補正しているためです。
ただし、PCの時刻を強制的に変更して期間終了日前の時刻に設定することで永久にサービスを使用することができます。
じゃあどうしたらよいか🤔
結論
サーバー時刻を取得することで一部解決することができます。
ajaxでサーバー側と通信を行い、レスポンスヘッダに含まれる時刻を取得します。
※完全解決するためにはサーバーサイドで時間比較を行う必要があります。
try {
let serverTime: Date = null;
const request: XMLHttpRequest = new XMLHttpRequest;
const date = await new Promise((resolve, reject) => {
request.open('HEAD', window.location.href, true); // ヘッダ情報だけ取得するのでHEAD指定。
request.send(null); // 送信データないためnull指定。
request.onreadystatechange = () => {
if(request.readyState === 4 && request.status !== 0) {
serverTime = new Date(request.getResponseHeader('Date'));
return resolve(serverTime);
} else if(request.readyState === 4 && request.status === 0) {
return reject("通信に失敗しました");
}
}
});
console.log(date);
} catch(error) {
console.log(error); // 通信に失敗しました
}