我爱编程程序员

[Tornado]扫码登录实践

2018-06-16  本文已影响110人  melo的微博
思路: 基于[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 – 同步原语

上一篇下一篇

猜你喜欢

热点阅读