如何让Django应用作为OAuth2资源所有者接收第三方令牌XHR请求?
嘿,刚好我之前折腾过类似的场景,给你梳理下具体的实现思路和步骤,帮你把Django从OAuth2登录客户端变成资源服务器:
首先得明确:python-social-auth主要负责的是让你的Django对接第三方社交平台,完成用户登录(也就是OAuth2客户端角色)。而要让Django成为资源所有者,开放受保护的API给SPA这类应用调用,得结合一些额外的配置或者工具库,下面分情况给你说:
1. 选对令牌验证的方案
方案A:让Django自己发令牌、验令牌
如果你的SPA需要先从Django拿到合法令牌(比如用户先通过社交登录到Django,再由Django给SPA发令牌),推荐用django-oauth-toolkit来搭OAuth2服务端:
- 先装依赖:
pip install django-oauth-toolkit - 在
INSTALLED_APPS里加oauth2_provider - 配置URL路由,添加上OAuth2的核心端点(比如令牌获取、验证的接口)
- 给你的API视图加保护:要么继承
oauth2_provider.views.generic.ProtectedResourceView,要么用@oauth2_provider.decorators.protected_resource()装饰器
方案B:直接验证第三方社交平台的令牌
如果你的SPA已经拿着用户的第三方令牌(比如Google的ID Token),那可以直接用python-social-auth的能力来验证这个令牌,找到对应的Django用户:
- 可以利用对应社交后端的
validate_token方法,比如Google的后端:
from social_core.backends.google import GoogleOAuth2 from social_core.exceptions import AuthTokenError from django.contrib.auth.models import User def check_social_token(token): backend = GoogleOAuth2() try: # 验证令牌并拿到用户信息 user_info = backend.validate_token(token) # 通过社交登录时绑定的邮箱找到Django用户 user = User.objects.get(email=user_info.get('email')) return user except (AuthTokenError, User.DoesNotExist): # 令牌无效或者找不到对应用户 return None
然后在你的API视图里,从请求头(比如Authorization: Bearer <token>)取出令牌,调用这个函数验证,通过了再处理业务逻辑就行。
2. 给API加上保护
不管用哪种方案,都得确保只有带有效令牌的请求才能访问你的API:
- 如果用Django REST Framework(DRF),可以配合
django-oauth-toolkit的DRF扩展,把OAuth2Authentication设为默认认证类:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', ), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) }
- 如果不用DRF,就自己写个装饰器,在视图函数开头做令牌验证,没通过就返回401 Unauthorized。
3. 别忘了处理跨域(CORS)
因为是SPA通过XHR调用,跨域是绕不开的问题,得配置Django允许跨域请求:
- 装
django-cors-headers:pip install django-cors-headers - 在
INSTALLED_APPS加corsheaders,然后在MIDDLEWARE里把corsheaders.middleware.CorsMiddleware放在django.middleware.common.CommonMiddleware前面 - 生产环境别乱开全局允许,指定你的SPA域名:
CORS_ALLOWED_ORIGINS = ["https://your-spa-domain.com"],开发环境可以临时开CORS_ALLOW_ALL_ORIGINS = True
4. 衔接已有的社交登录用户体系
你已经用python-social-auth实现了社交登录,用户数据都存在Django的用户表里了,所以不管哪种方案,最终都要把令牌验证和已有的用户记录关联起来,确保权限控制一致。比如方案A里,用户社交登录后可以自动或手动申请令牌;方案B里,验证第三方令牌后直接关联到之前社交登录创建的用户。
内容的提问来源于stack exchange,提问作者Yogesh Sajanikar

