day76---Django的认证系统

1. Cookie和Session的介绍

http://www.cnblogs.com/yange/articles/8359446.html#_label0

2. Django中操作Cookie

http://www.cnblogs.com/yange/articles/8359446.html#_label1

3. Django中操作Session

http://www.cnblogs.com/yange/articles/8359446.html#_label2

4. 用户认证

auth模块

  • 描述:Django自带的一套认证系统,使用django默认的数据库表进行管理

  • 说明:

    • 使用auth_user表作为用户表
    • request.user封装了用户登录信息的对象,类型是<class 'django.utils.functional.SimpleLazyObject'>
      • 如果是已登录用户,则对象名是已登录的用户
      • 如果是没有登录的用户,则对象名是AnonymousUser
  • 控制台创建超级用户:createsuperuser

  • 导入模块

    from django.contrib import auth
  • authenticate()方法:提供用户认证功能,对用户名、密码的正确性进行验证,需要提供username、password两个参数

    • password字段是加密后进行存储,authenticate()方法在校验之前会进行加密后再进行对比校验,不能直接使用User.objects.filter()的方式进行过滤
    • 如果认证成功,会返回一个User对象(当前用户对应的那条记录的对象)
    • 如果认证不成功,则返回None
    • authenticate()会在User对象上设置一个属性标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的。当我们试图登陆一个从数据库中直接取出来不经过authenticate()的User对象会报错的
    • 示例:
        # 校验用户名密码是否正确(校验成功返回User对象,否则user_obj为None)
        user_obj = auth.authenticate(username=user, password=pwd)
    
  • login(HttpRequest, user)方法:需要接收一个HttpRequest对象和一个已经认证过的User对象,使用Django中的session框架针对已经认证的User对象附加上session id等信息

    # 写入session
    auth.login(request, user_obj)
  • logout(request):注销用户,需要接收一个HttpRequest对象,没有返回值。调用logout方法时,当前用户请求的session信息会全部被清除,如果没有登录(没有session信息)也不会报错。调用logout()方法其实就是执行了request.session.flush()

    # 清除当前请求用户的session信息
    auth.logout(request)
  • 装饰器函数login_required():限制用户登录,未登录用户无法访问指定的页面。默认情况下,如果用户没有登录,会跳转到URL '/accounts/login/' (这个值可以在settings文件中通过LOGIN_URL进行修改),并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)

    from django.contrib.auth.decorators import login_required
    @login_required
    def index(request):
        return render(request, 'index.html')

User对象

  • User对象属性:username,password(必填项)password用哈希算法保存到数据库,其他字段可以为空

  • is_staff:用户是否拥有网站的管理权限(是否是超级用户)

  • is_active:是否允许用户登录,设置为False0表示可以不用删除用户来禁止用户登录

  • is_authenticated()方法:判断当前用户是否是已登录用户,已登录返回True,未登录返回False

    • 限制用户登录之后才能访问的页面
    • 如果用户没有登录则返回登录页面
    • 用户从其他页面跳转到登录页面,登录成功后,会自动跳转到之前访问的页面
    • 示例:
        # 获取当前用户的对象
        user_obj = request.user
        # 判断当前用户是否已经登陆,返回True表示已登录,False表示未登录
        if not user_obj.is_authenticated():
            return redirect('/login/')
    
  • create_user()create_superuser():创建用户或超级用户(由于password是加密存储的,所以不能使用ORM的User.obects.create()的方式进行添加用户。create_user()create_superuser()会自动针对password的值进行加密后再存储)

    # 添加新用户
    new_user_obj = User.objects.create_user(username=username, password=password, email=email)
    # 新注册用户免登录
    auth.login(request, new_user_obj)
  • check_password(passwd):检查密码(用户需要修改密码的时候 首先要先输入原来的密码,如果给定的字符串通过了密码检查,返回True,否则返回False)

    # 获取当前登录用户的对象
    user_obj = request.user
    # 获取输入的老密码
    old_pwd = request.POST.get('old_password')
    # 针对老密码进行校验
    if user_obj.check_password(old_pwd):
        print('OK')
    else:
        print('ERROR')
  • set_password():修改密码(先获取用户对象,然后调用方法进行修改,最后需要使用save()方法进行保存)

    # 获取当前登录用户的对象
    user_obj = request.user
    # 获取输入的老密码
    new_pwd = request.POST.get('new_password')
    repeat_pwd = request.POST.get('repeat_password')
    # 针对两次新密码进行校验
    if new_pwd == repeat_pwd:
        # 修改密码,并保存
        user_obj.set_password(new_pwd)
        user_obj.save()

5. 认证系统的应用

指定认证系统的用户表为应用中的模型(settings.py)

    AUTH_USER_MODEL = 'app01.UserInfo'

配置路由器系统(urls.py)

    from django.conf.urls import url
    from app01 import views
    urlpatterns = [
        url(r'^index/', views.index),
        url(r'^login/', views.log_in),
        url(r'^logout/', views.log_out),
        url(r'^set_pwd/', views.set_pwd),
    ]

扩展认证系统用户表的表结构(models.py)

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    class UserInfo(AbstractUser):
        nickname = models.CharField(max_length=32, null=True)
        telephone = models.BigIntegerField(null=True)

配置视图函数(views.py)

    from django.shortcuts import render, redirect
    from django.http import JsonResponse
    from .models import *
    from django.contrib import auth
    def log_in(request):
        if request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            login_response = {'user': None, 'err_msg': None}
            user_obj = auth.authenticate(username=user, password=pwd)
            if user_obj:
                login_response['user'] = user_obj.username
                auth.login(request, user_obj)
            else:
                login_response['err_msg'] = '用户名密码错误'
            return JsonResponse(login_response)
        return render(request, 'login.html')
    def log_out(request):
        auth.logout(request)
        return redirect('/login/')
    def index(request):
        if not request.user.is_authenticated():
            return redirect('/login/')
        return render(request, 'index.html')
    def set_pwd(request):
        user_obj = UserInfo.objects.get(username=request.user)
        set_pwd_response = {'user': user_obj.username, 'err_msg': None}
        if request.is_ajax():
            old_pwd = request.POST.get('old_pwd')
            new_pwd = request.POST.get('new_pwd')
            repeat_new_pwd = request.POST.get('repeat_new_pwd')
            if user_obj.check_password(old_pwd):
                if not new_pwd:
                    set_pwd_response['err_msg'] = '密码不能为空'
                elif new_pwd != repeat_new_pwd:
                    set_pwd_response['err_msg'] = '两次密码输入不一致'
                else:
                    request.user.set_password(new_pwd)
                    request.user.save()
            else:
                set_pwd_response['err_msg'] = '原密码错误'
            return JsonResponse(set_pwd_response)
        return render(request, 'index.html')

配置模版页面(login.html和index.html)

    {# login.html #}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
        <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
        <title>登录页面</title>
    </head>
    <body>
    <div class="container">
        <div class="row">
            <div class="col-md-offset-3 col-md-8">
                <div class="page-header">
                    <h1>
                        登录页面
                        <small>login</small>
                    </h1>
                </div>
                <form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="user" class="col-md-2 control-label">用户名:</label>
                        <div class="col-md-5">
                            <input type="text" class="form-control" id="user" placeholder="用户名" autocomplete="off">
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="pwd" class="col-md-2 control-label">密码:</label>
                        <div class="col-md-5">
                            <input type="password" class="form-control" id="pwd" placeholder="密码" autocomplete="off">
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-md-offset-2 col-md-10">
                            <div class="checkbox">
                                <label>
                                    <input type="checkbox">记住我
                                </label>
                            </div>
                        </div>
                    </div>
                    <p class="col-md-offset-3 err_msg"></p>
                    <div class="form-group">
                        <div class="col-md-offset-2 col-md-5">
                            <button type="button" id="login" class="btn btn-primary btn-block">登录</button>
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <script>
        // 登录校验
        $("#login").click(function () {
            $.ajax({
                url: "/login/",
                type: "post",
                data: {
                    "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(),
                    "user": $("#user").val(),
                    "pwd": $("#pwd").val()
                },
                success: function (data) {
                    if (data.user) {
                        location.href = '/index/'
                    } else {
                        $(".err_msg").html(data.err_msg).css({
                            "color": "red",
                            "font-size": 20,
                            "font-weight": 700
                        });
                    }
                }
            })
        });
        setInterval(function () {
            $(".err_msg").html("")
        }, 2000)
    </script>
    </body>
    </html>
    {# index.html #}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
        <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
        <title>首页</title>
    </head>
    <body>
    <div class="container">
        <div class="row">
            <div class="col-md-offset-3 col-md-5">
                <div class="page-header">
                    <h1>
                        首页
                        <small>index</small>
                    </h1>
                </div>
                <div>
                    <div class="col-md-6">
                        <a href="/logout/" class="btn btn-success">注销退出</a>
                    </div>
                    <div class="col-md-offset-9">
                        <a class="set_pwd btn btn-danger">修改密码</a>
                    </div>
                </div>
                <hr>
                <div>
                    <form class="form-horizontal hidden" action="" method="post" enctype="multipart/form-data">
                        {% csrf_token %}
                        <div class="form-group">
                            <label for="old_pwd" class="col-md-3 control-label">原密码:</label>
                            <div class="col-md-8">
                                <input type="password" class="form-control" id="old_pwd" placeholder="原密码">
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="new_pwd" class="col-md-3 control-label">新密码:</label>
                            <div class="col-md-8">
                                <input type="password" class="form-control" id="new_pwd" placeholder="新密码">
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="repeat_new_pwd" class="col-md-3 control-label">确认新密码:</label>
                            <div class="col-md-8">
                                <input type="password" class="form-control" id="repeat_new_pwd" placeholder="确认新密码">
                            </div>
                        </div>
                        <p class="col-md-offset-4 err_msg"></p>
                        <div class="form-group">
                            <div class="col-md-offset-4">
                                <input type="button" id="set_pwd" class="btn btn-primary col-md-3" value="提交">
                                <input type="reset" id="cancel" class="btn btn-warning col-md-offset-2 col-md-3" value="取消">
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
    <script>
        // 显示修改密码的输入框
        $(".set_pwd").click(function () {
            $(".form-horizontal").removeClass("hidden")
        });
        // 修改密码校验
        $("#set_pwd").click(function () {
            $.ajax({
                url: "/set_pwd/",
                type: "post",
                data: {
                    "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(),
                    "old_pwd": $("#old_pwd").val(),
                    "new_pwd": $("#new_pwd").val(),
                    "repeat_new_pwd": $("#repeat_new_pwd").val()
                },
                success: function (data) {
                    if (!data.err_msg) {
                        location.href = '/index/'
                    } else {
                        $(".err_msg").html(data.err_msg).css({
                            "color": "red",
                            "font-size": 20,
                            "font-weight": 700
                        });
                    }
                }
            })
        });
        setInterval(function () {
            $(".err_msg").html("")
        }, 2000)
    </script>
    </body>
    </html>
posted @ 2018-03-01 09:33  _岩哥  阅读(105)  评论(0)    收藏  举报