PHPのTODOアプリのアウトプット④パスワードのハッシュ化

166 回閲覧されました
みなさんこんにちは、jonioです。
今回はパスワードのハッシュ化から検索機能まで作ります。
それではアウトプットの開始です。
目次
ログインパスワードのハッシュ化
ログインする時のパスワードですがデータベースにそのまま保存されている状態です。
↓はusersテーブルです。
今の私のスキルでは他人のデータベースに接続する方法を知りませんがデータベースに接続したらパスワードが丸見えの状態になっているのはセキュリティ上良くないです。
だからパスワードを別の文字列に変換するのですがこれをハッシュ化といいます。(文字列への変換はランダムに行われるのではなく一定の規則に基づいて変換されるので同じパスワードを何度ハッシュ化しても同じ文字列になります)
ちなみに私が「taro」をハッシュ化すると「$2y$10$CED/5u4LW4B3wKS92yUE..HldJsdBk0ZJHeHQ5LRckH.S3ft27U3」になります。(ハッシュ化した値はパソコンによって異なります)
ハッシュ化後のパスワードからハッシュ化前のパスワードを辿ることもできます。
図にすると↓です。
ハッシュ化してログインする流れ
今回実装するのに新しい内容は下記になります。
- パスワードのハッシュ化:password_hash( )
- ハッシュ化される前と後の値が等しいのか確認できる:password_verify( )
これをふまえた上でハッシュ化したパスワードでログインする流れはこうなります。
- 新規登録する時にパスワードをハッシュ化する(このアプリを作った時に最初に設定した名前(田中太郎)とパスワード(taro)はハッシュ化されていません)
- フォームに入力したパスワードと「password_hash( )」でハッシュ化したパスワードが「password_verify( )」を使って一致するかを確認する
- フォームに入力したパスワードとハッシュ化したパスワードが同じならログインする
今の状態では名前とパスワードは「名前:田中太郎・パスワード:taro」しかなくてパスワードのハッシュ化ができないので名前とパスワードを登録するページ(signUp.php)も作りまずは名前とパスワードを登録するページを作ります。
名前とパスワードを追加するページ(signUp.php)の作成
新たにsignUp.phpを作ります。
signUp.phpのコードを↓にします。
cssに↓を追加してください。
これで↓と表示されます。
名前を「田中太郎2」・パスワードを「taro2」と入力して「新規登録」のボタンを押してください。
すると新規登録ができず「SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column ‘password’ at row 1」
のエラーが表示されて新規登録ができません。
「select * from password;」でパスワードカラムを見るとパスワードが追加されていないのが分かります。
このエラーの意味は「passwordカラムに登録する値は文字が長すぎます」という意味です。
ターミナルでpasswordカラムに登録できる文字数の確認を「desc users;」でします。
すると↓になりますがvarchar(8)となっているので8文字しかパスワードには8文字しか使えないとなっています。
使える文字数を長くすればいいので80文字にしますがターミナルで「ALTER TABLE users MODIFY password varchar(80);」と入力します。
そして新規登録のページ(signUp.php)で名前を「田中太郎2」・パスワードを「taro2」と入力して登録すると↓の様に登録できます。(赤枠)
データベースのusersテーブルを見ると名前とパスワードが追加されているのが分かります。(パスワードがハッシュ化されていますがハッシュ化はすぐに説明します)
13行目ですがテーブルのカラムに値を追加するのでINSERT文を使っています。
ハッシュ化は16行目で第二引数に「PASSWORD_DEFAULT」のはこんなもんと思っていいです。
password_hash( )についてはこの記事に詳しい説明があります。
残りのコードは今までと同じなので省略します。
これでハッシュ化は完成したのですがログインページ(login.php)でログインします。
ハッシュ化した状態でログインする
パスワードが「taro2」をハッシュ化すると「$2y$10$CED/5u4LW4B3wKS92yUE..HldJsdBk0ZJHeHQ5LRckH.S3ft27U3.」ですがパスワード欄にこれを入力するのは嫌ですよね。
一般的に登録した人がパスワードをハッシュ化されているなんて知らないし普通は「taro2」を使うので「taro2」でログインできるようにしないといけません。
そこで「password_verify()」を使って入力したパスワードをハッシュ化した時に正解のパスワードになるかの確認をすることでログインできる様にします。
「password_verify()」は「password_verify(ハッシュ化する前の値,ハッシュ化した後の値)」と書きますがこの記事が詳しく説明してます。
login.phpのif文を↓にします。
これでログインしてもまだ上手くいきません。
理由はlogin.phpの「try{ }」の中の「$sql = “select * from users where name = :name and password = :password”;」 ですが「password = :password」があります。
これはハッシュ化する前のパスワードを使うことになるのですがハッシュ化した後のパスワードを使いたいのでこのままではエラーになります。
それでは意味がないので「password = :password」を取ります。
これで「try{ }」は↓になります。
これだとパスワードは違うけど名前は同じ人がいる場合ログインはどうなるんだろう?と思いますがif文でパスワードの認証ができるので問題ないです。
これでパスワードのハッシュ化の完成です。
最後に簡単な検索機能の追加をします。
簡単な検索機能
簡単な検索機能というのは「同じ語句を含むレコードの内容を表示する」という意味です。
同じ語句でもひらがな・カタカナ・漢字の識別はできません。
だから「でもタイトル」なら検索に引っかかりますが「でもたいとる」では検索に引っかかりません。
普通はひらがな・カタカナも認識できるので検索の機能としては弱過ぎるので商品としては使えないです。
main.phpには投稿した内容が表示されています。
私の場合だと↓です。
「タイトル」・「本文」の内容で検索して検索した内容のレコードを表示できるようにします。
↓が例ですが「でもタイトル1」と入力しています。
実装の考え方
↓の流れで実装します。
- main.phpに検索のフォームを設置
- フォームから送られた情報を変数として受け取る
- 受け取った変数の中身をデータベースのタイトルカラム・本文カラムにあるか探しあった場合は該当するレコードの内容を表示する
- 検索の機能はSQLの「LIKE文」で行う
それでは実装しますがまずはmain.phpにフォームを設置します。
フォームの設置
main.phpのコードを↓にします。(HTMLの部分だけを載せます)
次はフォームから送られた情報を変数(main.phpのHTMLのコードの41行目のname属性の値)として受け取ります。
main.phpのコードを↓にします。(PHPの部分だけを載せます)
6行目の「search」・7行目の「search_word」が変数です。
受け取った変数をデータベースから探す
main.phpのコードを↓にします。(PHPの部分だけを載せます)
検索する時ですが何も語句を入力せずに検索できたら意味がないです。
そこで19行目のif文があります。(login.phpを初めて作った時のログインの実装方法と考え方は同じです)
22行目は本文とタイトルの内容で検索できますが本文だけで検索するなら「or title like ‘%$search_word%’」を取ってタイトルだけで検索するなら「content like ‘%$search_word%’ or」を取ればいいです。
これで実装は完成です。