一、OAuth2 核心流程解析

1. 授权码模式流程

Client Backend WeChat 请求微信登录入口 返回微信授权URL 用户授权登录 返回授权码(code) 提交授权码 用code换access_token 返回用户信息 签发JWT令牌 Client Backend WeChat

2. 微信开放平台准备

  1. 注册微信开放平台账号
  2. 创建网站应用获取 AppIDAppSecret
  3. 配置授权回调域名(如 yourdomain.com/api/auth/wechat/callback

二、DRF 集成方案实现

1. 安装依赖库

pip install social-auth-app-django python-social-auth

2. 基础配置

# settings.py
INSTALLED_APPS = [
    ...
    'social_django',
    'rest_framework_simplejwt',
]

AUTHENTICATION_BACKENDS = [
    'social_core.backends.weixin.WeixinOAuth2',
    'django.contrib.auth.backends.ModelBackend',
]

SOCIAL_AUTH_WEIXIN_KEY = 'wx1234567890'       # 微信AppID
SOCIAL_AUTH_WEIXIN_SECRET = 'abcdefghijk123'  # 微信AppSecret
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'          # 前端回调地址

3. URL 路由配置

# urls.py
from django.urls import include, path
from .views import WechatCallbackView, WechatLoginView

urlpatterns = [
    path('api/auth/', include('social_django.urls', namespace='social')),
    path('api/auth/wechat/login/', WechatLoginView.as_view()),
    path('api/auth/wechat/callback/', WechatCallbackView.as_view()),
]

三、核心功能开发

1. 微信登录入口视图

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from social_django.utils import psa

class WechatLoginView(APIView):
    def get(self, request):
        auth_url = reverse('social:begin', args=('weixin',))
        full_url = request.build_absolute_uri(auth_url)
        return Response({'authorization_url': full_url})

2. 回调处理与令牌生成

class WechatCallbackView(APIView):
    @psa('social:complete')
    def get(self, request):
        # 自动完成OAuth2流程
        user = request.backend.do_auth(request.GET.get('code'))
        
        # 生成JWT
        from rest_framework_simplejwt.tokens import RefreshToken
        refresh = RefreshToken.for_user(user)
        
        return Response({
            'access': str(refresh.access_token),
            'refresh': str(refresh),
            'user_id': user.id
        })

3. 用户模型扩展

# models.py
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    wechat_openid = models.CharField(max_length=64, unique=True)
    nickname = models.CharField(max_length=64, blank=True)
    avatar = models.URLField(blank=True)

四、前端对接示例

1. 发起授权请求

// 获取微信登录入口
fetch('/api/auth/wechat/login/')
  .then(res => res.json())
  .then(data => {
    window.location.href = data.authorization_url
  })

2. 处理回调(SPA示例)

// 解析URL中的code参数
const urlParams = new URLSearchParams(window.location.search)
const code = urlParams.get('code')

if(code) {
  fetch(`/api/auth/wechat/callback/?code=${code}`)
    .then(res => res.json())
    .then(data => {
      localStorage.setItem('access_token', data.access)
      // 跳转到主页
    })
}

五、安全增强方案

1. 防范 CSRF 攻击

# 限制state参数有效性
SOCIAL_AUTH_FIELDS_STORED_IN_SESSION = ['state']
SOCIAL_AUTH_SESSION_FIXATION = False

2. 敏感信息加密存储

# 使用django-fernet-fields加密字段
from fernet_fields import EncryptedCharField

class WechatConfig(models.Model):
    app_id = EncryptedCharField(max_length=64)
    secret = EncryptedCharField(max_length=128)

3. 访问令牌刷新机制

class TokenRefreshView(APIView):
    def post(self, request):
        refresh_token = request.data.get('refresh')
        try:
            token = RefreshToken(refresh_token)
            new_access = str(token.access_token)
            return Response({'access': new_access})
        except Exception as e:
            return Response({'error': '令牌无效'}, status=400)

六、调试与问题排查

1. 常见错误代码

错误码 含义 解决方案
40029 无效的授权码 检查code是否过期/重复使用
40163 code已被使用 确保code单次有效性
41008 缺少授权code参数 验证回调URL配置

2. 日志记录配置

LOGGING = {
    'loggers': {
        'social': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': False
        }
    }
}

七、扩展多平台登录

1. 统一接入层设计

class UnifiedAuthView(APIView):
    def post(self, request):
        provider = request.data.get('provider')  # wechat/github/google
        code = request.data.get('code')
        
        backend = load_backend(provider)
        user = backend.authenticate(code=code)
        
        # 生成统一JWT
        ...

2. 账户关联功能

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def link_account(request):
    provider = request.data['provider']
    code = request.data['code']
    
    # 执行关联逻辑
    request.user.social_auth.create(provider=provider, uid=wechat_openid)
    return Response({'status': 'success'})

八、最佳实践总结

1. 架构选择建议

场景 推荐方案
纯API服务 JWT + OAuth2授权码模式
混合Web应用 Session + 前端代理授权流程
多平台账户体系 统一用户ID + 社交账户关联表

2. 性能优化指标

  • 令牌验证响应时间 < 50ms
  • 第三方API调用失败率 < 0.1%
  • 用户信息缓存命中率 > 95%

通过本教程,您已掌握在DRF中集成微信等第三方登录的核心方法。建议参考以下资源深入优化:

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐