inuinu blog(開発用)

BOT @wagagun の開発ノウハウや、IT向け?の雑記ブログです。

素のJavascript(Vanilla)だけでフロントエンド開発(02:Cookie編)

このページでは、ReactやVueではなく、Vanillaと呼ばれる素のJavascriptのみで、フロントエンド開発が可能であるか?を解説します。今回はCookieの設定やログイン画面について。

今回は、前回…

inuinu-tech.hatenablog.jp

の続きになります。

いきなりここにたどり着いたのでしたら、お手すきの際で構いませんので、下記の記事からも読んでみていただければ幸いです。

inuinu-tech.hatenablog.jp

今回の課題のゴールは?

JavascriptCookieを扱ってみましょう。

Cookieとは、ブラウザに保存する文字列です。
ドメイン単位に扱うことが出来ます。

JavascriptCookieのセットや取り出しができるの?

はい、Javascriptでクッキーの操作は可能です。

セット・取得プログラム例

Cookieに値をセットし、その値を連想配列として取得するプログラム例です。

Cookieの中身を取り出す簡単な関数が存在しないようですので、一連のロジックをfunction化します。

●test_cookie_set.html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<script src="js/vanilla-front-end.js"></script>
<script>
// クッキーに値をセット
document.cookie = 'test-1=abc';
document.cookie = 'test-2=' + 'テスト';
document.cookie = 'test-3=' + encodeURIComponent('テスト');

//console.log(document.cookie);

// クッキーを連想配列化
let dctCookie = getCookie();

console.log(dctCookie); // 連想配列、存在しない場合はundefined
console.log(dctCookie["test-2"]); // 値の文字列、存在しない場合はundefined
</script>
</head>
<body>
</body>
</html>

jsディレクトリを作成し、以下のJavascriptソース(vanilla-front-end.js)を作成します。

他の演習を先に行い、vanilla-front-end.jsがすでに存在する場合は、追記してください。

●vanilla-front-end.js

// クッキーを連想配列化
function getCookie() {
  let dctCke = {};
  document.cookie.split('; ').forEach(function(value) {
    //console.log(value);
    let arrContent = value.split('=');
    dctCke[arrContent[0]] = arrContent[1];
  })
  return dctCke;
} // function

http://localhost/~(ユーザー名)/test_api_select.html
で、Cookieの値がF12のconsoleに表示されていればOKです。<

Cookieは削除できる?

はい、可能です。

削除プログラム例

上記プログラムの、値のセットの箇所を以下のようにすると、Cookieは削除されます。

document.cookie = 'test-1=; max-age=0';
document.cookie = 'test-2=; max-age=0';
document.cookie = 'test-3=; max-age=0';

値がクリアされるのではなく、キーごと削除されますので、取得しようとするとundefinedになります。

CookieよりLocal Storageのほうが良い?

Coookieの他にローカルストレージというものが存在するのですが…

どうなんでしょうね…サーバーサイドではアクセスできなさそうですし、セキュリティ上危険では?という意見もありそうですし…

Vanillaでは、Cookieはログイン(セッション管理)に使用します

Cookieをログイン画面に使用する際の注意点

以下のことを守ると、そこまで気にすることはない気もします。

  • ユーザーIDではなく、ハッシュ値を置く
  • ハッシュ値はできる限り時限であること
  • パスワードは置かない
  • 他の項目は可能な限り置かない

以上でしょうか。

ハッシュ値は何に使用する?

ハッシュ値は、ユーザーテーブル内でユニークな値が設定されています。
これを各APIに忍ばせておいて、API内で以下のチェックを行います。

  1. DB内にあるユーザーテーブル内で有効なハッシュか?のチェックを行う
    • エラーの場合はログイン画面のURLを返す
  2. (可能であれば)不正な場所からのアクセスか?のチェックを行う
    • エラーの場合はログイン画面のURLを返す
    • 不正であることのログを保管し、通知を行う

こんな感じでしょうか。
不正でない場合は、API本来の処理を行い、JSONを返します。

考慮すべきはハッシュ値の無効化でしょうか。

  • ログオフの場合はハッシュ値をクリアする
  • 再度ログインした場合のハッシュ値は異なる値にする
  • 時間切れの処理を行う(いつどこで?)

といったことを考えれば良いと思います。

上記の仕様ですと、同一ブラウザの別タブで、一方がログオンしていればCookieを共用できますが、異なるブラウザ同士で同居することは不可能になります。
それを回避するのは、再度ログインした場合のハッシュ値は異なる値にしないことなのですが、果たしてそれでOKなのかは考えておく必要がありそうです。

Cookieだけだと不安な場合は?

Cookieだけだと不安な場合は、もう一つ別のハッシュ値を用意します。

これはログイン画面ではなく、ログイン以後の入力画面ですが、以下の手法を採用することで、より強靭化します

  1. 画面実行時のどこかの共通APIで(Cookieとは別の値の)第2ハッシュを取得する
  2. hidden等にセット
  3. APIを実行した際に、第2ハッシュも渡すようにする(POSTだと楽)
  4. API側は、Cookieのハッシュチェックの他に、hidden値のハッシュチェックも行う

なお、Cookieの方のハッシュ値はPOST時にどこかに忍ばせておかなくとも、APIが動作するサーバーサイドフレームワークで取得可能だと思います。

上記はCSRF対策として、よく使用される手法になります。

参考サイト:安全なウェブサイトの作り方 – 1.6 CSRF(クロスサイト・リクエスト・フォージェリ) | 情報セキュリティ | IPA 独立行政法人 情報処理推進機構
www.ipa.go.jp

これはRuby on Railsでは標準装備されていますが、多分に知らず知らずの内に、何も考えずに利用していると思います。

ログイン画面での考慮点

これで1冊の本ができるかもしれませんが(大袈裟)、かいつまんで、要点のみを解説いたします。

デザインやレイアウト等、オリジナリティがあると思いますので、画面例は提示しません。

APIでログインチェックからcookieセットまで一気に行う

まあ、当たり前ですが、APIにユーザーIDやパスワード(を変換したもの?)を送信し、ログインチェックを行いますよね。
そのAPI内で、ログインがOKならば、サーバーサイド側でcookieに値をセットします。

チェックからセットまでを一気に行うことも、CSRF(クロスサイト・リクエスト・フォージェリ)対策のひとつになると思います。

APIで、次の画面遷移先を取得する

APIで次の遷移先を取得して、リダイレクトします。
正常終了ならばメイン画面が表示されると思いますし、ではない場合は、ログイン画面が再び表示されるだけかもしれません。

まあ、ありえないと思いますが、もし心配性ドメインが異なる場合のチェックは挟んだほうが良いかもしれませんね。

最後に

今回はfunctionをHTMLの中にベタ書きしましたが、実際の開発では、外部のJSソースにまとめましょう。

次回は、GETパラメータのハウツーを解説いたします。

inuinu-tech.hatenablog.jp

それでは、また。