Почему разрешения не переопределяются для набора представлений?
Я создал набор представлений для аутентификации. Поскольку это набор представлений для аутентификации, я хочу, чтобы этот набор представлений был доступен и для неавторизованных пользователей. Следуя документации DRF, вот что у меня получилось:
class AuthenticationViewSet(viewsets.ViewSet):
permission_classes = [AllowAny]
def create_user(self, request: Request) -> Response:
#code for creating a user
Поскольку я хочу, чтобы другие наборы представлений были доступны только авторизованным пользователям, я установил следующее в settings.py:
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated"],
"DEFAULT_AUTHENTICATION_CLASSES": [
"authentication.token_auth.ExpiringTokenAuthentication"
]
}
Когда я делаю вызов API к конечной точке create_user, я получаю ошибку, говорящую: "Токен не найден". Почему это происходит? Разве разрешения не должны переопределяться на основе списка permission_classes в наборе представлений?
Для справки, мой класс аутентификации:
class ExpiringTokenAuthentication(TokenAuthentication):
def authenticate(self, request):
if COOKIE_KEY in request.COOKIES:
token_key = request.COOKIES[COOKIE_KEY]
else:
raise exceptions.AuthenticationFailed("No token found")
try:
token = Token.objects.get(key=token_key)
except Token.DoesNotExist:
return exceptions.AuthenticationFailed("Invalid token")
if isTokenExpired(token):
raise exceptions.AuthenticationFailed("Token has expired")
user = token.user
return (user, token)
def isTokenExpired(token):
currentTime = datetime.now(datetime.UTC)
currentTimeUTC = currentTime.replace(tzinfo=pytz.UTC)
return token.created < currentTimeUTC - timedelta(hours=TOKEN_EXPIRE_HOURS)
У меня ушло гораздо больше времени, чем следовало бы, чтобы понять это. Но вы должны добавить и permission_classes=[]
, и authentication_classes=[]
в наборе представлений, если хотите разрешить неограниченный доступ к набору представлений.
Аутентификация и разрешения - это две разные концепции в DRF. Аутентификация - это выяснение того, кто является пользователем. Разрешения - это выяснение того, разрешено ли аутентифицированному пользователю выполнять запрошенное действие.
В этом случае, хотя я обходил разрешения, устанавливая permission_classes=[]
, я все равно получал 401, потому что запрос исходил не от аутентифицированного пользователя, так как DRF проверял запрос, чтобы понять, кто его делает.
Таким образом, код для набора представлений выглядит так:
class AuthenticationViewSet(viewsets.ViewSet):
permission_classes = []
authentication_classes = []
def create_user(self, request: Request) -> Response:
# code for creating a user