zoukankan      html  css  js  c++  java
  • Channels实现扫码登录

    参考了下别人说的原理,根据自己的逻辑实现,没有完全按照别人的原理来,所以不一定适用于大家,仅供参考吧!!!

    流程如下:

      1. web发起websocket链接,后端接受链接后立马发送第一次消息,消息为全局唯一标识key
      2. web收到第一次的消息,将key生成二维码展现出来
      3. App进行扫码获取key,并当做参数调用后端接口,成功则App提示用户

      3. 后端收到App的请求,成功处理(APP扫码成功)则向web发送第二次消息,为身份标识token,并关闭连接

      4. web收到token,存到本地,再做登录成功的逻辑,就o了

    Django实现websocket的包目前只了解到channels跟dwebsocket,channels维护得比较好,功能也强大一些,所以采用channels了

    具体在与web的通讯中,怎么判断App是否扫码了,我是这样做的(仅供参考):

      在后端生成key并第一次向web发送消息的时候,就存入将key存入redis,值为空。然后循环检测该值是否不为空,不为空就当做token发送给web,超时就提醒web。app扫码后调用后端接口时,后端就根据key将值设为身份token,前面循环检测到不为空,就...

    当然,也可以去掉循环检测,让app也走websocket,把整体当做一个聊天室

    下面展示主要代码

     跟Web通讯的代码:

    from channels.generic.websocket import WebsocketConsumer
    import time,random
    
    redis_helper = RedisHelper()    # 自己的连接Redis工具类
    
    # 扫码登录
    class SaoLoginSync(WebsocketConsumer):
        redis_hash_name = 'sao_login'   # key存入redis1的hash结构名
        def connect(self):
            # 创建连接时调用
            self.accept()
            self.key = str(time.time()) + str(random.randint(0,9999))    # 用户id + 时间戳 + 随机数
            redis_helper.hset(self.redis_hash_name, self.key, '')
            self.send(text_data=self.key)  # key发给web生成二维码
    
            # 在此循环监听 app是否扫码了,扫码后吧生成的token发给web
            token = False
            start_time = time.time()
            while not token:
                token = redis_helper.hget(self.redis_hash_name, self.key)
                if token:
                    self.send(text_data=token, close=True)
                if time.time() - start_time > 120:
                    self.send(text_data='again', close=True)
    
        def disconnect(self, close_code):
            # 连接关闭时调用
            redis_helper.hdel(self.redis_hash_name, self.key)  # 删除key
            self.close()

    App扫码之后调用的接口代码:

    from rest_framework.decorators import api_view
    
    # 扫码完成通知
    @api_view(['POST'])
    @login_verify   # 自己的登录验证装饰器,验证成功会加入user对象参数
    def sao_code(request,user):
        key = request.POST.get('key')     # 扫码获取的key
        redis_hash_name = 'sao_login'   # key所在的hash结构名,与web通讯时一致
        platform = 'web'  # 平台
        redis_helper = RedisHelper()
    
        if redis_helper.hexists(redis_hash_name, key):  # 如果key存在
            # redis存token
            token = create_login_token(user.id, Platform[platform])
            login_key = Platform[platform] + '_login_token_' + str(user.id)
            redis_helper.set(login_key, token, ex=datetime.timedelta(days=30))    # 记录web的登录token
            redis_helper.hset(redis_hash_name, key, token)  # app 已经扫码完成,可以把token发送给web
            code, msg = (100, 'Sao successfully')
        else:
            code, msg = (-1, 'Key does not exist')
    
        return ret_CORS(code, msg)

    对了, 正式部署到服务器的时候,channels得用daphne启动,然后最好配置一下由nginx转发请求

  • 相关阅读:
    多态
    抽象类和接口
    面向对象3
    类的继承 设计模式
    面向对象2
    面向对象
    复习
    对json的简单认识
    关于AJAX
    PHP配置开发环境
  • 原文地址:https://www.cnblogs.com/MilletChili/p/9936850.html
Copyright © 2011-2022 走看看