首页
学习
活动
专区
圈层
工具
发布

使用带令牌的Google API [Django & AllAuth]

使用带令牌的Google API [Django & AllAuth] 综合指南

基础概念

在Django项目中使用Google API结合AllAuth认证系统,主要涉及以下几个核心概念:

  1. OAuth 2.0 - Google API使用的授权协议,允许用户授权第三方应用访问其Google账户信息而不暴露密码
  2. AllAuth - Django的多功能认证系统,支持多种社交账号登录(包括Google)
  3. 访问令牌 - OAuth流程完成后获得的凭证,用于访问受保护的API资源
  4. 刷新令牌 - 长期有效的令牌,用于获取新的访问令牌

优势

  1. 简化认证流程 - 用户可以使用Google账号快速登录
  2. 安全性高 - 无需处理密码存储和验证
  3. 访问Google服务 - 可以直接集成Gmail、Google Drive等API
  4. 用户友好 - 减少注册摩擦,提高转化率

配置步骤

1. 安装必要包

代码语言:txt
复制
pip install django-allauth google-auth google-auth-oauthlib google-api-python-client

2. 配置Django settings.py

代码语言:txt
复制
INSTALLED_APPS = [
    ...
    'django.contrib.sites',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.google',
    ...
]

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend'
]

SITE_ID = 1

# Google OAuth配置
SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'SCOPE': [
            'profile',
            'email',
            'https://www.googleapis.com/auth/drive.readonly',
            # 添加其他需要的scope
        ],
        'AUTH_PARAMS': {
            'access_type': 'offline',
        }
    }
}

3. 在Google开发者控制台创建项目

  1. 访问Google开发者控制台
  2. 创建新项目
  3. 启用"Google+ API"(现为People API)
  4. 创建OAuth 2.0客户端ID
  5. 配置授权重定向URI为http://yourdomain.com/accounts/google/login/callback/

4. 在Django Admin中添加Social Application

  1. 在Admin界面找到"Social Applications"
  2. 添加新的Social Application
  3. 选择Provider为"Google"
  4. 填写从Google开发者控制台获取的Client ID和Secret Key
  5. 选择适当的Sites

获取和使用访问令牌

获取令牌

用户通过AllAuth登录后,可以在视图中获取访问令牌:

代码语言:txt
复制
from allauth.socialaccount.models import SocialToken

def get_google_token(request):
    if request.user.is_authenticated:
        try:
            social_token = SocialToken.objects.get(
                account__user=request.user, 
                account__provider='google'
            )
            access_token = social_token.token
            refresh_token = social_token.token_secret
            # 使用令牌访问Google API
            return access_token, refresh_token
        except SocialToken.DoesNotExist:
            return None, None
    return None, None

使用令牌访问Google API

代码语言:txt
复制
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build

def access_google_drive(request):
    access_token, refresh_token = get_google_token(request)
    if not access_token:
        return HttpResponse("未找到Google令牌", status=401)
    
    credentials = Credentials(
        token=access_token,
        refresh_token=refresh_token,
        token_uri='https://oauth2.googleapis.com/token',
        client_id=settings.SOCIALACCOUNT_PROVIDERS['google']['APP']['client_id'],
        client_secret=settings.SOCIALACCOUNT_PROVIDERS['google']['APP']['secret']
    )
    
    try:
        service = build('drive', 'v3', credentials=credentials)
        results = service.files().list(
            pageSize=10, fields="nextPageToken, files(id, name)").execute()
        items = results.get('files', [])
        
        if not items:
            return HttpResponse("Google Drive中没有找到文件")
        else:
            return render(request, 'drive_files.html', {'files': items})
    except Exception as e:
        return HttpResponse(f"访问Google Drive出错: {str(e)}", status=500)

常见问题及解决方案

1. 令牌过期问题

原因: 访问令牌通常有1小时的有限生命周期

解决方案:

  • 确保在SOCIALACCOUNT_PROVIDERS配置中设置了'access_type': 'offline'以获取刷新令牌
  • 使用刷新令牌获取新的访问令牌
代码语言:txt
复制
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials

def refresh_access_token(refresh_token):
    credentials = Credentials(
        None,
        refresh_token=refresh_token,
        token_uri='https://oauth2.googleapis.com/token',
        client_id=settings.SOCIALACCOUNT_PROVIDERS['google']['APP']['client_id'],
        client_secret=settings.SOCIALACCOUNT_PROVIDERS['google']['APP']['secret']
    )
    
    credentials.refresh(Request())
    return credentials.token

2. 权限不足错误

原因: 请求的scope未包含在初始授权中

解决方案:

  • 确保所有需要的scope都包含在SOCIALACCOUNT_PROVIDERS配置中
  • 可能需要让用户重新授权

3. 用户取消授权后的问题

解决方案:

  • 捕获特定异常并引导用户重新授权
  • 实现令牌失效检测机制
代码语言:txt
复制
from google.auth.exceptions import RefreshError

try:
    # 尝试使用令牌
except RefreshError:
    # 令牌失效,引导用户重新登录
    return redirect('socialaccount_login', provider='google')

高级应用场景

1. 后台任务中使用Google API

代码语言:txt
复制
from django.core.cache import cache
from allauth.socialaccount.models import SocialToken
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from celery import shared_task

@shared_task
def process_google_drive_files(user_id):
    try:
        social_token = SocialToken.objects.get(
            account__user_id=user_id, 
            account__provider='google'
        )
        
        credentials = Credentials(
            token=social_token.token,
            refresh_token=social_token.token_secret,
            token_uri='https://oauth2.googleapis.com/token',
            client_id=settings.SOCIALACCOUNT_PROVIDERS['google']['APP']['client_id'],
            client_secret=settings.SOCIALACCOUNT_PROVIDERS['google']['APP']['secret']
        )
        
        service = build('drive', 'v3', credentials=credentials)
        # 执行后台任务...
        
    except SocialToken.DoesNotExist:
        # 处理令牌不存在的情况
        pass

2. 多账户集成

对于需要访问多个Google账户的情况,可以扩展模型存储多个令牌:

代码语言:txt
复制
from django.db import models
from django.contrib.auth.models import User

class GoogleAccount(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    email = models.EmailField()
    access_token = models.TextField()
    refresh_token = models.TextField()
    expires_at = models.DateTimeField()
    
    def is_expired(self):
        from django.utils import timezone
        return self.expires_at <= timezone.now()

安全最佳实践

  1. HTTPS - 始终在生产环境使用HTTPS
  2. 令牌存储 - 确保数据库中的令牌加密存储
  3. 最小权限原则 - 只请求必要的scope
  4. 令牌刷新 - 定期检查并刷新即将过期的令牌
  5. 错误处理 - 妥善处理各种API错误情况

通过以上配置和代码示例,您可以在Django项目中成功集成带令牌的Google API,并利用AllAuth简化用户认证流程。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

没有搜到相关的视频

领券