Si je suis connecté en tant que user1
et que j'accède à un ViewSet
appelé RecipeSubmissionViewSet
, le POST
prend un recette_id
de la recette que l'utilisateur souhaite soumettre. Comment puis-je m'assurer que user1
ne soumet pas la recette de user2
, en supposant que le modèle Recipe
a un champ owner
dessus et je peux simplement le comparer à request.user? Dois-je utiliser une classe d'autorisation pour cela ou y a-t-il un meilleur moyen? Je parle d'un point de vue backend et ne tient pas compte du fait que le front-end filtrerait bien sûr les recettes qui appartiennent à l'utilisateur et ne leur montrerait que leurs propres recettes.
3 Réponses :
Utilisez-vous le système d'authentification django? Ensuite, vous devriez pouvoir accéder à request.user
dans les vues et définir le champ owner
en conséquence.
EDIT: Je pense que j'ai mal compris la question.
Mais cela pourrait aider et Nafees Anwar a l'air bien.
Il peut y avoir deux manières. Vous pouvez filtrer l'ensemble de requêtes ou définir une classe d'autorisation.
Si vous remplacez la méthode get_queryset
comme ceci.
from rest_framework.permissions import BasePermission class RecipeSubmissionPermission(BasePermission): def has_object_permission(self, request, view, obj): # you can also check permission here based on action # if view.action == 'update': # pass return request.user.is_authenticated and obj.owner == request.user class RecipeSubmissionViewSet(...): permission_classes=[RecipeSubmissionPermission]
L'utilisateur obtiendra 404 réponse et ne pourra jamais accéder à des objets autres que lui.
Le deuxième choix est la classe d'autorisation. Vous pouvez définir une classe d'autorisation personnalisée et vérifier explicitement la propriété de cette manière.
class RecipeSubmissionViewSet(...): def get_queryset(self): return Recipe.objects.filter(owner=self.request.user) # you can also use filtration based on action name like this # if self.action == 'update': # return Recipe.objects.filter(owner=self.request.user) # return Recipe.objects.all()
Dans ce cas, l'utilisateur recevra une erreur d'autorisation 403 .
Si vous utilisez ces deux méthodes. 404 sera préféré.
Vous pouvez utiliser la méthode de votre choix ou les deux. La classe d'autorisation semble plus programmatique et structurée, mais l'utilisateur saura que l'objet avec cet identifiant existe mais il n'avait pas l'autorisation de le mettre à jour. Mais si vous remplacez le jeu de requêtes, l'utilisateur n'est même pas en mesure de savoir si l'objet existe ou n'est donc pas plus sécurisé.
Merci d'avoir répondu. J'utilise en fait la méthode get_queryset
, mais qu'en est-il sur un message? Qu'en est-il d'empêcher un utilisateur de publier la recette d'un autre utilisateur? Dois-je maintenant utiliser une classe d'autorisation ou puis-je en quelque sorte tirer parti du get_queryset
dans un POST
?
Lorsque l'utilisateur publie pour mettre à jour une recette, get_queryset
sera automatiquement utilisé pour obtenir l'instance de Recipe
et tout le filtrage sera appliqué. Si vous effectuez la mise à jour manuellement (définissant des actions personnalisées), vous devez utiliser la méthode get_object
pour obtenir l'instance Recipe
que vous souhaitez mettre à jour. Il utilisera automatiquement la méthode get_queryset
et retournera 404 si l'objet n'appartient pas à l'utilisateur.
La méthode get_queryset ()
n'a aucun rôle lors de la création d'objets. @NafeesAnwar
@JPG le POST prend une recette_id de la recette que l'utilisateur veut soumettre Je pense qu'il essaie de mettre à jour.
Non, j'essaye de créer.
@Pittfall Vous devriez ajouter quelques morceaux de code (ensemble de vues, modèles) si possible pour une réponse plus claire. Formez un anglais simple, il est difficile de comprendre exactement ce que vous essayez de faire.
Ok, disons que vous avez une Recipe
, vous la postez parce que vous n'avez pas fini de l'écrire mais elle n'est PAS soumise dans le tableau RecipeSubmission
. Ensuite, vous POST
(créez) un RecipeSubmission
et dans le corps de la vue RecipeSubmission
attend un recette_id
. Je ne veux pas que quelqu'un injecte une recette_id dans le corps de RecipeSubmission
pour une Recipe
qui n'appartient pas à cet utilisateur authentifié.
La réponse de Nafees est à peu près la voie à suivre.
J'ai développé des microservices avec multi-location pour les utilisateurs et les règles pour eux (selon les spécifications de mes projets) sont:
La façon dont je fais cela est simple.
Pour interdire l'affichage / la modification des données de quelqu'un d'autre
class SomeSerializer(...): def validate(self, data): data.pop('user', None) data['user'] = self.context['request'].user
Et pour interdire la modification des choses de quelqu'un d'autre, cela se fait sur un sérialiseur
def get_queryset(self): return self.queryset.filter(user=request.user)
Avec ce qui précède, le get_queryset
dans l'ensemble de vues renverra toujours un 404 si l'utilisateur1 demande des informations sur l'utilisateur2.
Et le La fonction de validation
empêchera l'attribution. C'est à dire. Si user1 crée quelque chose assigné à user2, il attribuera plutôt user1, ce comportement est ce dont j'avais besoin dans mon application, vous pouvez toujours augmenter les sérialiseurs.ValidationError ("Vous ne pouvez pas assigner des choses à user2")
à la place si c'est ce dont vous avez besoin au lieu de réaffecter l'utilisateur comme je le fais dans mon cas d'utilisation. Avec cette logique dans le valider
, vous pouvez être sûr que toute fonction inscriptible aura toujours le même comportement pour ce sérialiseur.
J'espère que cela vous aidera.
p>
Pour plus de précisions, pouvez-vous inclure vos modèles et vues si possible?