まさ@ブログ書き込み中

読者です 読者をやめる 読者になる 読者になる

まさ@ブログ書き込み中

まさの旅、英語、プログラミング、プライベートについて、色々記録しています。

SinatraとActiveRecordとセッションを使ってログイン機能を実装して昇天したお話

 

 

 

こんばんは、セキュリティ・まさです。

 

昨日の記事を見てくださった方は僕が順調にLINEづくりを進めていると思ったことでしょう。

 

masa-world.hateblo.jp

 

僕だってそう思っていました。

 

13時から19時までの6時間もの間考えてもググってもなにしても進捗ゼロになるまでは。

 

そうやってRESTfulならぬSTRESSful(うまい!)になったまま昨日は就寝しました。

 

昨日:セキュアなログイン認証かつステートフルにする方法がわからん

ログイン機能を作らないといけない・・・。

昨日のまさはパニクっていました。パニクった(ハマった)流れはこんな感じ。

 

  1.  ActiveRecordを初めて利用するから頭が混乱して簡単なIDとPWをチェックするコードも思い浮かばないうわあああ
  2. というかステートフルにしないといけないから単純なif文による認証してもダメだとわかっているうわあああああ
  3. Sinatra ログイン認証」とかでググるとwardenが引っかかってやってみたけどやっぱりわからずドツボにハマるうわあああああ

 

 

1に関しては今日落ち着いて考えてみたらすぐ書けました(昨日はそれくらい変な所でハマってた)が、2と3についてはもうお手上げ状態。こうやって僕の6時間は過ぎていったのでした。

 

 

 今日:我らがコーチさぼさんに聞いてみたら30分程度で解決策の提示・コードによる実演・仕組みの説明・質疑応答が全て終わった。昇天した。

見出し通りです。

もう昨日の6時間と就寝までのブルーな時間を返して欲しいです。本当に。

 

とにかく、どうやって解決したかを説明します。

 

そもそもwardenとかいらない、セッションでおk

僕みたいに初心者丸出しで「Sinatra ログイン認証」とかで検索してしまうといろんなエンジニアの人たちがやれ「wareden」だの「OAuth」だの記事を書いているからそこを参照してwardenを使おうと頑張っていたのですが、そもそも僕の目的はセキュリティがガバガバじゃないログイン機能を作るということでした。 

 

それならまずはSinatraのセッション機能を使えばいい、というさぼさんからのアドバイスを受けました。

 

そもそもセッションとは

masa-world.hateblo.jp

 

ここにもありますが、一言でいうとCookieをただ利用するよりセキュアにユーザーの情報をサーバに保持させ、ステートフルにする方法です。

 

使い方

Sinatraはセッションを使うよ」っていう宣言的なやつは

enable :sessions

でOK。セッションIDを発行したい場合は、ログイン成功時にユーザーのIDなどの情報を session[:foo] に入れるだけ。 ほんとそれだけ。便利。

user = User.find_by(id: params[:id])

session[:user_id] = user.id

 

具体的にどう役に立つの

上に述べましたが、セッション機能によってサーバ(アプリ)サイドが「このリクエストはログイン済みの◯◯さんで、個人情報は△△で・・・」ということがわかります。

 

上の「Web技術入門」の記事でもそう書きましたが、それは具体的にどうなっているのか、ここで記録したいと思います。

このコードの中の session[:user_id] = user.id のように、セッション変数(?)にデータを格納すると、その変数はサーバ側が一定期間の間保持しておくのでset_current_user メソッドがいつどこで呼ばれても利用できます。

 

データベース内もセキュアに

最後に、ActiveRecordのhas_secure_passwordというAPIを使ったという記録も書いて起きます。まず最初に思い出していただきたいのは、以前の投稿で見せたSequel proのスクショ。

 

f:id:masaincebu:20170515124950p:plain

 

さぼさんが言うには、ここのパスワードの所が僕らに見えてしまっている時点でセキュアじゃない。

 

確かに、誰かがデータを盗み取ったときにパスワードも綺麗に表示されていたら危ない・・・。

 

そこで使ったのが has_secure_password というActiveRecordAPI。これを使うなら以下の二点に気をつけなければなりません。

  • DBのパスワードに対応するカラム(フィールド)はpassword_digest にする
  • インスタンスをつくる(データを入れる)際にpassword属性を操作する際には password と表記する
  • passwordを引数として認証を行う際には authenticate というメソッドを使う(具体的にはauthenticateメソッドはpasswordをハッシュ化してDB内のpassword_digestと比較する)

 

最後にその例とうまくいったらどうなるかを貼り付けておきます。

このように、パスワードの部分がしっかりハッシュ化されてますね。

f:id:masaincebu:20170517100403p:plain

 

 

まとめと感想

今回の一件で本で読んで学んだセッションに関する理論(ロジック)が実践を通してさらに深く理解できました。実際に見えるって最高。

 

まとめとしては

  • セッションはRESTなHTTPをステートフルにするために役に立つ
  • 同時にCookie内にidやpasswordが露わになることを防ぐ
  • has_secure_password を利用するとDB内でもパスワードがハッシュに変換される
  • 1時間くらいかけてわからないのならさぼさんに聞いてみる方がいい

 

ということでした!

 

 

(1時間くらい)