我有一个架构问题。我正在使用Django(使用管理面板)和DRF(使用JWT进行无状态身份验证的api)。
Django具有由模型表示的Admin用户,它与默认的Django用户模型大致相同。管理员仅使用Django Admin,不能使用DRF api。
DRF的API用户只允许通过DRF使用api,不能与Django Admin或Django Session等交互。
我知道最好的方法是使用多模型继承,例如:
class User(DjangoUserModel):
pass
class Admin(User):
pass
class API(User):
pass
AUTH_USER_MODEL = "User"
但问题是,这些用户完全不同。例如:API用户具有复杂的复合键作为用户名字段,这与简单的Admin
用户名字段无法组合。还有很多其他的差异。 ..
问题是:我可以在DRF中使用不是AUTH_USER_MODEL
实例的用户对象吗?因此,self.request.user
将存储未以AUTH_USER_MODEL
以任何方式连接的模型实例。你们有没有做过类似的事情?
答案 0 :(得分:4)
嗯,是的,先生。你可以做到这一点。请查看以下example:
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
class AuthenticatedServiceClient:
def is_authenticated(self):
return True
class JwtServiceOnlyAuthentication(JSONWebTokenAuthentication):
def authenticate_credentials(self, payload):
# Assign properties from payload to the AuthenticatedServiceClient object if necessary
return AuthenticatedServiceClient()
在settings.py中:
REST_FRAMEWORK = {
'UNAUTHENTICATED_USER': None,
'DEFAULT_AUTHENTICATION_CLASSES': (
'myapp.authentication.JwtServiceOnlyAuthentication',
),
}
如果需要,您可以为DRF定义其他DEFAULT_AUTHENTICATION_CLASSES
。身份验证类就像中间件一样,只是一个填充request.user
的队列。
使用来自AUTH_USER_MODEL
的不同用户模型添加自己的身份验证类将完全按照您的方式工作。
答案 1 :(得分:3)
由于您使用的是Django和DRF,或许您可以编写一个APIUser
模型,该模型从AbstractBaseUser
扩展到您的自定义项,写一个custom authentication class并将其插入REST_FRAMEWORK.DEFAULT_AUTHENTICATION_CLASSES } 设置。为django admin留下AUTH_USER_MODEL。
您的自定义身份验证可能只需要覆盖authenticate_credentials
(我已在DRF github中引用了TokenAuthentication类)并返回APIUser而不是settings.AUTH_USER_MODEL
中定义的默认值。这将有点不同,因为您正在解码JWT,因此您可能会从JWT中提取一些信息,并通过您需要的任何方式查找您的APIUser,例如您的复合字段。这应该会导致self.request.user
成为DRF API视图的APIUser。
您的API视图应该使用其余框架的设置,而您的Django管理员应该使用常规的django设置。可能还有其他一些注意事项,但我认为通常你会对此感到满意。
答案 2 :(得分:2)
我立即回忆起的一件事是Mongoengine如何破解整个django身份验证系统。 Mongoengine< 0.10有一个django compatibility app,它实现了一个拐杖,用于在MongoDB中存储用户,并通过self.request.user
访问它们。
它必须使用拐杖,因为Django Session API是固执己见的,并假设你使用AUTH_USER_MODEL,由SQL数据库支持存储你的用户。
因此,我认为您应该禁用SessionMiddleware
和CSRF令牌处理,并为管理员和API目的使用2个不同的custom authentication systems。使用TokenAuthentication或JWTAuthentication,这应该是可行的。
Here's another example of a project使用DRF和Mongoengine,custom implementation of TokenAuthentication,由MongoDB支持。