Django Google OAuth2回调报错:需添加哪个backend参数?
我正在开发集成RESTful API的Django项目,实现用户注册、登录及Google/Apple OAuth登录功能。当前Google OAuth2回调环节触发内部服务器错误,报错信息如下:
/accounts/google/login/callback/ Traceback (most recent call last):
File "/home/zaibe/Desktop/project2/env/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request) File "/home/zaibe/Desktop/project2/env/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs) TypeError: api_google_oauth2_callback() missing 1 required positional argument: 'backend' [17/Mar/2024 06:39:23] "GET /accounts/google/login/callback/?code=4%2F0AeaYSHADSCseU_Nkg2BMLc5P8UpfRRqCJUNRIAyHrcW_tX4uQDpPADdj5rTJRS8v6siZHw&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&prompt=consent HTTP/1.1" 500 65562
视图代码
from django.http import JsonResponse from django.contrib.auth import authenticate, login from django.views.decorators.csrf import csrf_exempt from .forms import UserRegistrationForm from .models import Profile from django.shortcuts import redirect from social_django.utils import psa import json from social_django.views import auth from django.views.generic import RedirectView from django.shortcuts import render def default_callback(request): return render(request, 'default_callback.html') @psa() def api_google_oauth2_login(request): backend = 'social_core.backends.google.GoogleOAuth2' return redirect('social:begin', backend=backend) @psa() def api_google_oauth2_callback(request): backend = 'social_core.backends.google.GoogleOAuth2' return auth(request, backend=backend) @csrf_exempt def api_user_login(request): if request.method == 'POST': # Retrieve raw JSON data from the request body data = json.loads(request.body) # Extract username and password from the JSON data username = data.get('username') password = data.get('password') if username is None or password is None: return JsonResponse({'error': 'Missing credentials'}, status=400) user = authenticate(request, username=username, password=password) if user is not None: login(request, user) return JsonResponse({'message': 'Authenticated successfully'}, status=200) else: return JsonResponse({'error': 'Invalid login'}, status=401) else: return JsonResponse({'error': 'Invalid request method'}, status=405) @csrf_exempt def api_user_register(request): if request.method == 'POST': form = UserRegistrationForm(request.POST) if form.is_valid(): new_user = form.save(commit=False) new_user.set_password(form.cleaned_data['password']) new_user.save() Profile.objects.create(user=new_user) return JsonResponse({'message': 'Registration successful'}, status=201) else: return JsonResponse({'error': form.errors}, status=400) else: return JsonResponse({'error': 'Invalid request method'}, status=405) class UserRedirectView(RedirectView): """ This view is needed by the dj-rest-auth-library in order to work the google login. It's a bug. """ permanent = False def get_redirect_url(self): return "http://127.0.0.1:8000/accounts/google/login/callback/" # Replace "redirect-url" with your actual redirect URL
URL配置代码
from django.urls import path, include from . import views urlpatterns = [ path('login/', views.api_user_login, name='api_user_login'), path('register/', views.api_user_register, name='api_user_register'), path('auth/', include('social_django.urls', namespace='social')), # Social authentication URLs # Add the following URLs for Google OAuth2 authentication path('google/login/', views.api_google_oauth2_login, name='api_google_oauth2_login'), path('google/login/callback/', views.api_google_oauth2_callback, name='api_google_oauth2_callback'), path('default-callback/', views.default_callback, name='default_callback'), # Remove trailing slash # Removed <str:backend> from the callback URL since it's not needed in this case # Add the redirect view URL path("~redirect/", view=views.UserRedirectView.as_view(), name="redirect"), ]
解决方案
报错核心原因是api_google_oauth2_callback函数未接收backend参数,但auth视图函数需要该参数,同时@psa()装饰器未正确注入backend。按以下两种方式之一修正即可:
方式一:通过装饰器固定注入backend(推荐)
直接给@psa装饰器指定Google OAuth2的backend路径,同时让函数保留backend参数位(设默认值避免报错):
@psa('social_core.backends.google.GoogleOAuth2') def api_google_oauth2_callback(request, backend=None): return auth(request, backend=backend)
该方式下,装饰器会自动注入指定的backend,无需URL传递参数,适配你当前的URL配置。
方式二:恢复URL中的backend参数
如果遵循social_django的默认逻辑,可将回调URL改回带<str:backend>的形式:
path('google/login/callback/<str:backend>/', views.api_google_oauth2_callback, name='api_google_oauth2_callback'),
同时调整视图函数接收backend参数:
@psa() def api_google_oauth2_callback(request, backend): return auth(request, backend=backend)
两种方式都能解决"missing 1 required positional argument: 'backend'"的错误,推荐第一种方式,因为你的场景是固定使用Google OAuth2,无需动态传入backend。
内容的提问来源于stack exchange,提问作者zaibe_.x

