当前位置:   article > 正文

Python sanic-jwt 身份验证_sanic jwt

sanic jwt

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

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

安装

pip install sanic-jwt
  • 1

使用

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

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

启动后会绑定以下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')
  • 1

/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',
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

获取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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83

代码增加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,
           )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

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

刷新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})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

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

可以用多个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
  • 2
  • 3
  • 4
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/558383
推荐阅读
相关标签
  

闽ICP备14008679号