Django REST framework 使用 JWT

在 Django REST framework 使用 JWT

  • 0. 参考博客
  • 1. JWT or Cookie&Session
    • 1.1 JWT
    • 1.2 Cookie&Session
    • 1.3 两者优劣
  • 2. REST framework JWT Auth
    • 2.1 说明
  • 3. 正常操作
    • 3.1 前端怎么传递?
    • 3.0 对整个 ViewSet 设置权限
    • 3.1 view 里操作?
    • 3.2自定义 负载里面的 信息?
  • 4. “骚操作”
    • 4.1 部分有权限接口,但前端无法自定义请求?

0. 参考博客

  1. 初步理解JWT并实践使用
  2. cookie 和session 的区别详解
  3. 基于django-rest-framework的JWT的登陆与认证流程

1. JWT or Cookie&Session

1.1 JWT

  1. JWT(JSON WEB Token)是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。讲人话?是一种基于JSON的、用于在网络上声明某种主张的令牌(token)
  2. JWT通常由三部分组成: 头信息(header), 负载(payload)和签名(signature)
    1. header

      1. 通常包含 token类型 和 采用的加密算法 两部分
            {
                "alg":"HS256",
                "typ":"JWT"
            }
         
        
    2. payload

      1. 负载,它包含了claim, Claim是一些实体(通常指的用户)的状态和额外的元数据,有三种类型的claim:reserved, public 和 private.Reserved claims: 这些claim是JWT预先定义的,在JWT中并不会强制使用它们,而是推荐使用,常用的有 iss(签发者),exp(过期时间戳), sub(面向的用户), aud(接收方), iat(签发时间)。 Public claims:根据需要定义自己的字段,注意应该避免冲突 Private claims:这些是自定义的字段,可以用来在双方之间交换信息 负载使用的例子:{ "sub": "1234567890", "name": "John Doe", "admin": true} 上述的负载需要经过Base64Url编码后作为JWT结构的第二部分。
    3. signature

      1. 前面两部分信息加密,然后加上我们自己设定的一个secret的字符串,进行再次加密,这次加密是header中声明的加密算法(HS256),构造成一个签名信息
  3. 最后变成 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMywidXNlcxxxxxxxxxxxXNoZXJfdGVzdCIsImxxxxA1NDc0OCwiZW1haWwiOiIxMjNAMTIzMS5jb20ifQ.DF2a63Up9wqVvEwQrb7r3z3aOdkDcFCgNNL9pjVN3R8

1.2 Cookie&Session

  • 具体可以参考 cookie 和session 的区别详解

1.3 两者优劣

  • 网上 文章一大推,个人经历场景有点少,没办法详细比较,留坑~
  • 现在的感觉?两者都不是 “放之四海而皆准”的,总有场景有坑。。。
  • 那为什么要用 token? !!! 又不是我决定的(如果我决定?团队熟悉哪个就用哪个!),出现什么就解决什么问题呗!

2. REST framework JWT Auth

2.1 说明

  1. 使用REST framework JWT Auth, 官方文档
  2. 环境要求
    1. Python (2.7, 3.3, 3.4, 3.5)
    2. Django (1.8, 1.9, 1.10)
    3. Django REST Framework (3.0, 3.1, 3.2, 3.3, 3.4, 3.5)
  3. 刚发现,项目环境一个也不符合,但目前没发现什么坑!(不要问为什么还用了,我是接盘的。。。私以为,应该文档未更新)
    1. djangorestframework 3.8.2
    2. Django 1.11.1
    3. Python 3.6.6
  4. 项目配置
    1. 请参考基于django-rest-framework的JWT的登陆与认证流程

3. 正常操作

3.1 前端怎么传递?

  1. 官方文档里面有写,在 HTTP hard AuthorizationJWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMywidXNlcm5hbWUiOiJwdXNoZXJfdGVzdCIsImV4cCI6MTUzOTUyODUxMywiZW1haWwiOiIxMjNAMTIzMS5jb20ifQ.nm9odcWAXL05YM8TP0XTZhjbhuiqq6bYeeRjbcorgKw。ps: 格式为:JWT+空格+token。默认为 JWT ,配置中可更改

3.0 对整个 ViewSet 设置权限

from rest_framework.authentication import SessionAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication

class EducationViewSet(mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin,
                       viewsets.GenericViewSet):
    queryset = Education.objects.all()
    serializer_class = EducationSerializer
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnlyDepth)
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
  • 说明,未带token 的会直接被框架拦截

3.1 view 里操作?

  • self.request.user 即 当前登录用户
  • 想起来再补充。。。

3.2自定义 负载里面的 信息?

from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

# obj 为一个对象
payload = jwt_payload_handler(obj)
# dict 即 自定义 信息 ,格式为 字典
token = jwt_encode_handler(dict)

4. “骚操作”

4.1 部分有权限接口,但前端无法自定义请求?

  1. 根据同源,不修改前端代码
    1. 启用 cookie
      1. 在配置中增加
        JWT_AUTH = { "JWT_AUTH_COOKIE": "token", # 键值名字随意订 }

      2. 登录接口中返回增加 cookie, 键名与上一步相同,将token 传过去

      3. 确保 ViewSet 中 authentication_classesSessionAuthentication,没有则增加

  2. 修改前端代码,将token 从HTTP 参数传入
    1. 自定义认证,从请求参数去取
      from rest_framework_jwt.authentication import JSONWebTokenAuthentication
      class GetAuthentication(JSONWebTokenAuthentication):
      
      def get_jwt_value(self, request):
          # 告诉框架 token 在哪里
         return request.query_params.get("jwt")   # http 参数为 jwt
      
    2. 引入GetAuthentication, ViewSet 中 authentication_classes 增加 GetAuthentication

你可能感兴趣的:(关于,Django,的一些事)