接口文档,jwt,base64编码解码

Ⅰ 接口文档

【一】接口文档了解

#  作为后端,接口写完了--->接口给前端使用
	-登录接口:username,password ,code
 
#  写接口的人负责写接口文档	
	-如何写?
    -写在哪?
 
#  通常在公司中:
	1 使用world编写,放在公共平台上
    2 使用MD编写
    3 第三方平台编写:showdoc
    	-https://www.showdoc.com.cn/
    4 自己开发:大公司
    5 基于开源的 使用:YAPI 百度开源
    	-https://zhuanlan.zhihu.com/p/366025001
    6 自动生成接口文档
    #  自动生成接口文档步骤
	-drf-->借助于第三方生成	
    	-corapi
        -drf-yasg
        -drf-spectacular
    -fastapi-->自带接口文档
    
#  接口文档规范(https://opendocs.alipay.com/open-v3/28d9fff7_alipay.trade.refund)
	-接口解释
	-地址
    -请求方式
    -请求参数:地址,头,体   参数说明,是否必填
    -返回示例:字段解释
    -错误码
  • showdoc

【二】coreapi如何使用

# 【1】 安装:REST framewrok生成接口文档需要coreapi库的支持。
	pip install coreapi
# 【2】 在路由中注册
		'''
		from rest_framework.documentation import include_docs_urls
        urlpatterns = [
            ...
            path('docs/', include_docs_urls(title='站点页面标题'))
        ]
		'''
    	from rest_framework.documentation import include_docs_urls
        urlpatterns = [
            path('docs/', include_docs_urls(title='智慧社区项目')),
        ]
# 【3】 在视图类中写 视图类
    	-使用注释
        	--->写在类上的注释:单一方法的视图,可直接使用类视图的文档字符串
        		# 写登录接口
				class UserViewSet(ViewSet):
                    '''
                        登录接口你值得拥有,给你想要的

                    '''
            --->写在方法内的注释:包含多个方法的视图,在类视图的文档字符串中,分开方法定义
                	class BookListCreateView(generics.ListCreateAPIView):
                        """
                        get:
                        返回所有图书信息.

                        post:
                        新建图书.
                        """
             对于视图集ViewSet,仍在类视图的文档字符串中封开定义,但是应使用action名称区分
            		class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
                    """
                    list:
                    返回图书列表数据

                    retrieve:
                    返回图书详情数据

                    latest:
                    返回最新的图书数据

                    read:
                    修改图书的阅读量
                    """
# 【4】 在序列化类中控制字段
    	-required  # 非必填
        -help_text	# 字段描述
       		 # extra_kwargs = {'price': {'required': False, 'help_text': '图书价格'}}
            或者:
            	class Student(models.Model):
                ...
                age = models.IntegerField(default=0, verbose_name='年龄', help_text='年龄')
                ...
# 【5】 配置文件配置
    	REST_FRAMEWORK = {
			'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
		}
# 【6】如果遇到报错

	#AttributeError: 'AutoSchema' object has no attribute 'get_link'
        REST_FRAMEWORK = {
         'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
            # 新版drf schema_class默认用的是rest_framework.schemas.openapi.AutoSchema

        }


# 【7】访问路径
    	http://localhost:8000/docs/
            
            
  • 在视图类中写 视图类

  • 在序列化类中控制字段

Ⅱ jwt介绍

【一】JWT认证

  • 在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。我们不再使用Session认证机制,而使用Json Web Token(本质就是token)认证机制。
  • 作用是 不使用session机制,来存储记录用户登录信息
  • jwt=Json Web Token:Json web token (JWT):常被用于认证,它是一个前端登录认证的方案,jwt就是token的一种

【二】token认证机制

#  token认证机制
	【1】 签发阶段:登录接口,登录成功,就签发
    	-token有 三部分,每部分用 . 分割 ,组装成一个字符串,每部分都用base64编码
        	头部:公司信息,加密方式等
            荷载:真正数据部分,用户id,用户名字,过期时间,签发时间。。
            签名:头部+荷载-->使用某种加密方式加密---》得到一个字符串
       	
        -直接返回给前端,不在后端存储
        -前端拿到后,web:存到cookie中,小程序:存到小程序存储中  app:app存储中
        
    【2】 认证阶段:需要登录后方的接口,要校验token是否合法
    	-前端携带 token在请求头中到后端,后端接收到后进行校验
        -把头部和荷载使用同样的加密方式加密-->得到一个字符串  和第三部分比较是否一样
        	-如果一样,说明就是当前我们签发的,没有被别人篡改过-->校验通过
            	-取出用户id-->就能知道是哪个用户访问了
            -如果不一样,说明就不是当前我们签发的,被别人篡改过-->校验不通过

【三】一个典型的token样式

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.       # 头 
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.# 荷载
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ   # 签名

【1】header

wt的头部承载两部分信息:

  • 声明类型,这里是jwt
  • 声明加密的算法 通常直接使用 HMAC SHA256

完整的头部就像下面这样的JSON:

{
  'typ': 'JWT',
  'alg': 'HS256'
}

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

【2】payload

载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分

  • 标准中注册的声明
  • 公共的声明
  • 私有的声明

标准中注册的声明 (建议但不强制使用) :

  • iss: jwt签发者
  • sub: jwt所面向的用户
  • aud: 接收jwt的一方
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.
  • iat: jwt的签发时间
  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避时序攻击。

公共的声明 : 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

私有的声明 : 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

定义一个payload:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后将其进行base64加密,得到JWT的第二部分。

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

【3】signature

WT的第三部分是一个签证信息,这个签证信息由三部分组成:

  • header (base64后的)
  • payload (base64后的)
  • secret

这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。

// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

将这三部分用.连接成一个完整的字符串,构成了最终的jwt:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

关于签发和核验JWT,我们可以使用Django REST framework JWT扩展来完成。

【4】本质原理

(1)jwt认证算法:签发与校验

1)jwt分三段式:头.体.签名 (head.payload.sgin)
2)头和体是可逆加密,让服务器可以反解出user对象;签名是不可逆加密,保证整个token的安全性的
3)头体签名三部分,都是采用json格式的字符串,进行加密,可逆加密一般采用base64算法,不可逆加密一般采用hash(md5)算法
4)头中的内容是基本信息:公司信息、项目组信息、token采用的加密方式信息
{
  "company": "公司信息",
  ...
}
5)体中的内容是关键信息:用户主键、用户名、签发时客户端信息(设备号、地址)、过期时间
{
  "user_id": 1,
 ...
}
6)签名中的内容时安全信息:头的加密结果 + 体的加密结果 + 服务器不对外公开的安全码 进行md5加密
{
 "head": "头的加密字符串",
  "payload": "体的加密字符串",
 "secret_key": "安全码"
}

(2)签发:根据登录请求提交来的 账号 + 密码 + 设备信息 签发 token

1)用基本信息存储json字典,采用base64算法加密得到 头字符串
2)用关键信息存储json字典,采用base64算法加密得到 体字符串
3)用头、体加密字符串再加安全码信息存储json字典,采用hash md5算法加密得到 签名字符串

账号密码就能根据User表得到user对象,形成的三段字符串用 . 拼接成token返回给前台

(3)校验:根据客户端带token的请求 反解出 user 对象

1)将token按 . 拆分为三段字符串,第一段 头加密字符串 一般不需要做任何处理
2)第二段 体加密字符串,要反解出用户主键,通过主键从User表中就能得到登录用户,过期时间和设备信息都是安全信息,确保token没过期,且时同一设备来的
3)再用 第一段 + 第二段 + 服务器安全码 不可逆md5加密,与第三段 签名字符串 进行碰撞校验,通过后才能代表第二段校验得到的user对象就是合法的登录用户

(4)drf项目的jwt认证开发流程(重点)

1)用账号密码访问登录接口,登录接口逻辑中调用 签发token 算法,得到token,返回给客户端,客户端自己存到cookies中

2)校验token的算法应该写在认证类中(在认证类中调用),全局配置给认证组件,所有视图类请求,都会进行认证校验,所以请求带了token,就会反解出user对象,在视图类中用request.user就能访问登录的用户

注:登录接口需要做 认证 + 权限 两个局部禁用

Ⅲ base64编码解码

#  base64的长度一定是 4 的倍数,如果不足,要用 =  补齐, = 不表示数据,只是占位
#  base64的作用
    #  jwt 使用base64编码
    # 数据在互联网中传输,会使用base64编码后传输
    # 图片的二进制-->转成base64在互联网中传输
import base64
import json


user_dict = {'name':'zyb','age':19,'user_id':741}

user_str = json.dumps(user_dict)

res = base64.b64encode(user_str.encode('utf-8'))


print(res)  # eyJuYW1lIjogInp5YiIsICJhZ2UiOiAxOSwgInVzZXJfaWQiOiA3NDF9

res1=base64.b64decode('eyJuYW1lIjogInp5YiIsICJhZ2UiOiAxOSwgInVzZXJfaWQiOiA3NDF9') # 签名
print(res1)


# 头
res2=base64.b64decode('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9')
print(res2) #   {"alg":"HS256","typ":"JWT"}
# 荷载
res3=base64.b64decode('eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9') # 签名
print(res3)  # {"sub":"1234567890","name":"John Doe","admin":true}

# 签名
res3=base64.b64decode('TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ=') # 签名
print(res3)  # L\x95@\xf7\x93\xab3\xb16p\x16\x9b\xdfDL\x1e\xb1\xc3pG\xf1\x8e\x86\x19\x81\xe1N4X{\x1e\x04
  • 以12306的数码扫码登陆图片为例


s='iVBORw0KGgoAAAANSUhEUgAAAMcAAADHCAIAAAAiZ9CRAAAHAklEQVR42u3bwXbbMAxEUf//T6fLLnrqyJgHUJCflk4iyeRVBQ7Y14+HB328HAKPLlWv7Ph7un8+efOj8Dxv/rx2ifArv7mNdxOQ3eFHlwiH9/qwqEpVqlLVRlW1Eblyu7UT1nR+NEMD5znrrPaoJxOnKlWpSlWrVVFVVK1YqV3io6vfZBYpneEDwD5sqlKVqlT1harC81Dr/zCGoAaB+hGVzowNgqpUpSpVfaEqqsigEvDJWPlIEI/PjqpUpSpVqSqMwsPWb5js165eW8njvCj31GN8vmOjKlWpSlUjqvCqxU+WfpJIUJWfqMpPFqmijrCgwfchhTUTdXU8OqE2tDUdqlKVqlS1SFXYB611KyfBUV+wL9DHb6wmD7lVValKVaraqGqgJRmWAuEY4Xn32VJpsqa8fkJVqUpVqlqtisoIqDNTMxTWizfpCuNDx+4hUJWqVKWq1aqoogev2PpqLzx2p+4n1BA+/IVBUJWqVKWqRaoGbo6KsMOaiQr08eqQAkfl5smDpCpVqUpVi1SFc9ZXclGq8JyaakXjHYvwzOFAqUpVqlLVA1T1LZhrdQP1y9TVa/LCOGPgqD2HqlKVqlS1VxVV/fS9y/Hsg+p/42UZHg1QD62qVKUqVX2tKmqwqG8S5uYDS/GwOqSKy3AuCudRlapUpapFqvDFJ15A1NJtqpN9tgijOtBje7BUpSpVqWqRqr4FPJXahwE61YqmVIV7sPBwnA2AVKUqVanqGaoG3tNhRjCwhMa9Up2G0CulXFWqUpWqHqBqcsXbNxBhtVEL0KkNUn3Pc1i/Xj+zqlSlKlUtUnU2LKB2Ux2pdQZayLgzKnSod5dVpSpVqWq5KrzDOlDQUCEINdN4P75vKsk9C6pSlapUdWNVePUzwAIfNbz/HX5T/FpNHXpVqUpVqlqkqq89TJUdfXnE5IOEL/v7rpVkTKpSlapUtUhVSCdsD1NRLw43VE6NalLi/HT+P2GyWleVqlSlqtOqkJOWm8Fh/o63vcNmMF4P4Q9kSPlqd1lVqlKVqjaowlehVF1Fdanx52eyyT2Q0SOPsapUpSpVbVRVm4++FS9Op68xsCg37248q0pVqlLVU1WFW3CStuXAiKyoh/pSA6QpoipVqUpVq1V99AqnNmOFKTk15fg3xUsuahDCLsLH3WVVqUpVqrqfKuo9TRUilBi8PsMLkb6Bwvvx1yWoSlWqUtUiVVRjdXJn0sD+KuqbUrvEBq6FJEqqUpWqVLVIFb4mx0NtfIbwv5qc+/Ba1Jz+789VpSpVqeoZqvDEGY+5KUN9zYPJjCCcC0SnqlSlKlWtVlXTgI81lXT07bg620vGKSORkKpUpSpVPUMV3lht+ibl9f9AIkAJrl2rRjm5hKpUpSpVLVIVLn1f/cdkMxgvjKgmLl5uhv8u/JKtq0pVqlLVKlXhi/bs+x7P8amO70CroC90KNTKqlKVqlS1SFVtpicDa3xxjgcKeG7eF9aHj01Ltq4qValKVYdUhaUAtTgfCLVr6T9VSuJt76T6AatnValKVap6gKq+Fz+1qA4rvyPnoZKOgdor7FioSlWqUtVeVeF7+mxkfBZ3rSgMB4EacLZIVZWqVKWqRar63sp90cDAHYbL9cneA97Or3FXlapUpaq9qvApR1aqrQvmPh94M5gKdxIxV0ZDVapSlaoWqaKmvK8dOxmg45MXBhx4At7NVFWqUpWqnqEq3PNUq7SoLUphCTiZXFOVX19Jev1+VKUqValqoypqDYzXTHjoEMKlzkM9q1QfPYSrKlWpSlUPUEWJoXYvTU4nlUcMhPV43xrpRqhKVapS1SJV4dIXL8LwlTOeaxxh2tfApm5DVapSlarWqZqsP/patrUz963b+zZahXUeNc6qUpWqVPUkVWGtgw8oVcyFacjAozWZreNVr6pUpSpVPUBVGMj29S8pcAMdAioKD531lWWqUpWqVKWq2q30zSv+bNTuuU8n1X3vvrqqVKUqVS1SFc5i34j0zUf4bIQ5fl/X/Mi2AFWpSlWq2quqVkWFpRI+MX05NX7RgZiGYloYFlWpSlWqWqRqcuk72YqmfIQbksIqszbltV9G+taqUpWqVLVRFbVJKFmX/jRs6qK+BVW13PZHyJyqSlWqUtUiVcjbNF/SU8v1vvU/Hl6ElO+5G0BVqlKVqjaqCuuPpqwWjKfxqq7Wu53sf4d1Z+FJUJWqVKWq1arCUiAMkdntPq2NZ2oBP1CWUenMr5+oSlWqUtUXqqqlBgOdY6q2oLIGqkMQtvzxclNVqlKVqlSF0wlHra+Gw1sOOB28Wj1WV6lKVapS1YiqWszdt/6nqrq+DKXv+cGv1XeHqlKVqlS1V9XZNJmKwvta41R7+KyzWpl4PfJQlapUpapFqjw8wENVHvzxB9n66vzMepmGAAAAAElFTkSuQmCC'

res=base64.b64decode(s)
print(res)
with open('a.jpg','wb') as f:
    f.write(res)

posted on 2024-08-02 21:24  silence^  阅读(243)  评论(0编辑  收藏  举报

导航