带自定义用户模型的django-oauth2-provider?
我现在在项目中遇到了很大的困难。我正在尝试为我的应用实现Oauth2。我了解到很多关于django-oauth2-provider的信息,并且也尝试过使用它。唯一的问题是,它使用的是django.contrib.auth中的用户模型。而我们网站的主要用户是保存在一个叫做User的自定义模型中,这个模型并没有继承或扩展django.contrib.auth中的模型。
有没有办法让我使用自定义的User模型来创建客户端和令牌呢?
如果django-oauth2-provider不能满足这个需求,有没有人能推荐一些可以与我自己的模型一起实现Oauth2的库呢?
真诚的,
Sushant Karki
4 个回答
你需要创建一个自定义的 OAuth2 验证器,并重写 validate_user 这个函数。
"""API Core Auth Utils"""
from django.core.exceptions import ObjectDoesNotExist
from oauth2_provider.oauth2_validators import OAuth2Validator
from rest_framework.request import Request
from core.models import Customer
from core.models.serializers import UserSerializer
class OAuthValidator(OAuth2Validator): # pylint: disable=abstract-method
"""Custom Validator to be used with OIDC"""
def get_userinfo_claims(self, request):
claims = super().get_userinfo_claims(request)
...
return claims
def get_additional_claims(self, request: Request):
return {
"id": request.user.id,
"email": request.user.email,
"username": request.user.username,
"given_name": request.user.first_name,
"family_name": request.user.last_name,
"name": f"{request.user.first_name} {request.user.last_name}",
}
class OAuthCustomerValidator(OAuth2Validator): # pylint: disable=abstract-method
"""Custom OAuth Validator for Customers to be used with OIDC"""
def validate_user(self, username, password, client, request, *args, **kwargs):
try:
customer = Customer.objects.get(email=username)
if customer.is_active and customer.authenticate(password):
request.user = customer
return True
return False
except ObjectDoesNotExist:
return False
另外,你还可以实现一个请求验证器:from oauthlib.openid import RequestValidator
django-oauth2-provider 这个库会用 settings.AUTH_USER_MODEL
来获取用户模型,如果没有设置的话,它会默认使用 auth.User
。如果你扩展了 AbstractUser
,那么你的用户模型会包含 auth.User
的所有字段,还可以加上你自己定义的额外字段。
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
some_additional_field = models.BooleanField(default=False)
在 settings.py
文件中指定要使用的用户模型,方法如下:
AUTH_USER_MODEL = 'user_api.User'
如果你不想基于 AbstractUser
来创建用户模型,你还需要自己写一个用户管理器,比如可以扩展 BaseUserManager
。
正如之前的回答所提到的,你应该从 django.contrib.auth.models
中扩展 AbstractUser
。
提问者提到的访问令牌问题,发生在你在 django-oauth2-provider
迁移之后才更改 AUTH_USER_MODEL
设置的时候。
当 django-oauth2-provider
迁移时,它会在用户模型和 django-oauth2-provider
之间创建一个关键约束。
解决这个问题的方法很简单:
- 创建你新的用户模型,并更改
AUTH_USER_MODEL
设置。 - 去你的数据库中的
django_migration
表。 - 删除所有与
django-oauth2-provider
相关的行。 - 运行
python manage.py makemigrations
。 - 运行
python manage.py migrate
。
现在,django-oauth2-provider
的表就和正确的用户模型连接起来了。