DRF中UserActivation ApiView调用报错:未提供认证凭证
问题描述
我编写了一个用于激活用户的UserActivationView(继承自APIView):
class UserActivationView(APIView): authentication_classes = ([]) permission_classes = [AllowAny] """ Intermediate view to activate a user's email. """ def get (self, request, uid, token): protocol = 'https://' if request.is_secure() else 'http://' web_url = protocol + request.get_host() post_url = web_url + "/auth/users/activate/" post_data = {'uid': uid, 'token': token} result = requests.post(post_url, data = post_data) content = result.text return Response(content)
通过Djoser发送邮件中的链接访问该视图时,返回以下错误:
HTTP 200 OK Allow: GET, HEAD, OPTIONS Content-Type: application/json Vary: Accept "{"detail":"Authentication credentials were not provided."}
相关配置如下:
用户应用路由
path('activate-user/<str:uid>/<str:token>/', views.UserActivationView.as_view()),
全局URL配置
# Register API apipatterns = [ path('', include('activities.urls')), path('', include('social_auth.urls')), path('', include('users.urls')), ] urlpatterns = [ path('admin/', admin.site.urls), path('api/v1/', include(apipatterns)), path('auth/', include('djoser.urls')), path('auth-token/', include('djoser.urls.authtoken')), re_path(r'^$', views.index, name='index'), ]
DRF配置
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.TokenAuthentication', 'rest_framework.authentication.BasicAuthentication', ), 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', 'rest_framework.permissions.AllowAny', ], 'DEFAULT_FILTER_BACKENDS': ( 'django_filters.rest_framework.DjangoFilterBackend', ), }
请问该如何解决这个认证错误?
解决方案
1. 修正全局DRF权限配置
你的全局DEFAULT_PERMISSION_CLASSES同时配置了IsAuthenticated和AllowAny,DRF会要求用户满足所有权限类的要求,这就导致匿名用户无法通过IsAuthenticated的检查,进而拦截了Djoser的激活接口(本应允许匿名访问)。
修改DRF配置,移除矛盾的权限类:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.TokenAuthentication', 'rest_framework.authentication.BasicAuthentication', ), 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], 'DEFAULT_FILTER_BACKENDS': ( 'django_filters.rest_framework.DjangoFilterBackend', ), }
2. 明确配置Djoser的匿名权限
在settings.py中添加Djoser配置,确保激活等需要匿名访问的接口权限正确:
DJOSER = { 'ACTIVATION_URL': 'activate-user/{uid}/{token}/', 'PERMISSIONS': { 'activation': ['rest_framework.permissions.AllowAny'], 'password_reset': ['rest_framework.permissions.AllowAny'], 'password_reset_confirm': ['rest_framework.permissions.AllowAny'], 'user_create': ['rest_framework.permissions.AllowAny'], 'token_create': ['rest_framework.permissions.AllowAny'], # 其他需要认证的接口保持默认配置 'set_password': ['rest_framework.permissions.IsAuthenticated'], 'user_delete': ['rest_framework.permissions.IsAuthenticated'], } }
3. 优化UserActivationView逻辑(可选但推荐)
无需通过外部HTTP请求调用Djoser接口,直接复用Djoser的激活逻辑更高效可靠:
from djoser.views import ActivationView from rest_framework.response import Response class UserActivationView(APIView): authentication_classes = [] permission_classes = [AllowAny] def get(self, request, uid, token): # 复用Djoser的激活视图逻辑 activation_view = ActivationView.as_view() # 构造POST请求对象 post_request = request._request post_request.method = 'POST' post_request.POST = {'uid': uid, 'token': token} # 调用激活逻辑并返回结果 response = activation_view(post_request) return Response(response.data, status=response.status_code)
4. 验证路由匹配
确保Djoser的ACTIVATION_URL配置与你的用户应用路由完全一致,避免链接跳转错误。
完成以上配置后,再次访问邮件中的激活链接即可正常完成用户激活,不会再出现认证错误。
内容的提问来源于stack exchange,提问作者B. Mohammad
相关产品推荐
相关产品推荐

