下面是关于“django使用JWT保存用户登录信息”的完整攻略:
1. 什么是JWT?
JWT是一种用于身份认证的开放标准,它定义了一种紧凑且易于传输的方式,以便在网络应用和服务之间安全地传输信息。 JWT实际上就是由头部、载荷和签名组成的字符串。
- 头部(Header): 是一个JSON对象,用于描述JWT的元数据信息,例如Token的类型是JWT,签名算法是什么等等
- 载荷(Payload): 是一个JSON对象,用于存放实际需要传输的数据,例如用户ID、用户名、用户角色等等
- 签名(Signature): 是一个Token的防伪标志,由头部和载荷中的信息加密形成,确保Token在传输过程中不被篡改
2. JWT的优点
与传统的Session-Based认证方式相比,JWT具有以下优点:
- 开放标准:JWT是一个开放的标准,它并不依赖于任何语言或平台技术,任何编程语言均可方便的生成或解析JWT
- 无状态:对于一个JWT来说,它不需要存放在服务端,这也就意味着,可以在多个服务之间共享JWT
- 安全性:JWT采用了数字签名的方式,确保Token在传输过程中不被篡改,且只能被签署密钥持有者修改
3. Django如何使用JWT
在Django框架中,我们可以使用django-rest-framework-simplejwt
这个第三方库来实现基于JWT的身份认证。
3.1 安装django-rest-framework-simplejwt
库
在终端执行以下指令安装:
pip install djangorestframework_simplejwt
3.2 配置Django项目
在项目的settings.py
文件中添加以下配置:
INSTALLED_APPS = [
# ...
'rest_framework',
'rest_framework_simplejwt',
# ...
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': True,
}
3.3 编写Django视图函数
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken
from django.contrib.auth import authenticate
class LoginView(APIView):
def post(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
refresh = RefreshToken.for_user(user)
return Response({
'refresh': str(refresh),
'access': str(refresh.access_token),
})
else:
return Response(status=status.HTTP_401_UNAUTHORIZED)
在上述代码中,我们定义了一个可以处理POST请求的视图类LoginView
,当用户在前端输入用户名和密码提交请求时,后端通过authenticate
函数来进行用户校验,如果校验成功,则生成并返回Token给前端。
3.4 在前端存储Token
前端在接收到Token之后,将Token存储在本地,每次请求后端API时,都需要在请求的Header中附带Token信息。
// 存储Token
localStorage.setItem('access_token', response.data.access);
localStorage.setItem('refresh_token', response.data.refresh);
// 在Vue中使用axios来发起请求并附带Token
import axios from 'axios';
const instance = axios.create({
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
},
baseURL: 'http://localhost:8000'
});
3.5 在后端解析Token
我们可以通过以下代码来解析Token并获取载荷中的数据:
from rest_framework_simplejwt.authentication import JWTAuthentication
class UserInfoView(APIView):
authentication_classes = [JWTAuthentication]
def get(self, request):
user = request.user
user_id = user.id
username = user.username
return Response({
'id': user_id,
'username': username,
})
在上述代码中,我们定义了一个可以处理GET请求的视图类UserInfoView
,该视图类使用JWTAuthentication
进行身份认证,当请求被认证通过后,可以通过request.user
来获取已认证的用户对象,从而获取其中需要的信息并返回给前端。
至此,已经成功的完成了一个基于JWT的用户认证和授权功能。
4. 示例说明
4.1 基于JWT的Token生成和校验
from rest_framework_simplejwt.tokens import RefreshToken
from django.contrib.auth import get_user_model
UserModel = get_user_model()
user = UserModel.objects.get(username='foo')
# 生成Token
refresh = RefreshToken.for_user(user)
access_token = str(refresh.access_token)
refresh_token = str(refresh)
print(f'access_token: {access_token}')
print(f'refresh_token: {refresh_token}')
# 校验Token
try:
payload = RefreshToken(token=refresh_token).payload
user_id = payload['user_id']
exp = payload['exp']
print(f'user_id: {user_id}, exp: {exp}')
except Exception:
print('Token校验失败')
在上述代码中,我们获取一个用户对象,通过RefreshToken.for_user
方法来生成Token,然后通过str
函数将Token转换为字符串格式,如果要校验Token,则需要将Token字符串传给RefreshToken
类的构造函数,解析出其中Payload并获取其中的数据。
4.2 在Django中使用JWT鉴权
from rest_framework.decorators import api_view, permission_classes, authentication_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.response import Response
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def hello_world(request):
return Response({'message': 'Hello World!'})
在上述代码中,我们定义了一个使用JWT进行鉴权的视图函数hello_world
,为了让该视图函数需要进行鉴权,我们指定了IsAuthenticated
权限,即只有经过身份认证的用户才可以访问该视图函数。同时,我们在视图函数的装饰器中指定了JWTAuthentication
来进行身份认证,表示只有持有有效的Token的用户才有权限访问该视图函数。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:django使用JWT保存用户登录信息 - Python技术站