django-Vue搭建博客:用户权限

萧升
2023-12-01

权限是 web 应用的重要组成部分。没有权限控制,任何人的请求都会对数据资源进行操控,那就乱套了。

本章就来学习 drf 中如何进行权限管理。

教程来源杜塞-django-vue系列
博客链接 传送门

文章与用户

依靠用户身份来限制权限是比较通用的做法,在静态模式下存在,drf中那也当然存在。
改写文章模型添加用户外键,确定每篇文章的作者,保险起见,我们要提前删除现有的所有文章。

修改文章model,添加以下:

#article/model.py
from django.contrib.auth.models import User

# 博客文章
class Article(models.Model):
	# 用户
    author = models.ForeignKey(
        User,
        null=True,
        on_delete=models.CASCADE,
        related_name='articles'
    )

执行迁移(每次对模型进行修改都需要!!!):

> python manage.py makemigrations
> python manage.py migrate

启动服务器,然后再次请求:

(venv) E:\drf\drf_vue_blog>http http://127.0.0.1:8000/api/article/
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 2
Content-Type: application/json
Date: Sun, 13 Jun 2021 06:22:02 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

[]

空空如也。

接下来对文章列表接口进行操作.

权限控制

DRF 内置了如IsAuthenticatedIsAdminUserAllowAny等权限控制类。

由于是个人博客,因此只准许管理员发布文章。修改文章列表视图如下:

# article/views.py
from rest_framework.permissions import IsAdminUser


class ArticleList(generics.ListCreateAPIView):
	···
    # 新增
    permission_classes = [IsAdminUser]

permission_classes可以接收一个列表,因此权限控制类可以设置多个,请求必须满足所有控制条件才允许被放行。

测试一下:

(venv) E:\drf\drf_vue_blog>http http://127.0.0.1:8000/api/article/
HTTP/1.1 403 Forbidden
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 58
Content-Type: application/json
Date: Sun, 13 Jun 2021 06:23:43 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "detail": "Authentication credentials were not provided."
}



(venv) E:\drf\drf_vue_blog>http POST http://127.0.0.1:8000/api/article/ title=may body=not..
HTTP/1.1 403 Forbidden
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 58
Content-Type: application/json
Date: Sun, 13 Jun 2021 06:24:11 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "detail": "Authentication credentials were not provided."
}

可以发现确实起作用了,但是除了管理员之外其他人也无法查看,显然这不是我们最重要的结果。

接下来让我们重写。新建 article/permissions.py:

from rest_framework import permissions


class IsAdminUserOrReadOnly(permissions.BasePermission):
    """
    定义我们需要的权限
        1.进管理员可以进行修改
        2.其他用户仅能查看
    """

    def has_permission(self, request, view):
        # 对所有人允许 GET,HEAD,OPTIONS请求
        if request.method in permissions.SAFE_METHODS:
            return True

        # 仅管理员可进行其他操作
        return request.user.is_superuser

自定义的权限类继承了 BasePermission这个基础的父类,并实现了父类中的钩子方法 def has_permission。此方法在每次请求到来时被唤醒执行,里面简单判断了请求的种类是否安全(即不更改数据的请求),如果安全则直接通过,不安全则只允许管理员用户通过。

再次修改视图:

# article/views.py
from .permissions import IsAdminUserOrReadOnly
permission_classes = [IsAdminUser]
# 改为
permission_classes = [IsAdminUserOrReadOnly]

# ArticleList和ArticleDetail添加

改完后进行测试。

首先测试用户未登录状态:


(venv) E:\drf\drf_vue_blog>http http://127.0.0.1:8000/api/article/
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 2
Content-Type: application/json
Date: Sun, 13 Jun 2021 06:43:43 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

[]



(venv) E:\drf\drf_vue_blog>http POST http://127.0.0.1:8000/api/article/ title=may body=not..
HTTP/1.1 403 Forbidden
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 58
Content-Type: application/json
Date: Sun, 13 Jun 2021 06:44:51 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "detail": "Authentication credentials were not provided."
}

我们发现,虽然没有文章返回,但是体现出了权限的作用(添加文章测试也是一样的效果,不做多赘述)。
在后台创建普通用户 Obama(这是基础),用普通用户身份进行请求:

# 普通用户Obama密码admin123456

(venv) E:\drf\drf_vue_blog>http -a Obama:admin123456 http://127.0.0.1:8000/api/article/
HTTP/1.1 200 OK 成功
···
[]

(venv) E:\drf\drf_vue_blog>http -a Obama:admin123456 POST http://127.0.0.1:8000/api/article/ title=may body=not..
HTTP/1.1 403 Forbidden 失败
Allow: GET, POST, HEAD, OPTIONS
···
{
    "detail": "您没有执行该操作的权限。"
}

这边中文是因为我更改时区问题,英文为:"detail": "You do not have permission to perform this action.
最后创建超级管理员进行测试,我的为 xianwei

# 管理员在用户 xianwei,密码:admin123456

(venv) E:\drf\drf_vue_blog>http -a xianwei:admin123456 http://127.0.0.1:8000/api/article/
HTTP/1.1 200 OK 请求成功
···
[]

(venv) E:\drf\drf_vue_blog>http -a xianwei:admin123456 POST http://127.0.0.1:8000/api/article/ title=may body=not..
HTTP/1.1 201 Created 请求成功
···
{
    "created": "2021-06-13T15:01:15.586622",
    "id": 8,
    "title": "may"
}

最终完成了我们要的效果,任何人可以查看,只有管理员进行新增(CREATE)、更新(PUT)、删除(DELETE)等修改操作

 类似资料: