認証で具体的にどんなアルゴリズムでやっているかご存じですか?
私は全然知りませんでした。😐
Railsのdeviseを使ったら勝手にやってくれるから特に気にも留めていませんでした。
しかし、プライベート開発中に仕組みを勉強する機会がありましたので、
学習した内容を記事にさせて頂きます。
記事がいいなと思ったらtwitterのフォローもお待ちしております‼
https://twitter.com/takeshi_program
はじめに
本記事は以下の読者様が対象です。
- プログラミング初心者
本記事のゴール
- トークンによるセキュリティ向上 +αデータベースリソースの負荷軽減ができる理由を把握できる。
トークンとは?
トークンは暗号文字列です。
そのため、復号化の方法知らなければ、意味のない文字列です。
認証トークンの使い方について
認証トークンはログインが成功した際にサーバーから発行されクライアントに付与されます。
そして、クライアント側は付与されたトークンを毎回のリクエスト時に本体データと一緒に送付します。
サーバー側はそのトークンを見て有効期限内の有効なトークンであれば
正常なレスポンスを送り、異常であれば再度ログインを求めるためのページを返すのが一般的です。
トークンの有無による認証方法の違い
トークンを使わない場合はトークンの代わりに毎回リクエストにemailとpassword
を付与して送ります。
その都度サーバー側はDBへリクエストを行い、password
を取得し、passwordが同じものかを照合します。
照合結果がOKであれば、適切なデータをレスポンスします。
単純なため仕組みですが、このプロトコルのデメリットは
仮に第三者にemailとpassword
を盗聴された場合に、ユーザーが盗まれた事に気づきpassword
を変更する必要があります。
それまで、第三者にデータを盗まれ続けます。
トークンの場合、ユーザーが盗聴に気づかなくても一定時間が経過したらトークンが無効になるため、トークンを使った方が仮に情報を盗まれても被害を小さくできます。
(もし期限のないトークンの場合はユーザーが盗聴に気づくまで盗まれ続けます)
トークン詳細について
トークンへの期限の実装方法ですが、
そもそも暗号化というのはある文字を意味のない文字列に変換する処理です。
暗号化する前の文字の中に期限を入れていれば期限の情報を内包した文字を暗号化できます。
それを復号すれば期限情報を取得できるため、現在時刻と比較すればよいという事です。
以下がRuby
で暗号化、復号化するコードです。
require 'openssl'
require 'securerandom'
def encrypt(data, key, iv)
cipher = OpenSSL::Cipher.new('AES-256-CBC')
cipher.encrypt
cipher.key = key
cipher.iv = iv
encrypted = cipher.update(data) + cipher.final
return encrypted
end
def decrypt(encrypted_data, key, iv)
cipher = OpenSSL::Cipher.new('AES-256-CBC')
cipher.decrypt
cipher.key = key
cipher.iv = iv
decrypted = cipher.update(encrypted_data) + cipher.final
return decrypted
end
# 32バイトのランダムな鍵を生成
encryption_key = SecureRandom.bytes(32)
iv = OpenSSL::Random.random_bytes(16) # Initialization Vector (IV)
# 暗号化
data_to_encrypt = '{email: "test_user", limit: "2023/12/24"}' #トークンの生成
encrypted_data = encrypt(data_to_encrypt, encryption_key, iv)
puts encrypted_data
# 復号化
decrypted_data = decrypt(encrypted_data, encryption_key, iv) #トークンの生成
puts decrypted_data
データベースリソースの負荷軽減
トークンがあればサーバー側はトークンの有効期限をチェックするだけよく、DBからユーザー情報を取得する必要がなくなるため、データーベースへのリクエストの回数が減り、DBリソース負荷を軽減できるメリットもあります。
おわりに
今回のサンプルコードはemailとlimit
のプロパティしか渡していませんが、ここに[create, update, delete, read]
などを入れることで認証だけでなく、認可の情報もトークンに載せて送ることができます。
すごい技術ですよね~
おそらくAWSのAMIやcognito
、Ruby on Railsのdevise
もそのような仕組みなのでしょうね。
また発見があれば記事にしたいと思います。
ありがとうございました。👍