[Ruby on Rails]sorceryによる認証 – (6)部署別のアクセス制限 #1 実装の概要
はじめに
sorceryを利用した認証機能に、ユーザの所属部署別にアクセス制限を行う機能を追加してみました。以前のAPIでの認証に機能を追加する形となりますので、全てを知りたい場合は一読をお勧めします。
今回の設計思想
以下の様な設計思想で実装しました。
- 部署は管理部(Administrator)、購買部(Purchase)を用意し、独立したマスタテーブル(departments)に保持する。
- ユーザの所属部署は新規のテーブル(user_departments)で管理し、既存のテーブルは変更しない。
- ログインしていないユーザも含む全ユーザが参照できるアクション、管理部のユーザのみが参照できるアクション、管理部・購買部のユーザが参照できるアクションを用意する。
テーブル設計
上記にも書きましたが、ユーザの所属部署を管理するため以下のテーブルを新たに追加しました。
- departmentsテーブル・・・部署を管理するマスタテーブル
- user_departmentsテーブル・・・ユーザの所属部署を管理するテーブル
項目は以下の通りです。
departmentsテーブル
項目名 | 型 | 概要 |
---|---|---|
id | integer | 部署のID |
name | varchar | 部署名 |
created_at | datetime | 作成日時 |
updated_at | datetime | 更新日時 |
user_departmentsテーブル
項目名 | 型 | 概要 |
---|---|---|
id | integer | 部署のID |
user_id | integer | ユーザのID |
department_id | integer | ユーザの所属する部署ID |
created_at | datetime | 作成日時 |
updated_at | datetime | 更新日時 |
コントローラのアクションとURL
部署別にアクセス制限をするアクションとして、Sampleコントローラ内に以下を実装しました。
アクション名 | 動詞(GET,PUT,POST,DELETE) | url | 概要 |
---|---|---|---|
public | GET | api/v1/sample/public.json | ログインの有無に関わらず、値を返却するアクション |
admin | GET | api/v1/sample/admin.json | 管理部のユーザのみ、値を返却するアクション |
restrict | GET | api/v1/sample/restrict.json | ログインしている場合のみ、値を返却するアクション |
これ以外のコントローラ、アクションについては以前の記事を参照してください。
アクセス制限のフロー
今回作成する機能のイメージを掴みやすくするため、ログイン〜アクセス制限の確認の順にAPIを呼び出した結果を貼付けておきます。
0.部署のマスターデータ
departmentsテーブルに予め部署のデータを作成しておきます。
id | name |
---|---|
10 | Administration |
20 | Purchase |
1.ユーザの作成
管理部と購買部のユーザを作成します。
$ curl -i -X POST http://localhost:3000/api/v1/users.json \ -d 'user[email]=sample@ggg.com' \ -d 'user[name]=sample' \ -d 'user[password]=password' \ -d 'user[password_confirmation]=password' \ -d 'department[department_id]=10' (中略) HTTP/1.1 201 Created (中略) $ curl -i -X POST http://localhost:3000/api/v1/users.json \ -d 'user[email]=purchase@ggg.com' \ -d 'user[name]=purchase' \ -d 'user[password]=password' \ -d 'user[password_confirmation]=password' \ -d 'department[department_id]=20' (中略) HTTP/1.1 201 Created (中略)
作成されるデータは以下の通りです。
sqlite> select * from users; id|email|name|crypted_password|salt|created_at|updated_at 53|sample@ggg.com|sample|$2a$10$5n3I64lD6tEPTvv/RVlZHesRvGH/ivukASs/RyeQYFMOO5KMwSXwC|YjSavmrpKymqV4vQDGqd|2015-07-05 04:18:25.683640|2015-07-05 04:18:25.683640 54|purchase@ggg.com|purchase|$2a$10$7TENNv4iH/ju0/3VxZdAB.Ccp6XAzbVA9F9AtwiSk5RmYIU9I6lAm|9NUJCCm6yA7tuxcfE5Z1|2015-07-05 04:25:38.262565|2015-07-05 04:25:38.262565 sqlite> select * from user_departments; id|user_id|department_id|created_at|updated_at 1|53|10|2015-07-05 04:18:25.709755|2015-07-05 04:18:25.709755 2|54|20|2015-07-05 04:25:38.266063|2015-07-05 04:25:38.266063
usersテーブルにユーザの情報が、users_departmentsテーブルにユーザの所属部署の情報が作成されます。
2.ログイン
上記で作成したユーザでログインします。ユーザ毎のAccessTokenが返却されるので、ログイン済みユーザとしてアクセスしたい場合は、このAccessTokenを使用します。
curl -i -X POST http://localhost:3000/api/v1/user_sessions.json \ -d 'user[email]=sample@ggg.com' \ -d 'user[password]=password' (中略) HTTP/1.1 200 OK (中略) {"user":{"id":53,"email":"sample@ggg.com","name":"sample"},"access_token":"aee2ac718d67a5e97e1a12e6434d56e7"} $ curl -i -X POST http://localhost:3000/api/v1/user_sessions.json \ -d 'user[email]=purchase@ggg.com' \ -d 'user[password]=password' (中略) HTTP/1.1 200 OK (中略) {"user":{"id":54,"email":"purchase@ggg.com","name":"purchase"},"access_token":"af5b4a9de777a97f163adc29ddbda492"}
3.部署別のアクセス
ログインしていないユーザ、上記で作成したユーザで、Sampleコントローラの各アクションにアクセスしてみます。
3-1.ログインしていないユーザ
$ curl -i -X GET http://localhost:3000/api/v1/sample/public.json HTTP/1.1 200 OK (中略) $ curl -i -X GET http://localhost:3000/api/v1/sample/admin.json HTTP/1.1 401 Unauthorized (中略) $ curl -i -X GET http://localhost:3000/api/v1/sample/restrict.json HTTP/1.1 401 Unauthorized (中略)
publicアクション以外は、アクセスを拒否されています。
3-2.管理部のユーザ
$ curl -i -X GET -H 'ACCESS_TOKEN: aee2ac718d67a5e97e1a12e6434d56e7' http://localhost:3000/api/v1/sample/public.json HTTP/1.1 200 OK (中略) {"message":"public"} $ curl -i -X GET -H 'ACCESS_TOKEN: aee2ac718d67a5e97e1a12e6434d56e7' http://localhost:3000/api/v1/sample/admin.json HTTP/1.1 200 OK (中略) {"message":"admin"} $ curl -i -X GET -H 'ACCESS_TOKEN: aee2ac718d67a5e97e1a12e6434d56e7' http://localhost:3000/api/v1/sample/restrict.json HTTP/1.1 200 OK (中略) {"message":"authorized"}
全てのアクションにアクセスできています。
3-3.購買部のユーザ
$ curl -i -X GET -H 'ACCESS_TOKEN: af5b4a9de777a97f163adc29ddbda492' http://localhost:3000/api/v1/sample/public.json HTTP/1.1 200 OK (中略) {"message":"public"} $ curl -i -X GET -H 'ACCESS_TOKEN: af5b4a9de777a97f163adc29ddbda492' http://localhost:3000/api/v1/sample/admin.json HTTP/1.1 401 Unauthorized $ curl -i -X GET -H 'ACCESS_TOKEN: af5b4a9de777a97f163adc29ddbda492' http://localhost:3000/api/v1/sample/restrict.json HTTP/1.1 200 OK {"message":"authorized"}
adminアクションにはアクセスできず、restritアクションにはアクセスできます。
まとめ
概要についてだけとなってしまいましたが、今回のポイントは
部署を管理するのに既存テーブルを変更しないこと
です。次回以降、実装について書いていきたいと思います。