跳转到主要内容

仅基于允许列表的授权系统

项目描述

django-denied

无人可进。

黑色骑士

django-denied 是 Django 网络框架的授权系统。使用 django-denied,Django 视图 必须显式允许。这种设计意味着开发者必须为视图的工作进行授权选择。

换句话说,django-denied 使得授权成为 Django 项目的每个视图的必需条件。

谁应该使用这个?

此包非常适合需要保护页面免受未经授权访问的 Django 项目。如果您正在开发需要用户登录并限制用户查看的数据的服务,那么 django-denied 可能适合您。

如果您的 Web 应用程序旨在对大量受众开放,特别是有很多匿名用户,那么此包可能超过了您的需求。博客或内容管理系统可能不是合适的选择。

安装

获取包。

pip install django-denied

django-denied 使用 Django 内置的 authadmin 应用。这些应用还依赖于 contenttypes 应用。请确保这些应用已包含在您的 Django 设置文件中的 INSTALL_APPS 中。

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    ...,
]

添加 DeniedMiddleware。这个中间件负责所有的授权检查。中间件依赖于 request.user,所以请确保在 AuthenticationMiddleware 之后再添加它。

MIDDLEWARE = [
    ...,
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "denied.middleware.DeniedMiddleware",
    ...,
]

现在你准备好了。

用法

django-denied有处理视图的两种主要模式。

  1. 允许
  2. 授权

这些装饰器是包的主要接口,下面将详细介绍。

默认情况下,django-denied假定所有用户都应该经过身份验证,除非是允许的视图或登录页面。

登录页面是

  • settings.LOGIN_URL 定义的页面,以及
  • admin:login 路由中定义的 Django 管理登录。

如果你设置了 LOGIN_URL,django-denied期望的是设置的路径形式(例如,/accounts/login/),而不是 url 名称(例如,accounts:login)。

允许视图

每个应用都可能有一些应该对未经验证用户可访问的视图。一个公司的关于页面、服务条款和隐私政策都是很好的例子。

allow 装饰器用于标记 Django 视图,使其免于 DeniedMiddleware 执行的授权检查。

这是一个创建服务条款视图的示例。

# application/views.py
from denied.decorators import allow
from django.shortcuts import render


@allow
def terms_of_service(request):
    return render(request, "tos.html", {})

allow 装饰器有一个次要功能。除了允许单个视图外,装饰器还可以允许一组视图,这可以使用 django.urls.path

这是为了允许第三方应用程序,这些应用程序有其他视图,但不知道 django-denied 系统。

这是一个使用 allow 允许 Django 管理视图以及流行的应用程序 django-allauth 的示例。

# project/urls.py
from denied.decorators import allow
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("accounts/", allow(include("allauth.urls"))),
    path("admin/", allow(admin.site.urls)),
]

注意:即使你在视图或一组视图中包含了 allow,这并不意味着你允许的内容会突然绕过现有的身份验证或授权检查。这是一个功能,而不是错误!

login_requiredpermission_required 以及视图上现有的任何其他身份验证或授权检查都将保持不变。django-denied不会禁用其他第三方库的安全功能。

授权视图

使用 django-denied,Django 视图通过 authorize 装饰器和 授权器 函数进行授权。授权器的函数签名如下:

from django.http import HttpRequest


def example_authorizer(request: HttpRequest, **view_kwargs: dict) -> bool:
    ...

授权器评估传入的请求和视图信息,如果请求被授权则返回 True,如果没有授权则返回 Falseview_kwargs 包含从 URL 路由解析出来的任何数据。

授权器充当声明性方式来显示对视图的授权。

from denied.decorators import authorize

from .authorizers import example_authorizer


@authorize(example_authorizer)
def example_view(request):
    ...

要在基于类的视图中使用 authorize,你必须将装饰器附加到 dispatch 方法。

from denied.decorators import authorize
from django.utils.decorators import method_decorator
from django.views.generic import DetailView

from .authorizers import example_authorizer
from .models import Example


@method_decorator(authorize(example_authorizer), "dispatch")
class ExampleDetail(DetailView):
    queryset = Example.objects.all()

内置授权器

库包含用于常见情况的内置授权器。

denied.authorizers.any_authorized

这个授权器始终评估为 True,并且与 login_required 逻辑等价,因为 django-denied始终强制执行身份验证检查。

denied.authorizers.staff_authorized

这个授权器仅当 user.is_staff == True 时允许访问。staff_authorized 与 Django admin 应用中的 staff_member_required 等价。

授权器示例

本节将展示一个更完整的授权器示例,以帮助你了解 django-denied 在实际中的工作方式。

对于我们的示例,我们将考虑一个项目跟踪应用程序。这不过是一个将任务分组到项目中的 TODO 列表。

以下是模型。

# application/models.py
from django.contrib.auth.models import User
from django.db import models


class Project(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE)


class Task(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    description = models.TextField()
    completed = models.BooleanField(default=False)

对于这个简单的系统,只有项目所有者可以对任务进行任何操作。让我们为这个创建一个授权器。

# application/authorizers.py


def task_authorized(request, **view_kwargs):
    return Task.objects.filter(
        project__owner=request.user,
        pk=view_kwargs["pk"],
    ).exists()

这是我们想使用此授权器支持的 URL。

# application/urls.py

from django.urls import path

from .views import task_detail, task_edit

urlpatterns = [
    path("tasks/<int:pk>/", task_detail, name="task_detail"),
    path("tasks/<int:pk>/edit/", task_detail, name="task_edit"),
]

现在我们可以设置我们的视图并设置它们的授权。

# application/views.py
from denied.decorators import authorize
from django.shortcuts import render

from .authorizers import task_authorized
from .models import Task


@authorize(task_authorized)
def task_detail(request, pk):
    task = Task.objects.get(pk=pk)
    return render(request, "task_detail.html", {"task": task})


@authorize(task_authorized)
def task_edit(request, pk):
    task = Task.objects.get(pk=pk)
    return render(request, "task_edit.html", {"task": task})

由于授权者处理访问控制,我们可以确信仅通过其密钥即可安全地获取任务。将访问控制推到视图的边界,这样视图的内部逻辑就尽可能简单。

项目详情


下载文件

下载适用于您平台的文件。如果您不确定选择哪一个,请了解更多关于安装包的信息。

源分发

django-denied-1.3.tar.gz (11.8 kB 查看哈希值)

上传时间

构建分发

django_denied-1.3-py3-none-any.whl (7.6 kB 查看哈希值)

上传时间 Python 3

支持

AWSAWS云计算和安全赞助商DatadogDatadog监控FastlyFastlyCDNGoogleGoogle下载分析MicrosoftMicrosoftPSF赞助商PingdomPingdom监控SentrySentry错误日志StatusPageStatusPage状态页面