基于DRF微服务架构:跨项目访问用户模型及CAS实现咨询
解决方案:为DRF微服务搭建中央认证系统(CAS)
既然你已经有了基于OAuth2的users认证服务,我们可以直接把它扩展为中央认证核心,让products服务通过标准化的API交互获取用户信息——这才是微服务架构里的正确姿势,而非直接跨服务访问数据库模型。下面是适配你现有环境的具体实现步骤:
1. 优化Users服务作为CAS核心
首先要确保users服务不仅能处理登录认证,还能安全提供用户信息接口,并配置为OAuth2资源服务器验证其他服务的请求合法性。
1.1 配置OAuth2资源服务器
在users项目的settings.py中补充资源服务器相关配置:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', 'rest_framework.authentication.SessionAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ] } OAUTH2_PROVIDER = { 'ACCESS_TOKEN_EXPIRE_SECONDS': 3600, # 按需调整token过期时间 'AUTHORIZATION_CODE_EXPIRE_SECONDS': 600, 'SCOPES': {'read': 'Read scope', 'openid': 'User info scope'}, 'ALLOWED_REDIRECT_URI_LIST': ['http://localhost:8001/callback'], # 添加products服务的回调地址 }
1.2 暴露标准化用户信息API
在users项目中新增视图,返回当前认证用户的核心信息:
# users/views.py from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from django.contrib.auth.models import User class UserInfoView(APIView): permission_classes = [IsAuthenticated] def get(self, request): user = request.user return Response({ 'id': user.id, 'username': user.username, 'email': user.email, # 按需添加其他需要共享的用户字段 })
然后在urls.py中注册这个接口:
# users/urls.py from django.urls import path from .views import UserInfoView urlpatterns = [ # 已有的OAuth2路由(比如/login、/o/token/等)... path('auth/user-info/', UserInfoView.as_view(), name='user-info'), ]
2. 配置Products服务作为OAuth2客户端
让products服务通过OAuth2客户端模式(适合服务间后台调用)获取access token,再用token调用users服务的用户信息接口。
2.1 安装依赖
在products项目中安装OAuth2相关工具:
pip install requests django-oauth-toolkit
2.2 添加客户端配置
在products项目的settings.py中添加OAuth2客户端的连接信息:
# products/settings.py OAUTH2_CLIENT = { 'CLIENT_ID': '你的users服务OAuth2客户端ID', # 在users服务的Django后台创建OAuth2应用时生成的ID 'CLIENT_SECRET': '你的users服务OAuth2客户端密钥', # 对应应用的密钥 'TOKEN_URL': 'http://localhost:8000/o/token/', 'USER_INFO_URL': 'http://localhost:8000/auth/user-info/', }
2.3 实现用户信息获取工具
创建工具函数封装token获取和用户信息请求逻辑:
# products/utils.py import requests from django.conf import settings from django.core.cache import cache def get_access_token(): # 先从缓存取token,避免重复请求 token = cache.get('oauth2_access_token') if token: return token # 客户端模式获取新token data = { 'grant_type': 'client_credentials', 'client_id': settings.OAUTH2_CLIENT['CLIENT_ID'], 'client_secret': settings.OAUTH2_CLIENT['CLIENT_SECRET'], 'scope': 'read', } response = requests.post(settings.OAUTH2_CLIENT['TOKEN_URL'], data=data) if response.status_code == 200: token_data = response.json() # 缓存token直到过期 cache.set('oauth2_access_token', token_data['access_token'], token_data['expires_in'] - 60) return token_data['access_token'] return None def get_user_info(access_token): headers = {'Authorization': f'Bearer {access_token}'} response = requests.get(settings.OAUTH2_CLIENT['USER_INFO_URL'], headers=headers) if response.status_code == 200: return response.json() return None
2.4 在Products业务视图中使用用户信息
比如在你的getProduct视图中,需要关联用户信息时调用上述工具:
# products/views.py from rest_framework.views import APIView from rest_framework.response import Response from .utils import get_access_token, get_user_info class GetProductView(APIView): def get(self, request, product_id): # 获取服务间调用的access token service_token = get_access_token() if not service_token: return Response({'error': '认证服务连接失败'}, status=500) # 如果需要验证当前请求的用户,从请求头拿前端传来的用户token user_token = request.headers.get('Authorization', '').split(' ')[-1] user_info = get_user_info(user_token) # 处理产品业务逻辑,比如关联用户ID product_data = { 'id': product_id, 'name': '示例产品', 'creator_id': user_info.get('id') if user_info else None } return Response(product_data)
3. 关键注意事项
- 跨域配置:在
users服务中允许products服务的跨域请求,安装django-cors-headers并配置:# users/settings.py INSTALLED_APPS = [ # ... 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # ... ] CORS_ALLOWED_ORIGINS = [ "http://localhost:8001", ] - 安全强化:生产环境必须使用HTTPS传输token;限制OAuth2客户端的权限范围(比如只给
read权限);定期轮换客户端密钥。 - 容错处理:在
products服务中添加token获取失败的降级逻辑,避免认证服务不可用时导致产品服务完全瘫痪。
4. 测试验证
- 启动
users和products服务 - 调用
products的/products/getProduct/1接口,检查是否能正确获取并返回关联的用户信息 - 测试token过期后,工具函数是否能自动重新获取有效token
内容的提问来源于stack exchange,提问作者Mohammed Sameer
相关产品推荐
相关产品推荐

