Python sanic-jwt 身份验证

官方文档地址:
Sanic JWT — sanic-jwt 1.5.0 documentation
https://sanic-jwt.readthedocs.io/en/latest/index.html

前后端分离项目,使用JWT进行身份校验。

安装

pip install sanic-jwt

使用

简易使用:
官方给出的代码:

from sanic import Sanic
from sanic_jwt import exceptions
from sanic_jwt import initialize


class User:
    def __init__(self, id, username, password):
        self.user_id = id
        self.username = username
        self.password = password

    def __repr__(self):
        return "User(id='{}')".format(self.user_id)

    def to_dict(self):
        return {"user_id": self.user_id, "username": self.username}


users = [User(1, "user1", "abcxyz"), User(2, "user2", "abcxyz")]

username_table = {u.username: u for u in users}
userid_table = {u.user_id: u for u in users}


async def authenticate(request, *args, **kwargs):
    username = request.json.get("username", None)
    password = request.json.get("password", None)

    if not username or not password:
        raise exceptions.AuthenticationFailed("Missing username or password.")
	#验证账号密码
    user = username_table.get(username, None)
    if user is None:
        raise exceptions.AuthenticationFailed("User not found.")

    if password != user.password:
        raise exceptions.AuthenticationFailed("Password is incorrect.")
		#返回错误应该只需返回"账号或密码错误"
    return user #成功返回user对象


app = Sanic()
initialize(app, authenticate=authenticate)


if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8888)

启动后会绑定以下URL:
http://127.0.0.1:8888/auth
成功返回返回access_token 要保存到本地,下次请求时要在请求头附加 Authorization。

access_token JSON Web Tokens (“JWT”) 介绍:
What is a JWT? — sanic-jwt 1.5.0 documentation
https://sanic-jwt.readthedocs.io/en/latest/pages/whatisjwt.html

同时还会绑定
/auth/verify
用于验证access token是否有效
verify

修改默认地址

Configuration — sanic-jwt 1.5.0 documentation
https://sanic-jwt.readthedocs.io/en/latest/pages/configuration.html

Initialize(app, url_prefix='/api/authentication')

/auth将被改为/api/authentication

其他地址的设置:

Initialize(
    app,
    path_to_authenticate='/my_authenticate',
    path_to_retrieve_user='/my_retrieve_user',
    path_to_verify='/my_verify',
    path_to_refresh='/my_refresh',
)

获取token的拥有者User

#!/usr/bin/env python
# -*- encoding: utf-8 -*-


from sanic import Sanic
from sanic_jwt import exceptions
from sanic_jwt import initialize

class User:

    def __init__(self, id, username, password):
        self.user_id = id
        self.username = username
        self.password = password

    def __repr__(self):
        return "User(id='{}')".format(self.user_id)

    def to_dict(self):
        return {"user_id": self.user_id, "username": self.username}

    @staticmethod
    def get(user_id):
        """
        静态方法 通过userid查询 构建User对象
        :param user_id:
        :return:
        """
        print("get",user_id)
        user = userid_table.get(user_id)#这里在业务上应该是查询数据库
        # _user =  checkUser(user_id)
        # user = User(_user.user_id,_user.username,_user.password) #构造自身
        return user

users = [User(1, "user1", "abcxyz"), User(2, "user2", "abcxyz")]

username_table = {u.username: u for u in users}
userid_table = {u.user_id: u for u in users}



async def authenticate(request, *args, **kwargs):
    username = request.json.get("username", None)
    password = request.json.get("password", None)

    if not username or not password:
        raise exceptions.AuthenticationFailed("Missing username or password.")

    user = username_table.get(username, None)
    if user is None:
        raise exceptions.AuthenticationFailed("User not found.")

    if password != user.password:
        raise exceptions.AuthenticationFailed("Password is incorrect.")
    print(user.to_dict())
    return user

async def retrieve_user(request, payload, *args, **kwargs):
    """
    这个是/auth/me接口的
    :param request:
    :param payload:
    :param args:
    :param kwargs:
    :return:
    """
    if payload:
        user_id = payload.get('user_id', None)
        print(payload) #{'user_id': 1, 'exp': 1615122254}
        user = User.get(user_id=user_id)#查询user并返回 get应该是个静态方法 返回构造好的user
        return user.to_dict()
    else:
        return None

app = Sanic(__name__)
initialize(app,
            authenticate=authenticate,
            retrieve_user=retrieve_user,
           )


if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8888)

代码增加User的get方法,函数retrieve_user和initialize增加retrieve_user=retrieve_user
在这里插入图片描述这个借口可以根据access token获取里面存储的user_id,再通过user_id获取User返回。

修改返回的response

from sanic_jwt import Responses


class MyResponses(Responses):
    """
    额外的返回 在playload外的
    """
    @staticmethod
    def extend_authenticate(request,
                            user=None,
                            access_token=None,
                            refresh_token=None):
        """
        /auth接口
        """
        print(user)
        if(type(user)!=User):
            return {'errno': '2', 'errmsg': '用户或密码错误'}
        return {"user":user.to_dict()}

    @staticmethod
    def extend_retrieve_user(request, user=None, payload=None):
        """
        这个是/auth/me接口的 在retrieve_user之后执行
        """
        return {"user":user,"payload":payload}

    @staticmethod
    def extend_verify(request, user=None, payload=None):
        """
        /auth/verify
        """
        print(payload)
        return {"user":user}

    @staticmethod
    def extend_refresh(request,
                       user=None,
                       access_token=None,
                       refresh_token=None,
                       purported_token=None,
                       payload=None):
        return {}

initialize(app,
            authenticate=authenticate,
            retrieve_user=retrieve_user,
            responses_class=MyResponses,
           )

在这里插入图片描述在这里插入图片描述

刷新access token

/auth/refresh
刷新access token
POST 返回新的access token

身份校验

@protected()
只有登录了才会响应

from sanic_jwt.decorators import protected


@app.route("/")
async def open_route(request):
    return json({"protected": False})


@app.route("/protected")
@protected()
async def protected_route(request):
    return json({"protected": True})

@scoped()
只有在这个用户域才会响应

@app.route("/protected/scoped/1")
@scoped('user')
async def protected_route1(request):
    return json({"protected": True, "scoped": True})

可以用多个scope
@scoped([‘user’, ‘admin’])

Scopes

增加scopes

async def my_scope_extender(user, *args, **kwargs):
    return user.scopes

Initialize(app, add_scopes_to_payload=my_scope_extender)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nickdlk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值