sanic-jwt

1.文档地址

sanic-jwt

2.开始使用

  • 示例
from sanic_jwt import Initialize

async def authenticate(request):
   return dict(user_id='some_id')

app = Sanic(__name__)
Initialize(app, authenticate=authenticate)
  • 两个接口
    • 获取token:/auth
    curl -X POST http://localhost:8000/auth
    
    • 验证token:/auth/verify
    curl -X GET -H "Authorization: Bearer <JWT>" http://localhost:8000/auth/verify
    

3.安装

pip install sanic-jwt

4.初始化

  • 概念
    • Sanic JWT通过Initialize创建Blueprint,并将一些路由附加到应用程序中
    • Sanic JWT是用户认证系统,需要把用户管理系统绑定到Sanic JWT
    • 尽量使用Initialize类,避免使用initialize方法,后续可能删除
  • Initialize类
    • Sanic JWT的入口,可配置运行的参数
    • 初始化分为5个部分:
      • A.sanin app/sanic blueprint的实例(必须)
      • B.handler methods(其中authenticate必须)
      • C.runtime configurations
      • D.additional Views
      • E.component overrides
    • 初始化完成后,通过@protected装饰器,保护路由/Blueprint
    • 可只保护指定的某个Blueprint
  • handler methods详解
    • Sanic JWT提供钩子函数,用户传入钩子函数完成相应的功能。大多函数都能使用普通函数/协程,特别注明的除外
    • A.authenticate(必须)
      • 功能:决定是否有一个有效的用户需要进行身份验证
      • 返回类型:
        • 包含user_id键的dict
        • 包含id和to_dict属性的实例(默认使用实例的user_id查找id,可指定)
      • 注意:如果不需要身份验证,应该抛出异常(AuthenticationFailed),而不应返回None,可能引起500异常
    • B.store_refresh_token
      • 功能:将刷新令牌持久化到磁盘
      • 注意:非必需。通过设置refresh_token_enabled=True起用,如果起用但没有实现,将抛出RefreshTokenNotImplemented异常
    • C.retrieve_refresh_token
      • 功能:从磁盘检索刷新令牌
      • 注意:非必需。通过设置refresh_token_enabled=True起用,如果起用但没有实现,将抛出RefreshTokenNotImplemented异常
    • D.retrieve_user
      • 功能:从应用程序检索用户对象
      • 用于返回/auth/me接口/装饰器@inject_user中的用户对象
      • 返回类型:
        • dict
        • 包含to_dict方法的实例
        • None
    • E.add_scopes_to_payload
      • 功能:向访问令牌添加scope。scope给程序提供许可(权限),同java shiro验证框架Permissions的功能
    • F.override_scope_validator
      • 功能:覆盖默认scope验证
      • 注意:本功能必须是一个普通函数,不能使用异步编程
    • G.destructure_scopes
      • 功能:在scope验证之前调用,可以对scope进行一些预处理
    • H.extend_payload
      • 功能:在将负载打包到JWT中,可以对负载添加额外的声明。(负载是jwt保存的json信息。jwt分三部分:header头,payload载体,signature签名)
  • runtime configurations(运行时配置)详解
    • 有多种方法配置Sanic JWT设置。其中之一是初始化时将配置作为关键字参数
  • additional Views详解
    • 功能:可向身份验证系统添加额外的接口,这些接口并不通过默认的用户认证
    • 实现:创建一个基于类的视图,实现处理程序(必须有options response),并映射一个接口名称
  • component overrides详解
    • 有些组件可以子类化进行控制:
      • Authentication
      • Configuration
      • Responses

5.接口和响应(Endpoints and Responses)

  • Endpoints(接口)
    • Sanic JWT提供的接口会以/auth为访问路径前缀,可通过url_prefix更改
    • Default Endpoints(默认有四个接口),可更改它们的路径:
      • path_to_authenticate=’/my_authenticate’
      • path_to_retrieve_user=’/my_retrieve_user’
      • path_to_verify=’/my_verify’
      • path_to_refresh=’/my_refresh’
    • Authenticate
      • 功能:检查用户是否有效,如果有效并返回true,则sanic jwt会生成访问令牌。访问路径/auth(post请求)
    • Verification
      • 功能:检查给定的访问令牌是否有效。访问路径/auth/verify(get请求)
    • Current User Details
      • 功能:检索当前已验证用户的信息。访问路径/auth/me(get请求)
    • Refresh Token
      • 功能:根据当前令牌获取一个新令牌。访问路径/auth/refresh(post请求)
  • Modify Responses
    • 默认接口的响应可以通过子类化并连接到适当的方法来扩展,必须返回dict。自定义响应应该在初始化时使用responses_class关键字参数连接到Sanic JWT
  • Custom Endpoints
    • 扩展默认接口,提供自定义的接口
  • Exception Handling
    • 可以自定义Sanic JWT发生异常时的响应。通过子类化responses类并覆盖exception_respons
  • Microservices(微服务)
    • 只对单个服务进行身份验证,并在其它服务中使用生成的令牌(auth_mode=True)。每个服务必须具有相同secret

6.Payload(jwt有效载荷)

  • Sanic JWT有效载荷三种主要用途:
    • passing claims(传递claims,jwt有效载荷JSON的每一条包含键/值对的信息,被称为一个claim)
    • passing scope(传递scope)
    • passing arbitrary information to the client(将任意信息传递给客户机)
  • jwt标准的五项claim
    • exp:Expires过期时间,token有效期通常很短,默认开启。可通过verify_exp=False禁用过期时间
    • aud:Audience面向的用户,默认关闭。可通过claim_aud='my_client_domain.com’设置
    • iat:Issued at签发时间,默认无,可通过claim_iat=True开启
    • iss:Issuer签发者,默认无,可通过claim_iss='my_server_domain.com’设置
    • nbf:Not before在指定时间之后才启用token,默认无。可通过claim_nbf=True, claim_nbf_delta=(60 * 3)开启并设置启用时间
  • jwt自定义的claim
    • 功能:在jwt的payload添加额外的claim
    • 实现:实现claim的子类,在custom_claims的列表中注册
  • Extra Verifications(额外的验证)
    • 功能:对负载进行额外的验证
    • 实现:通过extra_veriations注册一个方法列表(每个方法返回一个布尔值)
  • Payload Handlers(payload处理程序)
    • Initialize可用于修改Payload处理程序,如下
      • Adding Scopes(添加scope):add_scopes_to_payload
      • Extending the payload(扩展payload):extend_payload
      • Token signing(签名)
        • 以密码方式验证:secret
        • 使用非对称算法,须提供公钥和私钥来处理令牌的编码和解码:public_key,public_key

7.保护路由(Protecting Routes)

  • 功能:保证只有具有有效访问令牌的用户才能访问指定资源。可以使用@protected装饰器保护应用程序中的路由
  • @protected
    • 使用
      • 默认:@protected()
      • 在蓝图上初始化Sanic JWT:
        • 将蓝图的实例传递到@protected:@protected(blueprint)
        • 从Initialize实例访问装饰器:@sanicjwt.protected()
  • Class based views(保护基于类的视图)
    • 用标准的Sanic方法,保护基于类的视图
    app.add_route(ProtectedView.as_view(), '/protected')
    
  • Passing the Token(传递令牌)
    • Header Tokens(头部令牌,默认)
      • 头部令牌通过在http协议的header中添加Authorization传递
      • 组成
        • 前缀(the word Bearer),可通过authorization_header_prefix修改
        • 访问令牌(the JWT access token),可通过authorization_header修改
    • Cookie Tokens(cookie令牌)
      • 通过cookie_set=True开启
      • 配置:
        • cookie_domain 更改与cooke关联的域(默认为")
        • cookie_httponly 是否在cookie上设置httponly标志(默认为True)
        • cookie_access_token_name 存储cookie用于访问令牌的名称
        • cookie_refresh_token_name 存储cookie用于刷新令牌的名称
          注意:cookie令牌不要禁用cookie_httponly,禁用后在客户机上运行的任何javascript都可以访问令牌
    • Query String Tokens(查询字符串令牌)
      • 通过query_string_set=True启用。用于验证websocket认证
    • Both Header and Cookie(头部令牌和cookie令牌同时使用)
      • 首先采用cookie令牌,如果cookie不存在,则使用头部令牌
      • 设置cookie_set=True和cookie_strict=False
    • Per view declaration(每个视图单独指定令牌类型)
      • @protected(cookie_set=False)
  • Advanced Decorators(高级装饰器)
    • Sanic JWT实例中直接使用装饰器
    sanicjwt = Initialize(app)
    @sanicjwt.protected()
    async def protected_route(request):
    
    • 蓝图实例中直接使用装饰器
    bp = Blueprint('Users')
    @bp.protected()
    async def users(request, id):
    
    • 注意:基于实例的装饰器的概念也适用装饰器和@inject_user装饰器

8.访问权限(Scopes)

  • 功能:将资源限定为需一个或多个scope,只有具有指定scope的用户才允许访问
  • 使用:@scoped()装饰器
  • 组成(Requirements for a scoped)
    • namespace:范围可以有一个名称空间,也可以没有名称空间
    • actions:范围可以没有操作,也可以有很多操作
    scope:       user:read:write
    namespace:   user
    action:      [read, write]
    
  • 匹配规则(How are scopes accepted?)
    • 有效负载的scope等于或高于指定资源所需scope,则认为具有访问权限
    • 只指定namespace,没有指定具体的action,则认为拥有该namespace下所有action的权限
  • @scoped装饰器(The @scoped decorator)
# **需要user的scope
@scoped('user')  
# **需要user和admin的scope
@scoped(['user', 'admin'])
# **需要user或admin的scope
@scoped(['user', 'admin'], False)

# **Blueprint中使用
bp = Blueprint('Users')
Initialize(bp)

@bp.get('/users/<id>')
@scoped(['user', 'admin'], initialized_on=bp)
async def users(request, id):
    ...
- 参数(Parameters)
    - scopes:必须
        - 字符串
        - 字符串列表
        - 返回上述值的同步/异步函数
    - requires_all:默认true,可选。true表示需要匹配所有的scope,false表示只匹配其中之一即可
    - require_all_actions:默认true,可选。true表示需要匹配所有的action,false表示只匹配其中之一即可
- 处理程序(Handler)
    - 通过add_scopes_to_payload添加scope到jwt payload

9.刷新令牌(Refresh Tokens)

  • 问题:
    • 访问令牌一旦发放在有效期期间不能被撤销
    • 访问令牌的寿命很短,每次访问令牌过期,客户端都需重新进行身份验证
  • 刷新令牌运行过程
    • Refresh Tokens是由服务器存储的令牌。客户端随时可向服务器发送refresh令牌并请求新的访问令牌
    • 服务器接受refresh令牌,在存储中查找是否合法,是则生成新的访问令牌
    • 刷新令牌和访问令牌一起工作,以提供用户友好且安全的身份验证环境
  • (配置)Configuration
    • Sanic JWT实现了刷新令牌的创建和传递。和身份验证一样,令牌的存储和检索需要开发人员实现。开发人员可以决定如何持久化令牌,何时停用令牌。
    • 使用步骤
      • refresh_token_enabled:启用刷新令牌,默认关闭,设置为true开启
      • store_refresh_token:存储刷新令牌,可以是同步/异步函数
      # **把刷新令牌保存到redis中
      # **第一个参数为user_id或者authenticate方法返回的user对象
      # **第二个参数为刷新令牌
      async def store_refresh_token(user_id, refresh_token, *args, **kwargs):
          key = 'refresh_token_{user_id}'
          await aredis.set(key, refresh_token)
      
      • retrieve_refresh_token:检索刷新令牌
      # **从redis中检索刷新令牌
      # **第一个参数为请求对象
      # **第二个参数为user_id或者authenticate方法返回的user对象
      async def retrieve_refresh_token(request, user_id, *args, **kwargs):
          key = f'refresh_token_{user_id}'
          return await aredis.get(key)
      
  • 使用刷新令牌(Using the refresh token)
    • 需要访问refresh令牌接口,以获得一个新的访问令牌
  • 有效期的刷新令牌(Can I have an expirable refresh token?)
    • Sanin JWT不支持有效期的刷新令牌
    • 原因
      • 刷新令牌(utf-8编码,24个字符),不是JWT,没有payload,不受验证约束
      • 开发人员决定是否接受refresh令牌
      • 想使令牌过期,可在程序中处理
    • 实现:重写generate_refresh_token,生成自已的token,并在retrieve_refresh_token中进行验证

10.异常(Exceptions)

  • AuthenticationFailed
  • MissingAuthorizationHeader
  • MissingAuthorizationCookie
  • InvalidAuthorizationHeader
  • MissingRegisteredClaim
  • Unauthorized

11.配置(Configuration)

  • 配置方式
    • Sanic方式(The Sanic way)
    # **设置名称转换为大写,并添加SANIC_JWT_前缀
    app = Sanic()
    app.config.SANIC_JWT_ACCESS_TOKEN_NAME = 'jwt'
    
    Initialize(app)
    
    • 内联初始化(Inline at initialization)
      • 设置Initialize对象的关键字参数
      • 配置类(Configuration class)
      # **继承配置
      class MyConfiguration(Configuration):
          # **重写类的属性覆盖原属性
          access_token_name='jwt'
          
          # **使用方法set_<setting>覆盖原属性
          def set_access_token_name(self):
              return 'jwt'
          # **set_<setting>不限于一个函数,这样也可以 
          set_access_token_name = 'jwt'  
          
          # **get_< settings >()方法对每个请求求值
          # **节约资源,每个请求只计算一次,在该请求的生命周期内缓存结果
           def get_authorization_header(self, request):
              return request.headers.get(key) if key in request.headers else "authorization"
          
      # **注册
      Initialize(app, configuration_class=MyConfiguration)
      
  • 设置项(Settings)
    • access_token_name:默认’access_token’,标识访问令牌的key
    • algorithm:默认’HS256’,生成标记的哈希算法
      • 可选项: HS256,HS384,HS512,ES256,ES384,ES512,RS256,RS384,RS512,PS256,PS384,PS512
    • auth_mode:启用/auth接口,默认true
    • authorization_header:HTTP请求header中令牌key,默认authorization
    • authorization_header_prefix:HTTP请求header中JWT的前缀,默认Bearer
    • authorization_header_refresh_prefix:保留字,默认Refresh
    • claim_aud:面向的用户,默认None
    • claim_iat:启用生成令牌签发时间,默认false
    • claim_iss:令牌签发者,默认None
    • claim_nbf:启用生成令牌在签发后多久生效,默认false
    • claim_nbf_delta:令牌在签发后多久生效,默认60 * 3(3分钟)
    • cookie_access_token_name:使用cookie令牌,cookie中令牌的名称,默认access_token
    • cookie_domain:cookie所在的域,默认’’
    • cookie_httponly:启用http only cookie,默认true
    • cookie_refresh_token_name:使用cookie令牌,cookie中刷新令牌的名称,默认refresh_token
    • cookie_set:启用cookie令牌,默认false
    • cookie_strict:启用cookie令牌,cookie获取失败后是否禁用头部令牌,默认false
    • cookie_token_name:cookie_access_token_name的别名,用于测试,默认false
    • do_protection:启用@protected装饰器正常工作,默认true
    • expiration_delta:令牌有效期,默认60 * 5 * 6(30分钟)
    • generate_refresh_token:创建和返回刷新令牌的方法,默认sanic_jwt.utils.generate_refresh_token
    • leeway:系统时间配置中微小更改的回旋时间秒,默认60 * 3(3分钟)
    • path_to_authenticate:身份验证接口路径,默认/
    • path_to_refresh:刷新令牌接口路径,默认/refresh
    • path_to_retrieve_user:当前用户接口路径,默认/me
    • path_to_verify:令牌验证接口,默认/verify
    • private_key:用于生成令牌的私钥,依赖于使用的散列算法,默认None
    • public_key:secret的别名
    • query_string_access_token_name:查询字符串令牌,cookie中令牌的名称,默认access_token
    • query_string_refresh_token_name:查询字符串令牌,cookie中刷新令牌的名称,默认refresh_token
    • query_string_set:开启查询字符串令牌,默认false
    • query_string_strict:开启查询字符串令牌,查询字符串不存在是否禁用头部令牌,默认false
    • refresh_token_enabled:启用刷新令牌,默认false
    • refresh_token_name:刷新令牌的key,默认refresh_token
    • scopes_enabled:启用scope块并将作用域添加到jwt payload,默认false
    • scopes_name:jwt payload中scope的key,默认scopes
    • secret:用于哈希算法生成和签名JWT,每个应用应该设置自已的值,默认his is a big secret. Shhhhh
    • strict_slashes:启用对接口url执行严格的/匹配,默认false
    • url_prefix:sanic jwt默认接口的前缀,默认/auth
    • user_id:包含用户id的用户对象的键或属性,默认user_id
    • verify_exp:开启令牌过期验证,默认true
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值