jwt认证介绍和原理
jwt介绍:Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。我们不再使用Session认证机制,而使用Json Web Token(本质就是token)认证机制。
jwt工作原理:
jwt的构成:
jwt就是一端字符串,有三段信息构成的,将三段信息文本使用.符号链接
在一起就构成了jwt
eg:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
第一部分:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
称之为头部 header
第二部分:eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSIaG4gRG9lIiwiYWRtaW4iOnRydWV9.
称之为载荷(承载的信息)payload
第三部分:TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
称之为签证signature
头部header 承载两部分信息:
- 说明类型 jwt
- 说明使用的加密算法 通常使用HMAC SHA256
完整头部就像下面的json:
'typ': 'JWT',
'alg': 'HS256'
头部就是有这个json 加上 base64方法编码得到的,通过解码可以还原
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
载荷payload,就是存放有效信息的地方包含3个部分
- 标准注册声明
- 公共的声明
- 私有的声明
标准中注册的声明 (建议但不强制使用) :
- iss: jwt签发者
- sub: jwt所面向的用户 用户id
- exp: jwt的过期时间,这个过期时间必须要大于签发时间
- iat: jwt的签发时间
- jti: jwt的唯一身份标识,主要用来作为一次 性token,从而回避时序攻击。
- username:用户名
{
"sub": "1234567890",
"name": "John Doe",
"vip": false
}
例如我们定义一个payload,然后转换为json然后再使用base64编码就可以得到
a = {
"sub": "1234567890",
"name": "John Doe",
"vip": False
}
a = json.dumps(a)
res = base64.standard_b64encode(a.encode('utf8'))
print(res)
b'eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJIUzI1NiJ9'
# base64 应用场景
'''
1 jwt 使用了base64
2 网络中传输数据,也会经常使用 base64编码
3 网络传输中,有的图片使用base64编码
'''
s='iVBORw0KGgoAAAANSUhEUgAAAMcAAADHCAIAAAAiZ9CRAAAHC0lEQVR42u3dUXLjSAwEUd//0poDTIQloRLoBp389NgSxX4MVRcYuz8vDw/6+PESeHSp+smO397gv9/55Sf40Xcav/zVdwtQOuev3uuTV6bWQlWqUpWq9qqqXZHJTxKeT209vnr3Ph+196LAff46qlKVqlS1WhUVVvCkVXudr9Zj4B6jVvGr2w+Pm6pSlapUpao+H7VAg1906uRD07UXxN9CVapSlapUVaun8X17+IJ40zGw9iGCrblKVapSlapGVPWNLWu763CBKbgDMWiyNcCbDlWpSlWq2qtq8jEm'
# 这是一张图片被编写成了base64模式
res=base64.b64decode(s)
# 通过解码获得二进制数据
with open('a.png','wb') as f:
f.write(res)
同样我们得到载荷也可以转为json
b = base64.standard_b64decode(res)
b = json.loads(b)
print(b)
{'sub': '1234567890', 'name': 'John Doe', 'vip': False}
签名signature
就是第一部分和第二部分,然后通过秘钥加密方式得到的。也是base64
jwt一般应用于登录,当用户登录成功签发token,当用户再次来的时候基于签发的token做认证
jwt的快速使用
配置个路由即可,它会基于django原生的auth_user表去封装登录接口。
在django+drf 平台开发有2套jwt模块都是可以使用的
下载模块:
-djangorestframework-jwt
-djangorestframework-simplejwt 目前大多数公司使用
配置路由url:
from rest_framework_jwt.views import obtain_jwt_token
path('login/', obtain_jwt_token),
前端传入 username 和 password字段就可以判断了
判断通过会返回token
根据系统自带的auth_user表来验证,自己写的不支持快速使用
自定义签发token格式 登录成功
如果想要定制返回格式,让它不止有token字段,可以重写jwt_response_payload_handler,然后直接配置到字典中即可。
在app中创建一个新的py文件,在文件中重写
jwt_response_payload_handler方法
在django配置文件中添加默认配置
import datetime
JWT_AUTH = {
# 设置过期时间
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.jwt.jwt_response_payload_handler',
# 设置刚刚导入的自己重写的jwt_response_payload_handler方法
}
然后在app01.jwt.文件中重写jwt_response_payload_handler函数
def jwt_response_payload_handler(token, user=None, request=None):
return {'code':100,
'msg':'登录成功',
'token':token,
'username':user.username}
# 重新定义认证成功后要返回的数据内容
自定义认证类 再次登录验证
jwt内部有一个已经认证类
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
# 如果要使用jwt内置认证类,必要要搭配使用drf的权限类
# 因为jwt内置认证模块,如果你不带token他不做任何判断直接算你通过,只有你带了才会验证你的token
class BooksView(GenericViewSet, ListAPIView, CreateAPIView, ):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [JSONWebTokenAuthentication]
permission_classes = [IsAuthenticated]
# 这样才可以配合使用 首先判断你是否登录 其次判断你token是否正确
1.首先当你登录账号 账号密码正确后会返回一个 token给你
2 postman测试 -请求头中key值叫Authorization -请求头的value值是:jwt 有效的token值
# 已 jwt空格 +正确的token就可以访问正常的接口
完全自定义----------------------------------------------
标签:登录,签发,base64,jwt,认证,token,payload,drf
From: https://www.cnblogs.com/moongodnnn/p/17107074.html