Python Bottle基于 token 的认证应用

  • #JWT

'''
JWT 代表 JSON Web Token ,它是一种用于认证头部的 token 格式。这个 token 帮你实现了在两个系统之间以一种安全的方式传递信息。
我们暂且把 JWT 作为“不记名 token”。一个不记名 token 包含了三部分:header,payload,signature。

header 是 token 的一部分,用来存放 token 的类型和编码方式,通常是使用 base-64 编码。

payload 包含了信息。你可以存放任一种信息,比如用户信息,产品信息等。它们都是使用 base-64 编码方式进行存储。
signature 包括了 header,payload 和密钥的混合体。密钥必须安全地保存储在服务端。

(https://zhuanlan.zhihu.com/p/19920223)

'''

 

  • Python jwt

https://github.com/jpadilla/pyjwt

# -*-coding:utf-8 -*-

import jwt

secret = b'???\\\//>000'

encoded = jwt.encode({'user': 'bottle'}, secret, algorithm='HS256')
print encoded

decoded = jwt.decode(encoded, secret, algorithms=['HS256'])

print decoded

 

  • 实践

使用mongodb保存用户数据

使用bottle做服务

  1. config.py
class settings(object):
    host = 'localhost'

    port = 12306

    secret = b'---------00000???\\'

  

  1. mongodb保存数据
user ={
    'name':'user1',
    'passwd':'passwd',
    'ident':0 #public
}

admin = {
    'name':'bottle',
    'passwd':'passwd2',
    'ident':1 #admin
}
  1. /login路由
@app.route('/login', method='POST')
def login():
    name   = request.forms.get('name')
    passwd = request.forms.get('passwd')
    ret = db.user.find_one({'name':name})
    if ret and ret['passwd'] == passwd:
         if ret.get('token', None):
            res = {
                'status': False,
                'data': "Error occured: " + 'User already logined!'
             }
            return res
         token = jwt.encode({'user': name, 'ident':ret['ident']}, settings.secret, algorithm='HS256')
         db.user.update({'name':name}, {'$set':{'token':token}})
         res = {
            'status': True,
            'data': name,
            'token': token
         }
         return res
    else:
        res = {
            'type': False,
            'data': "Error occured: " + 'User name or password wrong!!!'
        }
        return res
  1. login_required  验证
def login_required():
    def decorator(func):
        def wrapper(*args, **kwargs):
            authorization = request.headers.get('authorization')
            if not authorization:
                 abort(403, "Sorry, access denied.")
            return func(authorization)
  return wrapper return decorator
  1. /me 测试路由
@app.route('/me')
@login_required()
def me(token):
    ret = db.user.find_one({'token':token})
    if ret:
        ret.pop('_id')
        res = {
            'type':True,
            'data':ret
        }
        return res
    else:
        res = {
            'type':False,
            'data':"Error occured: " + ret
        }
        return res

 

  • 测试

使用curl测试

获取token
curl -d 'name=bottle&passwd=passwd2' http://localhost:8080/login

使用token获取资源
curl -H 'authorization:your_token' http://localhost:8080/me

  

  • 总结

测试结果十分满意的。

不过个人发现了几个问题或者说不足

1,使用pyjwt每次生成token是一样的?

2,token是不是还应该有时效?

3,  现在只是拿到token,那么token的权限认证呢?

 

posted @ 2016-08-08 12:46  batch.me  阅读(1227)  评论(0编辑  收藏  举报