zoukankan      html  css  js  c++  java
  • django-访问控制

    django自带的用户认证系统提供了访问控制的的功能。
     
    1.只允许登录的用户登录
     
    django的用户可分为两类,一是可认证的用户,也就是在django.contrib.auth.models.User中注册了的;另一种是匿名用户django.contrib.auth.models.AnonymousUser,每个访问的未登录的用户都是该类的一个实例,而匿名用户是无法认证的,即 is_authenticated 方法永远返回 False,或者is_anonymous返回True,我们可以在代码逻辑中实现对匿名用户进行判断,然后拒绝其访问(403),或者重定向到登录页面等。
     
    from django.conf import settings
    from django.shortcuts import redirect
    
    def my_view(request):
        if not request.user.is_authenticated:
            return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
        # ...
    以上就是在代码中重定向到登录页面的做法,也可以返回错误信息:
     
    from django.shortcuts import render
    
    def my_view(request):
        if not request.user.is_authenticated:
            return render(request, 'myapp/login_error.html')
        # ...
    由于这是一个常见的需求,所以django提供了一个装饰器来实现这个功能。
     
    from django.contrib.auth.decorators import login_required
    
    @login_required
    def my_view(request):
        ...
     
    这样大大的简化了工作。
     
     login_required(redirect_field_name='next', login_url=None) 
     
    若用户没有登录的话, 其将无法访问被装饰的视图,而是重定向到登录页面,这个登录页面可以使用login_url参数指定,并且可以接受命名url的方式,如:@login_required(login_url='login'),当然前提是要有相应的命名的url。如果没有给定这个参数,将使用settings.LOGIN_URL的值。
     
     
    LOGIN_URL
    Default: '/accounts/login/'
     
    The URL where requests are redirected for login, especially when using the login_required() decorator.
     
    This setting also accepts named URL patterns which can be used to reduce configuration duplication since you don’t have to define the URL in two places (settings and URLconf).
     
    可以看见其有默认值,如果你不给参数,且登录地址不是这个默认值,将触发404错误,也就是还是重定向到那个页面去了,只是找不到而已。若强制重写为None,其会触发TypeError,若DEBUG=False,则应该是500系列的服务器错误。
     
    但是,在重定向的时候,并不是单纯跳转,而是会带一个next查询参数例如:
     
     
     
    这样你就可以获取登录前想要访问的页面(这里就是/account/change_info页面了),然后在登录后重定向回去,而不用盲目重定向到首页,用户体验会更好点。
     
    下面就是登录视图中所做的配合:
     
    next_to = request.GET.get('next', None)  # 获取是否有next的重定向,是一个相对路径,不含方案和域名
    if next_to:
        return redirect(next_to)
    当然你也可以改变redirect_field_name来改变next这个名称,当然在登录视图里也要做想要的调整,也可以将其设为None来取消附带参数的行为。
     
     
    注意:login_required 并不会检查用户是否处于活跃状态(is_active),而处理用户登录的默认后台模板在1.10之前并不会拒绝非活跃用户登录,而1.10版本就会。这意味着如果你使用的版本低于1.10,你必须在代码逻辑中拒绝非活跃用户登录。
     
    if user.is_active:  # 若用户是活跃的,即未冻结的,在1.10之前冻结用户默认也能登录,所以需要自己认证
        login(request, user)    # 登录
    ......    #其他处理
    else:
        return HttpResponse('用户被冻结')
     
    2.只允许staff身份的用户访问某个视图
     
    django同样提供了一个便捷的装饰器来实现这个功能:
     
     staff_member_required(redirect_field_name='next', login_url='admin:login') 
     
     
    可以看到其和上述的 login_required 参数上几乎一样,只是默认值有些许不同,而在用法上也是一样的,但并没有settings.LOGIN_URL之类的设置层面上的退路。要注意一点,因为其默认是重定向至admin的登录页面,若要通过复杂化url的方式来隐藏入口的时候,要小心其会暴露该url。
     
    This decorator is used on the admin views that require authorization. A view decorated with this function will having the following behavior:
    这个装饰器已经被admin的视图所使用了,其行为如下:
     
     
     
    • If the user is logged in, is a staff member (User.is_staff=True), and is active (User.is_active=True), execute the view normally.
    如果用户已经登录,且为staff身份,并且是活跃的,则正常执行所装饰的视图。
     
    • Otherwise, the request will be redirected to the URL specified by the login_url parameter, with the originally requested path in a query string variable specified by redirect_field_name. For example: /admin/login/?next=/admin/polls/question/3/.
    否则,将会重定向到login_url,并带查询参数。
     
    Example usage:
    用例:
     
     
    from django.contrib.admin.views.decorators import staff_member_required
    
    @staff_member_required
    def my_view(request):
        ...
    可以看到其使用方法和login_required()基本是一样的。
     

    3.简单的函数测试验证法
     
    django提供了一个装饰器,让我们可以自定义一个简单的验证函数,只有通过该验证函数之后才能访问指定的视图。
     
     user_passes_test(func[, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME]) 
     
    可以看到其比上面的两个装饰器多了一个参数,这个参数就是用指定验证函数的。
     
    例如,我想要验证某个用户的邮箱是否符合我想要的格式:
     
    原始的验证法:
     
    from django.shortcuts import redirect
    
    def my_view(request):
        if not request.user.email.endswith('@example.com'):
            return redirect('/login/?next=%s' % request.path)
        # ...
     
    在视图函数中验证其是否以@example.com结尾。
     
    下面是装饰器验证法:
     
    from django.contrib.auth.decorators import user_passes_test
    
    def email_check(user):
        return user.email.endswith('@example.com')
    
    @user_passes_test(email_check)
    def my_view(request):
        ...
    注意:email_check函数其本质上也是返回布尔值,所以在自定义函数的时候,返回True表示通过,False表示不通过。不通过则重定向到登录页面,其他细节和之前的两个装饰器一样。
     
     

    基于类的视图的实现
     
    基于类的视图在实现login_required的行为时,需要继承LoginRequiredMixin这个类,并将其放在继承树的最左边,同时相应的实现在类中书写,例如:
     
    from django.contrib.auth.mixins import LoginRequiredMixin
    
    class MyView(LoginRequiredMixin, View):
        login_url = '/login/'
        redirect_field_name = 'redirect_to'
     
    注:这里是View是通用视图,这里并没要导入的代码,详情请参考基于类的视图。
     
    还有更多的属性可供使用,可参考 AccessMixin 这个类。
     
     
    实现user_passes_test行为也是类似的,首先继承UserPassesTestMixin这个类(在最左边),然后在类的里面重写test_func方法,该方法也是返回布尔值。
     
    New in Django 1.9.
     
    from django.contrib.auth.mixins import UserPassesTestMixin
    
    class MyView(UserPassesTestMixin, View):
    
        def test_func(self):
            return self.request.user.email.endswith('@example.com')
    注:上述的两个也是不验证是否为活跃用户的,所以使用的时候要小心。
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    又见Python<4>:Pandas之DataFrame对象的使用
    又见Python<3>:Pandas之Series对象的使用
    使用tdload工具将本地数据导入到Teradata数据库中
    解决ubuntu系统root用户下Chrome无法启动问题
    又见Python<2>:如何安装第三方库(Windows)
    又见Python<1>:使用Anaconda搭建Python开发环境(Windows7)
    数据仓库原理<4>:联机分析处理(OLAP)
    数据仓库原理<3>:数据仓库与ODS
    配置hibernate,Struts。文件
    jQuery +ajax +json+实现分页
  • 原文地址:https://www.cnblogs.com/scolia/p/5786771.html
Copyright © 2011-2022 走看看