Userクラスについて - PastFantasy1640/WebPro2016_6 GitHub Wiki

概要

usersテーブルを直に触らずとも大丈夫なようにするクラスです。

publicメソッド

■Userコンストラクタ

新規登録や、ユーザー変更に使用したりするものです。idに、既存のものを入れたとしても、データーベースから該当するユーザーを持ってくる関数ではありません。また、こうして作られたUserインスタンスのuuidは必ず-1(User.NEW_USER_UUID)が代入されます。

引数

(final String id, final int university_id, final int sex, final String password_str, final String mail, final String twitter, final String facebook, final int icon_id)

■boolean isUniqueID()

上記コンストラクタで指定されたidがユニークなものかどうかを判定します。

戻り値

true:ユニーク

■boolean isValidPassword()

パスワードが正常かどうかを返します。

戻り値

true:正常

■boolean isValidParameter()

その他パラメータが正常かどうかを返します。また、uuidに関しては-1(User.NEW_USER_UUID)でないとfalseが返されます。あくまで、新しいユーザーとしてや、編集後の情報としてのエラーチェックです。

戻り値

true:正常

■User insertNewUser

新しいユーザーとしてデータベースへ登録します。内部的に、上記3つの関数によりエラーチェックが行われた後、新しく登録されます。また、データベース関係の例外を投げるため、サーブレットを使ってる方々はcatchしてあげてください。また、正常に登録が出来れば、自動的にログイン処理されますので、getLoginUser関数で取得できるようになります。

引数

javax.servlet.http.HttpSession session : セッション本体。nullで無いことを保証してください。

例外

SQLException, ClassNotFoundException

戻り値

nullのときは登録に失敗しています。nullで無いときは、登録後の正式なデータ(uuidが実際の数字のもの)が返ります。

■User updateUser

ユーザーをアップデートします。少し特殊な使い方をします。まず、変更を加味してUserインスタンスを生成してください。そして、そのインスタンスメソッドのupdateUserを呼び出し、引数に変更前のユーザー情報(uuidが正式なもの)を指定してください。また、passwordに""を指定するなど、isValidPasswordがfalseになるような文字列を入れた場合、パスワードは変更されません。

User current_user = User.getLoginUser(session); //[NOTICE] not null
User modifying_user = new User(current_user.id_, 13/*大学が変更になった*/, current.....);
User modified_user = modifying_user.updateUser(current_user);
//current_userは変更前
//modifying_userは変更中の一時的なインスタンス
//modified_userは変更後の正式なデータ

引数

final User old_user

戻り値

insertNewUserと同じく、変更後の正式なインスタンスを返す。

例外

SQLException, ClassNotFoundException

staticなpublicメソッド

■User authorizeUser

パスワード認証をします。認証が通った場合はログイン処理まで行うので、getLoginUser関数でユーザーを取得できます。

引数

final String id, final String password_str, javax.servlet.http.HttpSession session

戻り値

insertNewUserと同じく、正式なインスタンスを返す。 nullの場合、ログインに失敗しています。パスワードやIDが違う場合もこれです。

例外

SQLException, ClassNotFoundException

■User getUserFromID

主に他人のデータを取得するときに呼ばれる関数です。現段階はまだコアなデータはパスワード系ぐらいしかないですが、制限されたデータが返されます。現段階では、パスワードの情報は一切含まれないインスタンスを取得できます。

引数

final String id

戻り値

nullの場合は、idの指定ミスかなにかで取得に失敗しています。 そうでないばあいは、id指定されたユーザーの制限されたインスタンスが返されます。

例外

throws SQLException, ClassNotFoundException

■User getLoginUser

現在ログイン中のユーザーを返します。sessionのnullチェックは内部で行っているので、引数のsessionはnullでも構いません。

引数

javax.servlet.http.HttpSession session

戻り値

現在ログインしているユーザーの情報をセッションから取得し、Userインスタンスとして返します。 nullの場合は、sessionがそもそもnullか、誰もログインしていない状態を表します。

■void logoutCurrentUser

現在ログインしている場合は、ログアウトします。sessionはnullであっても構いません。また、誰もログインしていない状態でもこの関数を呼ぶことは可能です。何も動作をしません。

引数

javax.servlet.http.HttpSession session

データベースに関して

テーブル作成のクエリ

create table users (uuid int unique primary key auto_increment, id varchar(16) unique not null,university_id int not null,sex int not null,password varchar(64) not null, salt varchar(32) not null,stretch_count int not null, mail varchar(385), twitter varchar(16), facebook varchar(64), icon_id int);

テストデータについて

できれば新規登録をやってほしいけど、上手く動かないっていうときは、テスト段階ではDBへ直にinsertクエリを叩いてもいいですが…パスワードが少し複雑になっています。

パスワード[Asdf123]のデータです

password=9ce95f446f7d074e2d9d491df14f03a2d24feb8adf8c7828a0e1b5ed178516ae
salt=1484535834212
stretch_count=1000

これで認証がとおる、はず、です。

【裏話】パスワードの仕組みについて

ユーザーテーブルに関して、パスワードは平文で保存していません。DBへパスワード保存するときの方法として、ぱっと見でパスワードがわからない、DB管理者であってもわからないような仕組みにすべきです。また、もしデータが漏洩した場合でも、できるだけクラックされるまでの時間をかせぐべきです。というわけで、今回のパスワード生成アルゴリズムは「平文のパスワードにsalt(塩)とpepper(胡椒)を追加して、stretch_count回数分SHA-256アルゴリズムにてハッシュを行っています。

そうすることで、

  • パスワードが漏洩してもsaltが無事なら復元できない
  • データベースが漏洩してもpepperはソースコードに直書きしてあるため、ソースコードが無事なら復元できない
  • もしも全部漏洩してしまっても、stretch_count回遡るため時間を稼げる

という算段です。1つの文字列に対する施行時間が1000倍になるため、全体のブルートフォースにかかる時間も1000倍になります。(実際1000も数が少ない)

パスワード認証は同じアルゴリズムと同じsalt、pepper、stretch_countを使用することで、同じように暗号化が可能で、最終的なハッシュが一致したかどうかで認証できます。