[Ruby on Rails]sorceryによる認証 – (6)部署別のアクセス制限 #1 実装の概要

2015.07.06

この記事は公開されてから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アクションにはアクセスできます。

まとめ

概要についてだけとなってしまいましたが、今回のポイントは
部署を管理するのに既存テーブルを変更しないこと
です。次回以降、実装について書いていきたいと思います。