美文网首页我爱编程程序员
[Tornado]扫码登录实践

[Tornado]扫码登录实践

作者: melo的微博 | 来源:发表于2018-06-16 16:11 被阅读110次
    思路: 基于[Tornado]异步io实现异步非阻塞长链接。
    

    本文作者为
    简书-melo的微博 / 掘金-melo的微博
    Github-meloalright / Medium-@meloalright
    转载请注明出处哦。

    1.扫码登录需求

    部门项目需要实现一个APP扫码即可在PC端实现登录的需求。
    结合部门内部的资源协调,适合使用一个异步io的框架实现简单扫码登录接口快速上线。
    初期考虑使用[node.js]或者[Tornado]
    最终选择使用[Tornado]
    

    2.实现思路

    - 基于 uuid.uuid4() 为二维码生成唯一 uuid
    - 基于 tornado.locks 实现长链接 handler 协程的通知等待
    - 基于 await http_client.fetch 实现扫码确认请求handler的内部校验接口调用
    

    3.代码结构

    │ 
    │   # @ Python Tornado 工程代码
    │ 
    ├── tornado-project
    │   │
    │   │   # @ 各种handler放这里
    │   │
    │   ├── handlers
    │   │   │ 
    │   │   ├── __init__.py
    │   │   │ 
    │   │   ├── confirm_handler.py # 确认扫码请求的handler
    │   │   │ 
    │   │   │ 
    │   │   ├── uuid_handler.py # 获取uuid请求的handler
    │   │   │ 
    │   │   ├── wait_handler.py # 长链接请求的handler
    │   │   │ 
    │   │   │  # @ redis_map 放这里
    │   │   │ 
    │   │   └── redis_map 
    │   │       ├── __init__.py
    │   │       └── redis_map.py
    │   │ 
    │   ├── main.py # 入口文件
    │   │ 
    │   └── requirements.txt # 项目依赖
    

    4. wait_handler

    /wait 长链接接口

    class WaitHandler(tornado.web.RequestHandler):
        async def post(self):
            data = tornado.escape.json_decode(self.request.body)
            cursor = data["cursor"]
    
            status = int(RedisMap.get_status(cursor))
            '''
            some code ...
            '''
    
            while status < 2 and status > -1:
                self.wait_future = RedisMap.wait()
    
                try:
                    await self.wait_future
                except asyncio.CancelledError:
                    return
    
                status = int(RedisMap.get_status(cursor))
                '''
                some code ...
                '''
    
    
            if self.request.connection.stream.closed():
                RedisMap.delete(cursor) # delete
                return
    
            RedisMap.delete(cursor) # delete
            self.write({
                "status": status 
                '''
                other key value ...
                ''' 
            })
    
        def on_connection_close(self):
            self.wait_future.cancel()
    

    5. confirm_handler

    /confirm 确认扫码登录接口

    
    class ConfirmHandler(tornado.web.RequestHandler):
    
        async def auth(self, param):
            http_client = tornado.httpclient.AsyncHTTPClient()
            response = await http_client.fetch("An auth uri blau blau ...", headers=param)
            '''
            some code ...
            '''
            response_data = tornado.escape.json_decode(response.body)
            return response_data['status'] is 200
    
        async def post(self):
            data = tornado.escape.json_decode(self.request.body)
            authorization = data["authorization"]
            '''
            some code ...
            '''
            is_auth = await self.auth(authorization)
            if not is_auth:
                self.write({
                    "status": 401,
                })
                return
            else:
                self.write({
                    "status": 200
                    })
    

    结语:

    代码只是示例 仅供参考哈(∩_∩)

    鸣谢:

    参考文档:
    tornadoweb.org
    tornado.locks – 同步原语

    相关文章

      网友评论

        本文标题:[Tornado]扫码登录实践

        本文链接:https://www.haomeiwen.com/subject/egimeftx.html