zoukankan      html  css  js  c++  java
  • Python+Django+SAE系列教程17-----authauth (认证与授权)系统1

          通过session,我们能够在多次浏览器请求中保持数据,接下来的部分就是用session来处理用户登录了。 当然,不能仅凭用户的一面之词,我们就相信,所以我们须要认证。

    当然了,Django 也提供了工具来处理这种常见任务(就像其它常见任务一样)。 Django 用户认证系统处理用户帐号,组,权限以及基于cookie的用户会话。这个系统一般被称为 auth/auth (认证与授权)系统。 这个系统的名称同一时候也表明了用户常见的两步处理。 我们须要:

    1.     验证 (认证) 用户是否是他所宣称的用户(一般通过查询数据库验证其username和password)

    2.     验证用户是否拥有运行某种操作的 授权 (一般会通过检查一个权限表来确认)


    依据这些需求,Django 认证/授权 系统会包括下面的部分:

    § 用户 :在站点注冊的人

    § 权限 :用于标识用户能否够运行某种操作的二进制(yes/no)标志

    §  :一种能够将标记和权限应用于多个用户的经常用法

    § Messages : 向用户显示队列式的系统消息的经常用法

    假设你已经用了admin工具(详见第6章),就会看见这些工具的大部分。假设你在admin工具中编辑过用户或组,那么实际上你已经编辑过授权系统的数据库表了。

    在我们运行manage.py syncdb的时候,在命令行工具中,就已经依据向导创建了第一个用户,以下我们先来看看怎样使用Django认证与授权系统做登陆和注销的功能。

    首先我们先改动一下urls.py

    from django.conf.urls import patterns, include, url
    from django.contrib.auth.views import login, logout
    
    # Uncomment the next two lines to enable the admin:
    # from django.contrib import admin
    # admin.autodiscover()
    
    urlpatterns = patterns('',
        # Examples:
        # url(r'^$', 'Bidding.views.home', name='home'),
        # url(r'^Bidding/', include('Bidding.foo.urls')),
    
        # Uncomment the admin/doc line below to enable admin documentation:
        # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    
        # Uncomment the next line to enable the admin:
        # url(r'^admin/', include(admin.site.urls)),
        url(r'^hello/$', 'Bidding.views.hello'),
        url(r'^time/$', 'Bidding.views.current_datetime'),
        url(r'^time/plus/(d{1,2})/$', 'Bidding.views.hours_ahead'),
        url(r'^hello_base/$', 'Bidding.views.hello_base'),
        url(r'^request_test/$', 'Bidding.views.request_test'),
        url(r'^UsersSearch/$', 'Bidding.Users.views.search_form'),
        url(r'^search/$', 'Bidding.Users.views.search'),
        url(r'^ClassRoom/add/$', 'person.views.ClassroonAdd'),
        url(r'^ClassRoom/list/$', 'person.views.ClassroonList'),
        url(r'^ClassRoom/modify/(d+)/$', 'person.views.ClassroonModify'),
        url(r'^ClassRoom/delete/(d+)/$', 'person.views.ClassroonDelete'),
        url(r'^testPIC/$', 'Bidding.views.my_image'),
        url(r'^testPDF/$', 'Bidding.views.hello_pdf'),
        url(r'^testCookie/show/$', 'Bidding.views.show_cookie'),
        url(r'^testCookie/set/(w+)/$', 'Bidding.views.set_cookie'),
        url(r'^testCookie/del/$', 'Bidding.views.del_cookie'),
        url(r'^testSession/show/$', 'Bidding.views.show_session'),
        url(r'^testSession/set/(w+)/$', 'Bidding.views.set_session'),
        url(r'^testSession/del/$', 'Bidding.views.del_session'),
    #url(r'^accounts/login/$',  login),
        url(r'^accounts/login/$',  login, {'template_name': 'login.html'}),
        url(r'^accounts/logout/$', logout),
                           
    )
    

    注意:login和logout函数是不须要我们写视图的,由于在urls.py的顶部我增加了:

    fromdjango.contrib.auth.views import login, logout

    也就是说这两个函数时Django默认的视图,以下的问题就出来了,假设视图的默认的,我们无从编辑,那么视图相应的模板呢?这个不用着急,在Djiango中,login相应的模板存放在:registragiton/login.html  (能够通过视图的额外參数 template_name 改动这个模板名称)。 这个表单必须包括 username 和 password 域。例如以下演示样例:一个简单的 template 看起来是这种。

    {% extends "base.html" %}
    
    {% block content %}
    
      {% if form.errors %}
        <p class="error">用户名密码错误!</p>
      {% endif %}
    
      <form action="" method="post">
    {% csrf_token %} 
        <label for="username">用户名:</label>
        <input type="text" name="username" value="" id="username">
        <label for="password">密码:</label>
        <input type="password" name="password" value="" id="password">
    
        <input type="submit" value="登录" />
        <input type="hidden" name="next" value="{{ next|escape }}" />
      </form>
    
    {% endblock %}
    

    假设用户登录成功,缺省会重定向到 /accounts/profile 。你能够提供一个保存登录后重定向URL的next隐藏域来重载它的行为。也能够把值以GET參数的形式发送给视图函数,它会以变量next的形式保存在上下文中,这样你就能够把它用在隐藏域上了。

    logout视图有一些不同。 默认情况下它渲染 registration/logged_out.html 模板(这个视图一般包括你已经成功退出的信息)。视图中还能够包括一个參数 next_page 用于退出后重定向。


    这时输入你之前创建的usernamepassword,就能够登录了。为了以后的学习,我们先建立一个页面为登陆后的默认页:

    新建welcom.html

    {% extends "base.html" %}
    
    {% block content %}
    
    <p>欢迎訪问本页面</p>
       <a href="../accounts/logout/">退出系统</a>
    
    
    {% endblock %}
    

    加入视图views.py

    def welcom(request):
           return render_to_response('welcom.html', locals())
    

    配置urls.py

    from django.conf.urls import patterns, include, url
    from django.contrib.auth.views import login, logout
    
    # Uncomment the next two lines to enable the admin:
    # from django.contrib import admin
    # admin.autodiscover()
    
    urlpatterns = patterns('',
        # Examples:
        # url(r'^$', 'Bidding.views.home', name='home'),
        # url(r'^Bidding/', include('Bidding.foo.urls')),
    
        # Uncomment the admin/doc line below to enable admin documentation:
        # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    
        # Uncomment the next line to enable the admin:
        # url(r'^admin/', include(admin.site.urls)),
        url(r'^hello/$', 'Bidding.views.hello'),
        url(r'^time/$', 'Bidding.views.current_datetime'),
        url(r'^time/plus/(d{1,2})/$', 'Bidding.views.hours_ahead'),
        url(r'^hello_base/$', 'Bidding.views.hello_base'),
        url(r'^request_test/$', 'Bidding.views.request_test'),
        url(r'^UsersSearch/$', 'Bidding.Users.views.search_form'),
        url(r'^search/$', 'Bidding.Users.views.search'),
        url(r'^ClassRoom/add/$', 'person.views.ClassroonAdd'),
        url(r'^ClassRoom/list/$', 'person.views.ClassroonList'),
        url(r'^ClassRoom/modify/(d+)/$', 'person.views.ClassroonModify'),
        url(r'^ClassRoom/delete/(d+)/$', 'person.views.ClassroonDelete'),
        url(r'^testPIC/$', 'Bidding.views.my_image'),
        url(r'^testPDF/$', 'Bidding.views.hello_pdf'),
        url(r'^testCookie/show/$', 'Bidding.views.show_cookie'),
        url(r'^testCookie/set/(w+)/$', 'Bidding.views.set_cookie'),
        url(r'^testCookie/del/$', 'Bidding.views.del_cookie'),
        url(r'^testSession/show/$', 'Bidding.views.show_session'),
        url(r'^testSession/set/(w+)/$', 'Bidding.views.set_session'),
        url(r'^testSession/del/$', 'Bidding.views.del_session'),
        url(r'^accounts/login/$',  login, {'template_name': 'login.html'}),
        url(r'^accounts/logout/$', logout),
        url(r'^welcom/$', 'Bidding.views.welcom'),                
    )
    

    建立这个页面,是为了登陆以后跳转到这里,而不是系统默认的/accounts/profile,因此我们要改动一下login.html的模板,在next隐藏域打上我们新建的这个页面的路径,例如以下:

    {% extends "base.html" %}
    
    {% block content %}
    
      {% if form.errors %}
        <p class="error">用户名密码错误!</p>
      {% endif %}
    
      <form action="" method="post">
    {% csrf_token %} 
        <label for="username">用户名:</label>
        <input type="text" name="username" value="" id="username">
        <label for="password">密码:</label>
        <input type="password" name="password" value="" id="password">
    
        <input type="submit" value="登录" />
        <input type="hidden" name="next" value="../../welcome/" />
      </form>
    
    {% endblock %}
    

    在执行一下试试看,效果达到了吧!


    正如我们上面所操心的,事实上welcom/页面假设没有登陆事实上也是能够訪问的,不用着急Django为我们提供了很简便的办法,我们仅仅须要在相应的视图上面加上一句@login_required 就能够了:

    @login_required
    def welcom(request):
           return render_to_response('welcom.html', locals())
    

    这就意味着本页面必须通过验证的用户才干够訪问,注意一定要在头部加上

    from django.contrib.auth.decorators import login_required

    才干够哦!

    我们在直接訪问welcom/试验一下吧:



    系统会自己主动定位到登陆页面,等我们登陆以后才会真正运行视图中的函数。

    事实上另一种情况,就是尽管登陆了,可是一些关键的页面也不能让某些用户訪问,这里就用到权限的管理了。以下我们就来重点讨论一下管理 Users, Permissions 和 Groups的过程:

    首先我们先模仿

    Python+Django+SAE系列教程13-----MySQL记录的添

    的样例制作一个用户标的基础数据库操作

    首先配置urls.py:

    from django.conf.urls import patterns, include, url
    from django.contrib.auth.views import login, logout
    
    # Uncomment the next two lines to enable the admin:
    # from django.contrib import admin
    # admin.autodiscover()
    
    urlpatterns = patterns('',
        # Examples:
        # url(r'^$', 'Bidding.views.home', name='home'),
        # url(r'^Bidding/', include('Bidding.foo.urls')),
    
        # Uncomment the admin/doc line below to enable admin documentation:
        # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    
        # Uncomment the next line to enable the admin:
        # url(r'^admin/', include(admin.site.urls)),
        url(r'^hello/$', 'Bidding.views.hello'),
        url(r'^time/$', 'Bidding.views.current_datetime'),
        url(r'^time/plus/(d{1,2})/$', 'Bidding.views.hours_ahead'),
        url(r'^hello_base/$', 'Bidding.views.hello_base'),
        url(r'^request_test/$', 'Bidding.views.request_test'),
        url(r'^UsersSearch/$', 'Bidding.Users.views.search_form'),
        url(r'^search/$', 'Bidding.Users.views.search'),
        url(r'^ClassRoom/add/$', 'person.views.ClassroonAdd'),
        url(r'^ClassRoom/list/$', 'person.views.ClassroonList'),
        url(r'^ClassRoom/modify/(d+)/$', 'person.views.ClassroonModify'),
        url(r'^ClassRoom/delete/(d+)/$', 'person.views.ClassroonDelete'),
        url(r'^testPIC/$', 'Bidding.views.my_image'),
        url(r'^testPDF/$', 'Bidding.views.hello_pdf'),
        url(r'^testCookie/show/$', 'Bidding.views.show_cookie'),
        url(r'^testCookie/set/(w+)/$', 'Bidding.views.set_cookie'),
        url(r'^testCookie/del/$', 'Bidding.views.del_cookie'),
        url(r'^testSession/show/$', 'Bidding.views.show_session'),
        url(r'^testSession/set/(w+)/$', 'Bidding.views.set_session'),
        url(r'^testSession/del/$', 'Bidding.views.del_session'),
        url(r'^accounts/login/$',  login, {'template_name': 'login.html'}),
        url(r'^accounts/logout/$', logout,{'next_page':'/accounts/login'}),
        url(r'^welcom/$', 'Bidding.views.welcom'),
        url(r'^User/add/$', 'Bidding.Users.views.CreateUser'),
        url(r'^User/list/$', 'Bidding.Users.views.UserList'),
        url(r'^User/modify/(d+)/$', 'Bidding.Users.views.UserModify'),
        url(r'^User/delete/(d+)/$', 'Bidding.Users.views.UserDelete'),
    )
    

    加入视图,改动后的bidding/users/view.py是这种:

    # -*- coding: utf-8 -*-
    from django.http import HttpResponse
    from django.shortcuts import render_to_response
    from django.template import RequestContext
    from django.contrib.auth.models import User
    
    def search_form(request):
        return render_to_response('Users/search_form.html')
    
    def search1(request):
        if 'q' in request.GET:
            message = '您搜索的keyword是: %r' % request.GET['q']
        else:
            message = '请输入您要检索的内容'
        return HttpResponse(message)
    
    def search(request):
        if 'q' in request.GET and request.GET['q']:
            q = request.GET['q']
            return render_to_response('Users/search_results.html',
                {'query': q})
        else:
            return render_to_response('Users/search_form.html', {'error': True})
        
    
    def CreateUser(request):
        if request.POST.has_key('username')  and request.POST.has_key('password') and request.POST.has_key('email') :
            username = request.POST['username']
            password = request.POST['password']
            email = request.POST['email']
            user = User.objects.create_user(username=username,
                                            email=email,
                                            password=password)
            user.save()
            return render_to_response('Users/User_Add_results.html',
                {'username': username},context_instance=RequestContext(request))
        else:
            return render_to_response('Users/User_Add.html', {'error': True},context_instance=RequestContext(request))
    
    def UserList(request):
            UserList=User.objects.all()
            return render_to_response('Users/User_List.html',
                {'UserList': UserList})
    
    
    def UserDelete(request,id1):
        
        GetHost=request.get_host()
        try:  
            GetHTTP_REFERER = request.META['HTTP_REFERER']  
        except KeyError:  
            GetHTTP_REFERER = 'unknown'
            
        if GetHTTP_REFERER!='unknown' and GetHTTP_REFERER.find(GetHost)>0:
            user=User.objects.get(id=id1)
            old_name = user.username
            user.delete()
            return render_to_response('Users/User_Delete_results.html',{'name':old_name})
        else:
            return render_to_response('Users/Error.html')
    
    
    def UserModify(request,id1):
    
        GetHost=request.get_host()
        try:  
            GetHTTP_REFERER = request.META['HTTP_REFERER']  
        except KeyError:  
            GetHTTP_REFERER = 'unknown'
            
        if GetHTTP_REFERER!='unknown' and GetHTTP_REFERER.find(GetHost)>0:
            user=User.objects.get(id=id1)
            old_username = user.username
            old_email = user.email
            old_password = user.password
            if request.POST.has_key('username')  and request.POST.has_key('email') and request.POST.has_key('password') :
                new_username = request.POST['username']
                new_email = request.POST['email']
                new_password = request.POST['password']
                user.username=new_username
                user.email=new_email
                user.set_password(new_password)
                #Django 在 ``django.contrib.auth`` 提供了2个函数: ``authenticate()``和 ``login()`` 。
                #假设通过给定的username与password做认证,请使用 ``authenticate()`` 函数。
                #user = authenticate(username=username,password=old_password)
                #自己改动密码时首先验证旧密码是否正确
                #user.password=new_password  #这样不行的
                user.save()
                return render_to_response('Users/User_Modify_results.html',
                    {'old_username': old_username,'old_email':old_email,'old_password':old_password,'new_username': new_username,'new_email':new_email,'new_password':new_password},context_instance=RequestContext(request))
            else:
                return render_to_response('Users/User_Modify.html', {'error': True,'id':id1,'username':old_username,'email':old_email,'password':old_password},context_instance=RequestContext(request))
        else:
            return render_to_response('Users/Error.html')
    

    注意在改动和读取password的时候:

     由于数据库中存储的django加密以后的password,我们在读取的时候是一串加密后的字符串,这里不可以显示的表现出来,假设改动password用简单的user.password=new_password,也是不行的,必须使用user.set_password(new_password)来改动密。#假设用户自己改动password时首先验证旧password是否正确,可以通过给定的username和password做认证,请使用``authenticate()`` 函数,代码例如以下:记得要导入django.contrib.auth

    <span style="font-weight: normal;">from django.contrib import auth
    
     user =authenticate(username=username,password=old_password)</span>

    以下是一些模板,我把它们放在了Bidding/templates/Users中了

    User_Add.html

    <span style="font-weight: normal;"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
    <html>
    <head>
        <title>数据库操作简单表的加入</title>
    </head>
    <body>
        <h1>这里是用户的加入页面</h1>
        {% if error %}
            <p style="color: red;">请输入username、邮箱和password</p>
        {% endif %}
       <form action="" method="post">
       {% csrf_token %} 
            <table border="1" cellpadding="10">
              <tr>
                <td align="center">项目</td>
                <td align="center">内容</td>
              </tr>
              <tr>
                <td align="right">username:</td>
                <td><input type="text" name="username"></td>
              </tr>
              <tr>
                <td align="right">password:</td>
                <td><input type="text" name="password"></td>
              </tr>
              <tr>
                <td align="right">邮箱:</td>
                <td><input type="text" name="email"></td>
              </tr>
              <tr>
                <td colspan="2"><input type="submit" value="加入"></td>
              </tr>
            </table>
      </form>
      
    </body>
    </html></span>
    

    User_Add_results.html

    <span style="font-weight: normal;"><html>
    <head>
        <title>查询用户结果页</title>
    </head>
    <body>
        <table border="1" cellpadding="5"><tr>
          <td>用户:{{username}}加入成功 !</td></tr>
          <tr>
            <td><a href="http://127.0.0.1:8000/User/add/">点击返回</a></td>
          </tr>
        </table>
    </body>
    </html></span>
    

    User_Delete_results.html

    <span style="font-weight: normal;"><html>
    <head>
        <title>查询用户结果页</title>
    </head>
    <body>
        <table border="1" cellpadding="5"><tr>
          <td>用户:{{name}}删除成功 !</td></tr>
          <tr>
            <td><a href="http://127.0.0.1:8000/User/list/">点击返回</a></td>
          </tr>
        </table>
    </body>
    </html>
    </span>

    User_List.html

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
    <html>
    <head>
        <title>用户管理</title>
    </head>
    <body>
        <h1>这里是User的管理页面</h1>
            <table border="1" cellpadding="10">
              <tr>
                <td align="center">序号</td>
                <td align="center">用户名</td>
                <td align="center">邮箱</td>
                <td align="center">操作</td>
              </tr>
              {% for myuser in UserList%}
              <tr>
                <td align="right">{{ myuser.id }}</td>
                <td align="right">{{ myuser.username }}</td>
                <td align="right">{{ myuser.email }}</td>
                <td align="right">
                <a href="../modify/{{ myuser.id }}">改动</a>
                <a href="../delete/{{ myuser.id }}">删除</a>
            
                </td>
              </tr>
              {% endfor %} 
            </table>
    </body>
    </html>
    

    User_Modify.html

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
    <html>
    <head>
        <title>数据库操作简单表的改动</title>
    </head>
    <body>
        <h1>这里是User--{{username}}的改动页面</h1>
        {% if error %}
            <p style="color: red;">请输入班级名称和导师姓名</p>
        {% endif %}
        <form action="" method="post">
       {% csrf_token %} 
            <table border="1" cellpadding="10">
              <tr>
                <td align="center">项目</td>
                <td align="center">内容</td>
              </tr>
              <tr>
                <td align="right">用户名:</td>
                <td><input type="text" name="username" value="{{username}}"></td>
              </tr>
              <tr>
                <td align="right">邮箱:</td>
                <td><input type="text" name="email" value="{{email}}"></td>
              </tr>
    		  <tr>
                <td align="right">密码:</td>
                <td><input type="text" name="password" value="{{password}}"></td>
              </tr>
              <tr>
                <td colspan="2">
                <input type="hidden" name="id" value="{{id}}">
                <input type="submit" value="改动">
                <input type="button" value="返回" onClick="location.href='../../list'">
                </td>
              </tr>
            </table>
      </form>
    </body>
    </html>
    

    User_Modify_results.html

    <html>
    <head>
        <title>查询用户结果页</title>
    </head>
    <body>
        <table border="1" cellpadding="5"><tr>
          <td align="center"> </td>
          <td align="center">改动前</td>
          <td align="center">改动后</td>
          </tr>
          <tr>
            <td align="right">用户名:</td>
            <td align="right">{{old_username}}</td>
            <td align="right">{{new_username}}</td>
          </tr>
          <tr>
            <td align="right">邮箱:</td>
            <td align="right">{{old_email}}</td>
            <td align="right">{{new_email}}</td>
          </tr>
    	   <tr>
            <td align="right">密码:</td>
            <td align="right">{{old_password}}</td>
            <td align="right">{{new_password}}</td>
          </tr>
          <tr>
            <td colspan="3" align="center">改动成功!</td>
          </tr>
          <tr>
            <td colspan="3" align="center"><a href="../../list/">点击返回</a></td>
          </tr>
        </table>
    </body>
    </html>
    

    这样我们就做好了一个管理用户信息的页面了,用我们新加入的用户也能够登录之前的那个登录页面了。以下就是怎样对这些用户设置详细的权限。


  • 相关阅读:
    在 Laravel 5.1 中使用 Pjax
    在 iOS 中实现方法链调用
    利用 WireShark 深入调试网络请求
    设计一个健壮的后台下载
    设计一个健壮的大型文件下载系统
    iOS开发基础知识:Core Animation(核心动画)
    开发 Swift 和 Objective-C 混编的 Framework
    protobuf3 iOS 接入 protobuf
    iOS之ProtocolBuffer搭建
    iOS10 推送必看(基础篇)
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/3865493.html
Copyright © 2011-2022 走看看