JWT 登录与注销示例
1. 后端(Django + DRF)实现
安装依赖
首先,确保安装了 django-rest-framework
和 django-rest-framework-simplejwt
:
pip install djangorestframework
pip install djangorestframework-simplejwt
配置 settings.py
# settings.py
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework_simplejwt.token_blacklist', # 启用黑名单
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
...
}
SIMPLE_JWT = {
'AUTH_HEADER_TYPES': ('Bearer',),
}
创建视图(登录、注销)
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework import status
# 登录视图:获取 access 和 refresh token
class LoginView(APIView):
def post(self, request):
# 假设已经进行了用户名和密码的认证(这里只是示例,实际应用应使用用户验证逻辑)
username = request.data.get('username')
password = request.data.get('password')
# 模拟用户名密码验证(实际应用中应使用 Django 的认证系统)
if username == 'user' and password == 'password':
refresh = RefreshToken.for_user(username) # 为用户生成 refresh_token
return Response({
'access': str(refresh.access_token), # 返回 access_token
'refresh': str(refresh), # 返回 refresh_token
})
return Response({"error": "Invalid credentials"}, status=status.HTTP_400_BAD_REQUEST)
# 注销视图:将 refresh_token 加入黑名单
class LogoutView(APIView):
def post(self, request):
refresh_token = request.data.get('refresh')
try:
token = RefreshToken(refresh_token)
token.blacklist() # 黑名单化该 refresh_token
return Response(status=status.HTTP_205_RESET_CONTENT)
except Exception as e:
return Response({"error": "Invalid refresh token"}, status=status.HTTP_400_BAD_REQUEST)
#社交登录注销(social_django,是基于会话的)
from rest_framework.response import Response
from rest_framework.views import APIView
from django.contrib.auth import logout
from social_django.models import UserSocialAuth
class LogoutView(APIView):
def post(self, request):
# 注销当前用户
logout(request)
# 可选:删除社交平台的关联(如果需要)
for social_auth in UserSocialAuth.objects.filter(user=request.user):
social_auth.delete()
return Response({"message": "Logged out successfully"})
配置路由(urls.py)
# urls.py
from django.urls import path
from .views import LoginView, LogoutView
urlpatterns = [
path('api/login/', LoginView.as_view(), name='login'),
path('api/logout/', LogoutView.as_view(), name='logout'),
]
from django.urls import path
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
...,
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
2. 前端(Vue 3)实现
在前端,我们使用 axios
来处理 HTTP 请求,假设我们通过登录表单获取 username
和 password
,然后将 access_token
和 refresh_token
存储在 localStorage
。
安装 axios
npm install axios
登录函数
import axios from 'axios';
function login(username, password) {
axios.post('http://localhost:8000/api/login/', { username, password })
.then(response => {
const { access, refresh } = response.data;
// 存储 token
localStorage.setItem('access_token', access);
localStorage.setItem('refresh_token', refresh);
// 设置默认的 Authorization header
axios.defaults.headers.common['Authorization'] = `Bearer ${access}`;
console.log('Login successful!');
})
.catch(error => {
console.error('Login failed:', error.response.data);
});
}
注销函数
function logout() {
const refreshToken = localStorage.getItem('refresh_token');
axios.post('http://localhost:8000/api/logout/', { refresh: refreshToken })
.then(() => {
// 清除 token
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
// 清除 axios 默认 header
delete axios.defaults.headers.common['Authorization'];
console.log('Logout successful!');
})
.catch(error => {
console.error('Logout failed:', error.response.data);
});
}
3. 流程
- 登录:前端通过提供用户名和密码请求
/api/login/
,成功后获得access_token
和refresh_token
,并将其存储在localStorage
中。 - 注销:前端请求
/api/logout/
,将refresh_token
发送到服务器,后端将该refresh_token
加入黑名单,前端清除存储的 token。 - 请求认证:前端的后续请求需要携带
access_token
,后端通过Authorization
header 来验证用户身份。
4. 请求认证
在后续的 API 请求中,前端会将 access_token
放在请求头中以进行认证:
axios.get('http://localhost:8000/protected-endpoint/', {
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
})
.then(response => {
console.log('Authenticated request:', response.data);
})
.catch(error => {
console.error('Authentication failed:', error.response.data);
});
小结
- 登录:用户通过用户名和密码请求
POST /api/login/
,获取access_token
和refresh_token
。 - 注销:用户请求
POST /api/logout/
,将refresh_token
加入黑名单,前端清除 token。 - 请求认证:前端的后续请求需要携带
access_token
,后端通过Authorization
header 来验证用户身份。