我正在尝试 Django 1.10 中的 Channels 并设置了一些消费者。
我尝试为它创建一个 login_required 装饰器,在执行它之前关闭连接,以防止客人进入这个私有套接字。之后还集成了单元测试来对其进行测试,但它们一直失败,因为它一直让客人进来(到处都是匿名用户错误)。
此外,有时登录和注销会话时不会清除,它会让旧用户进入。
装饰师:
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())
只是返回假。
EDIT2:我看到它现在可以工作了,我尝试将 localhost 更改为 127.0.0.1 并证明它现在可以工作。有没有办法让它将 localhost 检测为有效域,以便通过会话进行端口?
EDIT3:原来我发现了 localhost vs 127.0.0.1 cookie 问题哈哈。为了不浪费赏金,您将如何亲自在消息/频道中实现 auth login_required?
edit4:虽然我仍然不知道为什么这件事不起作用,但这是我最终围绕这个问题改变我的应用程序的方式:
我创建了一个动作系统。进入时,套接字不会执行任何操作,直到您通过 JSON 向其发送 AUTHENTICATE 操作。我在 guest_actions 和 user_actions 中分离了登录操作。一旦通过身份验证,它就会设置会话并且您可以使用 user_actions。