惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Schneier on Security
A
Arctic Wolf
Scott Helme
Scott Helme
S
Securelist
Schneier on Security
Schneier on Security
W
WeLiveSecurity
Attack and Defense Labs
Attack and Defense Labs
Security Latest
Security Latest
Project Zero
Project Zero
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
P
Palo Alto Networks Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Google DeepMind News
Google DeepMind News
P
Proofpoint News Feed
C
Check Point Blog
F
Full Disclosure
Stack Overflow Blog
Stack Overflow Blog
H
Hacker News: Front Page
T
The Blog of Author Tim Ferriss
TaoSecurity Blog
TaoSecurity Blog
Vercel News
Vercel News
A
About on SuperTechFans
N
News and Events Feed by Topic
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The GitHub Blog
The GitHub Blog
S
Security Affairs
Y
Y Combinator Blog
T
The Exploit Database - CXSecurity.com
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Forbes - Security
Forbes - Security
IT之家
IT之家
WordPress大学
WordPress大学
Last Week in AI
Last Week in AI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
The Register - Security
The Register - Security
Jina AI
Jina AI
云风的 BLOG
云风的 BLOG
T
Tailwind CSS Blog
K
Kaspersky official blog
Hacker News: Ask HN
Hacker News: Ask HN
C
Cisco Blogs
MyScale Blog
MyScale Blog
博客园 - 【当耐特】
T
Threat Research - Cisco Blogs
D
Docker
G
GRAHAM CLULEY

博客园 - hgdfr

Django1.5内置的用户认证系统介绍(之五)在admin后台管理用户 --by hillfree Django1.5内置的用户认证系统介绍(之四)Authentication in Web requests --by hillfree Django1.5内置的用户认证系统介绍(之三)权限与授权--by hillfree Django1.5内置的用户认证系统介绍(之二)使用User对象--by hillfree Django1.5内置的用户认证系统介绍(之一)--by hillfree Django REST Framework Tutorial 5:关系与超链接API(中文版教程)by hillfree Django REST Framework Tutorial 3:基于类的Views(中文版教程)by hillfree Django1.5+Python3.3下groundwork的使用 Django1.5中设置静态目录的简要说明 参照《鲜活的数据:数据可视化指南》第2章:抓取网页数据(历史天气记录)的Python程序 Python3.3中如何产生伪随机数 《鲜活的数据:数据可视化指南》第2章 收集数据 Python3.3源码 CSCW领域的“老”词和“新”词 FOAF简介和朋友圈子 Class Library类型的工程难道不能用app.config? 配置文件中的DataDirectory在那里设置? 自己写的类需要重写ToString(), HashCode(), Equal()吗? 注释中如果出现尖括号怎么办?“<” - hgdfr - 博客园 Access Control Issues 有关访问控制
Django REST Framework Tutorial 4:认证与权限(中文版教程)by hillfree
hgdfr · 2013-03-26 · via 博客园 - hgdfr

摘要: 跟着Django的教程走例子,遇到了Django REST Framework的内容,可惜教程用的版本有点老,在Django1.5,Python3.3下例子都通不过。在http://django-rest-framework.org的官网上有教程,我看了看,似乎只有前两部分的中文翻译,就趁着自己看也翻一下后面的部分,自己学习,供大家参考:如有错讹,请多指教。

原始来源:http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html

教程4: 认证和权限 Authentication & Permissions

目前为止,我们的API对谁能编辑或删除snippet(代码片段)还没有任何限制。我们将增加一些扩展功能来确保以下:

  • snippets总关联一个创建者;
  • 只有认证后的用户才能创建一个snippets.
  • 只有创建者才能更新或删除snippet;
  • 非认证请求只拥有只读权限。

为model增加信息

我们先需要对Snippet的model做些修改。首先,增加一些fields. 其中一个用来表示创建者,另一个用来存储代码中的HTML高亮。

在模型中增加这两个字段。

1 owner = models.ForeignKey('auth.User', related_name='snippets')
2 highlighted = models.TextField()

我们还需要确保model存储时,我们能生成高亮字段内容,这里使用 pygments 代码高亮库。

首先需要一些额外的imports:

from pygments.lexers import get_lexer_by_name
from pygments.formatters.html import HtmlFormatter
from pygments import highlight

我们现在为模型增加一个 
.save() 方法:
def save(self, *args, **kwargs):
    """
    Use the `pygments` library to create a highlighted HTML
    representation of the code snippet.
    """
    lexer = get_lexer_by_name(self.language)
    linenos = self.linenos and 'table' or False
    options = self.title and {'title': self.title} or {}
    formatter = HtmlFormatter(style=self.style, linenos=linenos,
                              full=True, **options)
    self.highlighted = highlight(self.code, lexer, formatter)
    super(Snippet, self).save(*args, **kwargs)

这些完成后还需要更新一下数据库里面的表。通常我们要创建一个数据库迁移(database migration)来完成,但教程中,我们就只是删除数据库然后重新创建:

rm tmp.db
python ./manage.py syncdb

你可能想创建一些其他用户来测试这些API,最快捷的方式是利用 createsuperuser 命令。

python ./manage.py createsuperuser

为用户模型增加endpoints

现在我们需要一些用户,我们最好把用户呈现也增加到API上,创建一个新的serializer很容易:

from django.contrib.auth.models import User

class UserSerializer(serializers.ModelSerializer):
    snippets = serializers.PrimaryKeyRelatedField(many=True)

    class Meta:
        model = User
        fields = ('id', 'username', 'snippets')

因为 'snippets' 和用户model是反向关联(reverse relationship,即多对一),所以在使用 ModelSerializer时并不会缺省加入,所以我们需要显式的来实现。

我们还需要创建一些views,对用户呈现而言,我们最好使用只读的view,所以使用 ListAPIView 和 RetrieveAPIView 泛型类Views。

class UserList(generics.ListAPIView):
    model = User
    serializer_class = UserSerializer

class UserDetail(generics.RetrieveAPIView):
    model = User
    serializer_class = UserSerializer

最后,我们需要修改URL conf:

url(r'^users/$', views.UserList.as_view()),
url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),

把Snippets与Users关联

现在,如果我们创建一个code snippet,还没有方法指定其创建者。User并没有作为序列化内容的一部分发送,而是作为request的一个属性。

这里的处理方法是重载snippet view中的 .pre_save() 方法,它可以让我们处理request中隐式的信息。

在 SnippetList 和 SnippetDetail 的view类中,都需要添加如下的方法:

def pre_save(self, obj):
    obj.owner = self.request.user

更新 serializer

现在snippets已经和创建者关联起来了,我们接下来还需要更新SnippetSerializer,在其定义中增加一个新的字段:

owner = serializers.Field(source='owner.username')

Note: 确定你在嵌入类Meta的字段列表中也加入了 'owner'。

这个字段所做的十分有趣。source 参数表明增加一个新字段,可以指定序列化实例任何属性。它可以采用如上的点式表示(dotted notation),这时他可以直接遍历到指定的属性。在Django's template中使用时,也可以采用类似的方式。

我们增加字段是一个无类型 Field 类,而我们之前的字段都是有类型的,例如 CharFieldBooleanField etc... 无类型字段总是只读的,它们只用在序列化表示中,而在反序列化时(修改model)不被使用。 

给view增加权限控制

现在代码片段 snippets 已经关联了用户,我们需要确保只有认证用户才能增、删、改snippets.

REST framework 包括许多权限类可用于view的控制。这里我们使用 IsAuthenticatedOrReadOnly, 它可确保认证的request获取read-write权限,而非认证的request只有read-only 权限.

现需要在views模块中增加 import。

from rest_framework import permissions

然后需要在 SnippetList 和 SnippetDetail view类中都增加如下属性:

permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

为可浏览API(Browseable API)增加login

如果你打开浏览器,访问可浏览API,你会发现只有登录后才能创建新的snippet了。

我们可以编辑URLconf来增加一个登录view。首先增加新的import:

from django.conf.urls import include

然后,在文件末尾增加一个pattern来为browsable API增加 login 和 logout views.

urlpatterns += patterns('',
    url(r'^api-auth/', include('rest_framework.urls',
                               namespace='rest_framework')),
)

具体的, r'^api-auth/' 部分可以用任何你想用的URL来替代。这里唯一的限制就是 urls 必须使用'rest_framework' 命名空间。

现在如果你打开浏览器,刷新页面会看到页面右上方的 'Login' 链接。如果你用之前的用户登录后,你就又可以创建 snippets了。

一旦你创建了一些snippets,当导航至'/users/'时,你会看到在每个user的snippets字段都包含了一系列snippet的pk。

对象级别的权限

我们希望任何人都可以浏览snippets,但只有创建snippet的用户才能编辑或删除它。

为了实现这个需求,我们需要创建定制的权限(custom permission)。

在 snippets 应用中,创建一个新文件: permissions.py

from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    Custom permission to only allow owners of an object to edit it.
    """

    def has_object_permission(self, request, view, obj):
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:            
            return True

        # Write permissions are only allowed to the owner of the snippet
        return obj.owner == request.user

现在我们可以为snippet实例增加定制权限了,需要编辑 SnippetDetail 类的 permission_classes 属性:

permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                      IsOwnerOrReadOnly,)

别忘了import 这个IsOwnerOrReadOnly 类。

from snippets.permissions importIsOwnerOrReadOnly

现在打开浏览器,你可以看见 'DELETE' 和 'PUT' 动作只会出现在那些你的登录用户创建的snippet页面上了.

通过API认证

我们已经有了一系列的权限,如果我们需要编辑任何snippet,我们需要认证我们的request。因为我们还没有建立任何 authentication classes, 所以目前是默认的SessionAuthentication 和 BasicAuthentication在起作用。

当我们通过Web浏览器与API互动时,我们登录后、然后浏览器session可以为所有的request提供所需的验证。

如果我们使用程序访问这些API,我们则需要显式的为每个request提供认证凭证(authentication credentials)。

如果我们试图未认证就创建一个snippet,将得到错误如下:

curl -i -X POST http://127.0.0.1:8000/snippets/ -d "code=print 123"

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

如果我们带着用户名和密码来请求时则可以成功创建:

curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 789" -u tom:password

{"id": 5, "owner": "tom", "title": "foo", "code": "print 789", "linenos": false, "language": "python", "style": "friendly"}

小结

我们已经为我们的Web API创建了相当细粒度的权限控制和相应的系统用户。

在教程第5部分 part 5 ,我们将把所有的内容串联起来,为我们的高亮代码片段创建HTML节点,并利用系统内的超链接关联来提升API的一致性表现。

【translate by hillfree @ 2013年3月26日10:14:55】