【问题标题】:Django RestAPI - only allow access to users data with JWT AuthenticationDjango Rest API - 仅允许使用 JWT 身份验证访问用户数据
【发布时间】:2021-04-27 12:15:00
【问题描述】:

我有以下 API:

型号:

class Todo(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=20, default="")
    text = models.TextField(max_length=450, default="")
    done = models.BooleanField(default=False)

查看:

class TodoView(viewsets.ModelViewSet):
    serializer_class = TodoSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        id = self.request.query_params.get("id")
        queryset = Todo.objects.filter(owner__id=id)
        return queryset

序列化器:

class TodoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Todo
        fields = ("id", "owner", "name", "text", "done")

我使用rest_framework_simplejwt 作为我的令牌,并使用以下路径来接收我的令牌:

path("api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"),

这是令牌:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjE5Mjg4ODAwLCJqdGkiOiJhY2E4MjM5ZGMyZjA0NGE5YWE4NzM3NWZjMDc2NWQ0YSIsInVzZXJfaWQiOjF9.xJ4s971XE0c9iX0Ar1HQSE84u_LbDKLL4iMswYsk2U8

当我在 jwt.io 上对其进行解码时,我可以看到它包含用户 ID:

{
  "token_type": "access",
  "exp": 1619288800,
  "jti": "aca8239dc2f044a9aa87375fc0765d4a",
  "user_id": 1
}

在我的请求标头中没有令牌的http://localhost:8000/todos/?id=1 请求不起作用(很好!),但是有了令牌,我也可以访问http://localhost:8000/todos/?id=2,这当然是不希望的。我只想访问http://localhost:8000/todos/?id=1(有效载荷中对应的user_id

我该怎么做?

【问题讨论】:

    标签: django django-rest-framework django-authentication


    【解决方案1】:

    用这个改变你的get_queryset 方法:

    def get_queryset(self):
        reque Todo.objects.filter(owner=self.request.user)
    

    现在任何人都只能访问自己的 Todo 记录。

    网址应该是这样的http://localhost:8000/todos/<id>

    额外: 不要从客户那里接受owner。而是设置自己。 如下所示。

    class TodoSerializer(serializers.ModelSerializer):
        owner = serializers.HiddenField(default=serializers.CurrentUserDefault())
    
        class Meta:
            model = Todo
            fields = ("id", "owner", "name", "text", "done")
    

    【讨论】:

    • 嗯,我收到一个新错误:TypeError: Field 'id' expected a number but got .
    • @DataMastery 看起来您仍然在过滤器上使用owner__id 而不是owner
    • 您还应该在 url 中提供 id 的类型是 int /todos/<int:id>/ 但如果您使用的是 Todo.objects.filter(owner=self.request.user) 则无需在 URL 中传递 id,所以 /todos/跨度>
    猜你喜欢
    • 2020-01-01
    • 2016-12-27
    • 2019-01-01
    • 1970-01-01
    • 2016-03-24
    • 2019-03-01
    • 2021-12-21
    • 1970-01-01
    • 2012-08-17
    相关资源
    最近更新 更多