我正在使用 Django OAuth 工具包并使用以下代码进行 OAuth 实现
import requests
from django.http import JsonResponse
from django.shortcuts import redirect, render
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from .forms import AuthenticationForm, UserProfileForm
from .models import UserProfile
from oauth2_provider.models import get_application_model
import base64
Application = get_application_model()
def oauth_login(request):
app = Application.objects.get(name="App")
#redirect_uri = request.GET.get("redirect_uri", "http://test.com:8000/callback")
#redirect_uri = request.GET.get("redirect_uri", "http://test.com:8002/malicious_redirect.html")
redirect_uri = request.POST.get("redirect_uri", "http://test.com:8002/malicious_redirect.html")
authorization_url = (
f"http://test.com:8000/o/authorize/?client_id={app.client_id}&response_type=code&redirect_uri={redirect_uri}"
)
return redirect(authorization_url)
def oauth_callback(request):
code = request.GET.get("code")
if not code:
return JsonResponse({'error': 'missing_code', 'details': 'Missing code parameter.'}, status=400)
token_url = "http://test.com:8000/o/token/"
client_id = Application.objects.get(name="App").client_id
client_secret = Application.objects.get(name="App").client_secret
#redirect_uri = request.GET.get("redirect_uri", "http://test.com:8002/callback")
redirect_uri = request.GET.get("redirect_uri", "http://test.com:8002/unique_redirect.html")
data = {
"grant_type": "authorization_code",
"code": code,
"redirect_uri": redirect_uri,
"client_id": client_id,
"client_secret": client_secret,
}
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': f'Basic {base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()}',
}
response = requests.post(token_url, data=data, headers=headers)
tokens = response.json()
print(tokens)
if response.status_code != 200:
return JsonResponse({'error': 'token_exchange_failed', 'details': tokens}, status=response.status_code)
request.session['access_token'] = tokens['access_token']
request.session['refresh_token'] = tokens['refresh_token']
return JsonResponse(tokens)
#return redirect('profile')
问题是,如果我使用超级用户凭据登录 OAuth 2.0 管理面板,上面的代码可以正常工作并重定向到提供的 URL。否则它不起作用并使用
LOGIN_REDIRECT_URL = '/profile/'
中的 settings.py
。
可能是什么原因?
希望你做得很好。我不是这方面的专家,也没有办法亲自测试这一点,但让我给您一些可能有助于解决问题的建议。
首先想到的是,Django OAuth 工具包有时会在允许重定向之前执行授权检查。因此,当您以超级用户身份登录时,您就拥有完全权限,这就是它起作用的原因。对于其他用户,可能无法通过此检查。
为了安全起见,您还应该确保您使用的
redirect_uri
完全匹配客户端应用程序有效重定向中列出的 URI 之一。
我认为这不会被忽略,但仍然检查用户是否具有特定的范围权限(如果您已经定义了范围)
哦,您还可以正确查看您可能已经完成的会话处理,因为当未以超级用户身份登录时,应用程序可能会丢失会话信息并默认为
LOGIN_REDIRECT_URL
我建议执行以下操作来查明问题:
在各个点记录
redirect_uri
,以确保其正确通过。
检查您的
settings.py
文件,确保 OAuth 工具包配置正确,并特别检查 OAUTH2_PROVIDER
设置。
您还可以考虑实现使用 Django 身份验证系统的自定义登录视图。
您可以尝试这样的操作,以检查非超级用户的流程到底在哪里中断:
@login_required
def oauth_login(request):
app = Application.objects.get(name="App")
redirect_uri = request.POST.get("redirect_uri", "http://test.com:8002/malicious_redirect.html")
print(f"User: {request.user}, Redirect URI: {redirect_uri}")
if not request.user.is_authenticated:
raise PermissionDenied("User must be authenticated")
print(f"Cleared authentication check.")
authorization_url = (
f"http://test.com:8000/o/authorize/?client_id={app.client_id}&response_type=code&redirect_uri={redirect_uri}"
)
print(f"Authorization URL: {authorization_url}")
return redirect(authorization_url)
作为最后的手段,您可以查看 Django OAuth Toolkit 的源代码,特别是
AuthorizationView
类,以了解它如何处理重定向和身份验证。
由于我无法亲自测试这些,我只能提供一些您可能已经尝试过的建议,如果这没有多大帮助,我深表歉意。
仍然祝你好运,并希望你能解决你的问题。 👍