これまで、GoInstantのデータの取り扱いについて説明してきましたが、実際のアプリケーションでは
”このルームにはこのユーザしか入れない”とか
”この時間になったら、このルームへの入出を許そう”とか
”このデータを取得できるのはadminユーザだけ”とか
そういったアクセスコントロール要件が出てきます。
もちろんこういったアクセスコントロールにもGoInstantは対応しています。
ということで、今回はACLについて。
基本的にGoInstantではAccess ControlというJSONの設定とユーザのJWT(ユーザ名とかグループ名)によって
制御することができます。
例えば、RoomにJoinできるユーザを絞り込みたいときは
{
"$room": {
"#join": { "users": ["localhost:tzm%40freedom-man.com"] },
...
}
こんな感じにやると、localhostで発行されたtzm@freedom-man.comっていうユーザがJoinできる設定になります。
(@を%40にしないとエラーになったので、ちゃんとURLエンコードしないとダメみたい…。)
グループだとこんな感じ。
{
"$room": {
"#join": {"groups": ["freedom-man"]},
...
}
freedom-manっていうグループに属するユーザはJoinできるっていう設定になります。
一つ一つ特定のユーザ名やグループ名を設定するのは正直しんどいので、
ルームの名前が付いたグループとかユーザ名を一括で許可する設定ができます。
{
"$room": {
"#join": {
"groups": [
"$room-grp"
]
},
...
}
こうすると、ルームの名前 + “-grp”の名前(lobbyだったら”lobby-grp”)のグループに対して
一括でJoinの権限を付与することができます。
あるキーの読み取りを制限したい場合は以下のように書きます。
{
"$room": {
...
"test": {
"#get": {
"users": [
"localhost:tzm%40freedom-man.com"
]
},
...
}
これで、localhostから発行されたtzm@freedom-man.comユーザのみtestキーの値を取得することが出来ます。
onメソッドのイベントも制御することができます。
{
"$room": {
...
"test": {
"#onSet": {
"users": [
"localhost:tzm%40freedom-man.com"
]
},
...
}
こうすると、on(“set”, … と記述してもlocalhost:tzm@freedom-man.comユーザ以外では
コールバック関数が実行されることはありません。
これらのACLを設定して、あとはグループとユーザ名の制御をJWTで行ってあげればOKです。
python + flaskだとこんな感じ。※スクリプトタグでのJS呼び出しで対応しているのでFlaskのResponseがJSです。
## jwt_test.py ##
import base64
import json
import hmac
import hashlib
import Crypto
from Crypto.PublicKey import RSA
def base64url_decode(input):
input += '=' * (4 - (len(input) % 4))
return base64.urlsafe_b64decode(input)
def base64url_encode(input):
return base64.urlsafe_b64encode(input).replace('=', '')
def createJWT(groups, username, displayname):
key = base64url_decode("Input Your Secret Key")
header = {
'typ':'JWT',
'alg':'HS256'
}
payload = {
'iss':'localhost',
'sub': username,
'dn': displayname,
'g' : groups
}
data = base64url_encode(json.dumps(header)) + "." + base64url_encode(json.dumps(payload))
sig = base64url_encode(hmac.new(key, data, hashlib.sha256).digest())
return "var token = \"" + data+ "." + sig + "\";"
## flask_jwt.py ##
from flask import Flask
from jwt_test import createJWT
app = Flask(__name__)
@app.route("/jwt")
def jwt():
return createJWT([{'id':'lobby-grp', 'dn':'lobby'}], 'tzm@freedom-man.com', 'display')
if __name__ == "__main__":
app.run()
JWTの生成にはGoInstantと共有している秘密鍵が必要で、ユーザが自分自身で生成することは不可能です。
つまりJWT生成を行うサーバサイドで、「この時間帯でこのユーザであればRoomへのJoinは禁止しよう」等の
細かい制御をすることになります。
※expire的なパラメータが無いので、使い回しはできちゃいそうですが…。
パーミッションでエラーになったときはこんな感じのエラーが出ます。