Django 1.10 で Channels を試し、いくつかのコンシューマーをセットアップしています。
ゲストがこのプライベートソケットに入るのを防ぐために、接続を実行する前に接続を閉じる login_required デコレーターを作成してみました。また、後でユニットテストを統合してテストしましたが、ゲストを入れ続けているため失敗し続けています(どこでもAnonymousUserエラー)。
また、ログインおよびログアウト時にセッションがクリアされず、古いユーザーがログインできる場合があります。
デコレータ:
def login_required_websocket(func):
"""
If user is not logged in, close connection immediately.
"""
@functools.wraps(func)
def inner(message, *args, **kwargs):
if not message.user.is_authenticated():
message.reply_channel.send({'close': True})
return func(message, *args, **kwargs)
return inner
消費者コードは次のとおりです。
def ws_connect(message, slug):
message.reply_channel.send({ 'accept': True })
client = message.reply_channel
client.send(signal.message("Welcome"))
try:
# import pdb; pdb.set_trace()
Room.objects.get(name=slug)
except Room.DoesNotExist:
room = Room.objects.create(name=slug)
room.users.add(message.user)
room.turn = message.user.id
room.save()
story = Story(room=room)
story.save()
# We made sure it exists.
room = Room.objects.get(name=slug)
message.channel_session['room'] = room.name
# Check if user is allowed here.
if not room.user_allowed(message.user):
# Close the connection. User is not allowed.
client.send(Signal.error("User isn't allowed in this room."))
client.send({'close': True})
奇妙なことに、 client.send(signal.message)) 転送間のすべてのロジックをコメントアウトすると、正常に機能し、単体テストに合格します (ゲストがブロックされ、認証コードが実行されないことを意味します [したがって AnonymousUser エラー])。何か案は?
ここにもテストがあります:
class RoomsTests(ChannelTestCase):
def test_reject_guest(self):
"""
This tests whether the login_required_websocket decorator is rejecting guests.
"""
client = HttpClient()
user = User.objects.create_user(
username='test', password='password')
client.send_and_consume('websocket.connect',
path='/rooms/test_room', check_accept=False)
self.assertEqual(client.receive(), {'close': True})
def test_accept_logged_in(self):
"""
This tests whether the connection is accepted when a user is logged in.
"""
client = HttpClient()
user = User.objects.create_user(
username='test', password='password')
client.login(username='test', password='password')
client.send_and_consume('websocket.connect', path='/rooms/test_room')
私はこれに間違って近づいていますか?もしそうなら、どうすればこれを適切に行うことができますか(認証が必要ですか?)
編集: 何かを試すためにアクション システムを統合しました。Django チャネルが HTTP からセッションをまったく取得していないようです。
@enforce_ordering
@channel_session_user_from_http
def ws_connect(message, slug):
message.reply_channel.send({'accept': True})
message.reply_channel.send(Action.info(message.user.is_authenticated()).to_send())
false を返すだけです。
EDIT2: 動作するようになりました。localhost を 127.0.0.1 に変更してみましたが、動作することがわかりました。localhost を有効なドメインとして検出して、セッションを移植する方法はありますか?
EDIT3: localhost と 127.0.0.1 の Cookie の問題が見つかりました。報奨金を無駄にしないために、メッセージ/チャネルに auth login_required を個人的にどのように実装しますか?
edit4:なぜうまくいかなかったのかはまだわかりませんが、最終的に問題を回避してアプリを変更した方法は次のとおりです。
アクションシステムを作成しました。入力すると、JSON を介して AUTHENTICATE アクションを送信するまで、ソケットは何もしません。ログインしたアクションをguest_actionsとuser_actionsに分けました。認証されると、セッションが設定され、user_actions を使用できるようになります。