34.django使用jwt
1.jwt
这里是打包的代码地址jwt代码包
json web token:用于用户认证(前后端分离/微信小程序/app开发)
- 基于传统的token认证
用户登录,服务端给返回token,并将token(服务端不保存)
以后用户再来访问时,需要携带token,服务端获取token后,再去数据库中获取token
- jwt
用户登陆之后,服务端给用户返回一个token(服务器不保存)
以后用户访问,都需要带着token,服务器获取token后,通过算法进行token验证
优势:相较于传统的token相比,他无需在服务端保存token
2.jwt实现过程
1.提交用户名和密码给服务端,如果登录成功,使用jwt生成一个token值,并返回给用户
注意:jwt生成的token是由三段字符串通过.连接起来的
第一段字符串:HEADER,内部包含算法token类型。
json转化成字符串,然后做base64url加密(base64加密;+-\)
{
"alg": "HS256",
'type': "JWT"
}
第二段字符串:payload,自定义值:
json转化成字符串,然后做base64url加密(base64加密;+-\)
{
'id': "124124",
'name':'chengge',
'exp': '1423434132',# 超时时间
}
第三段字符串:
第一步:将第1,2不封密文拼接起来
第二步:对前两部分密文进行hs256加密+加盐
第三步:对hs256加密后的密文在做base64url加密
- 以后用户来访问时候,携带token,后端需要对token进行校验
- 获取token
- 第一步:对token进行切割
- 第二步:把第二段进行base64解密,并获取payload信息,检测超市时间
- 第二步:把第一个段拼接再次执行hs256加密+加盐
密文 = base64解密
如果密文相等表示token没有被修改过
3.应用
pip install pyjwt
pyjwt.encode 生成token
pyjwt.decode token解密
4.扩展
pip install djagnrestframework-jwt
djagnrestframework-jwt 本质上是调用pyjwt实现的
版本一:
原理就是服务端保存tokne
class LoginView(APIView):
'''用户登录'''
def post(self, request, *args, **kwargs):
username = request.data.get("username")
passwork = request.data.get("password")
user_obj = models.UserInfo.objects.filter(username=username, password=passwork).first()
if not user_obj:
return Response({"code": 1000, 'error': '用户名或密码错误'})
random_string = str(uuid.uuid4())
user_obj.token = random_string
user_obj.save()
return Response({"code":1001, 'data': '登陆成功'})
class OrderView(APIView):
def get(self, request, *args, **kwargs):
token = request.query_params.get("token")
print(token)
if not token:
Response({"code": 1003, 'error': '未登录失败'})
user_obj = models.UserInfo.objects.filter(token=token).exists()
if not user_obj:
Response({"code": 1003, 'error': '未登录失败'})
return Response("订单列表")
版本二:
通过jwt进行验证,但是发现每个函数都要使用太麻烦了
class JwtLoginView(APIView):
'''用户登录'''
def post(self, request, *args, **kwargs):
username = request.data.get("username")
passwork = request.data.get("password")
user_obj = models.UserInfo.objects.filter(username=username, password=passwork).exists()
if not user_obj:
return Response({"code": 1000, 'error': '用户名或密码错误'})
import jwt
import datetime
salt = "fadsf$@%#%#%gsfdgsdgfd"
headers = {
"typ": "jwt_",
"alg": "HS256",
}
payload = {
"user_id": 1,
"username": "alex",
"exp": datetime.datetime.utcnow() + datetime.timedelta(minutes=1)
}
token = jwt.encode(payload=payload, key=salt, headers=headers).decode("utf-8")
return Response({"code":1001, 'data': token})
class JwtOrderView(APIView):
def get(self, request, *args, **kwargs):
# 获取token并验证
token = request.query_params.get("token")
import jwt
from jwt import exceptions
result = None
msg = None
salt = "fadsf$@%#%#%gsfdgsdgfd"
try:
result = jwt.decode(token, salt, True)
except exceptions.ExpiredSignatureError:
msg = "token失效"
except exceptions.DecodeError:
msg = "token认证失败"
except exceptions.InvalidTokenError:
msg = "非法token"
if not result:
return Response({"code": 1002, "msg": msg})
return Response("订单列表")
版本三:
使用restful的认证组件认证
class PrLoginView(APIView):
authentication_classes = []
def post(self, request, *args, **kwargs):
username = request.data.get("username")
passwork = request.data.get("password")
user_obj = models.UserInfo.objects.filter(username=username, password=passwork).first()
if not user_obj:
return Response({"code": 1000, 'error': '用户名或密码错误'})
payload = {
"id": user_obj.pk,
"name": user_obj.username,
}
token = get_token(payload, 5)
return Response({"code": 1001, 'data': token})
class PrOrderView(APIView):
# authentication_classes = [JwtQuertParamsAuthentication]
def get(self, request, *args, **kwargs):
return Response("订单列表")
# get_token函数
import jwt
import datetime
from django.conf import settings
def get_token(payload, timeout):
salt = settings.SECRET_KEY
headers = {
"typ": "jwt_",
"alg": "HS256",
}
payload["exp"] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout)
token = jwt.encode(payload=payload, key=salt, headers=headers).decode("utf-8")
return token
实现一个restframework的认证类,将它应用到视图函数之中就可以了
import jwt
from jwt import exceptions
from rest_framework.authentication import BaseAuthentication
from django.conf import settings
from rest_framework.exceptions import AuthenticationFailed
class JwtQuertParamsAuthentication(BaseAuthentication):
def authenticate(self, request):
token = request.query_params.get("token")
salt = settings.SECRET_KEY
try:
result = jwt.decode(token, salt, True)
except exceptions.ExpiredSignatureError:
msg = "token失效"
raise AuthenticationFailed({"code": 1001, "msg": msg})
except exceptions.DecodeError:
msg = "token认证失败"
raise AuthenticationFailed({"code": 1002, "msg": msg})
except exceptions.InvalidTokenError:
msg = "非法token"
raise AuthenticationFailed({"code": 1003, "msg": msg})
return (result, token)
# 三种操作
# 1.抛出错误,后续不再执行
# 2.return一个元组,(1,2)认证通过,在视图中如果调用request.user 就是第一个值request.auth就是第二个
# 3.None不做任何操作
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步