用户认证组件

2.示例学习:用户认证、登录(全局request.user)、匿名用户、注册、注销、认证装饰器(next)...

项目文件/settings.py

数据库 略!

LOGIN_URL = "/login/"

项目文件/urls.py

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('login/', views.login),
    path('index/', views.index),
    path('logout/', views.logout),
    path('reg/', views.reg),
    path('order/', views.order),

]

app01.views.py

from django.shortcuts import render,HttpResponse,redirect

# 导入auth模块
from django.contrib import auth

# 对应数据库迁移django自带的 auth_user表的 对象
from django.contrib.auth.models import User

# 登录装饰器
# 在setting.py 配置 LOGIN_URL = "/login/"
# 如果没有登录就访问index路径,就会跳转到/login/页面
# 必须配置,否则将会跳转到默认的一个不相干的路径
from django.contrib.auth.decorators import login_required

def login(request):
    if request.method == "POST":
        username = request.POST.get("user")
        pwd = request.POST.get("pwd")

        """auth.authenticate() 
        提供了用户认证,即验证用户名以及密码是否正确,一般需要username  password两个关键字参数
        如果认证信息有效,会返回一个  User  对象。authenticate()会在User 对象上设置一个属性
        标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的。当我们试图登陆一个从数
        据库中直接取出来不经过authenticate()的User对象会报错的!!
        
        使用用户组件更严谨,比如同一个浏览器登录不同的用户,对应
        的session信息 django_session表中的session_key就会跟换,
        而直接用session操作只替换session_data
        """  # 验证成功,返回user对象,否则返回None, 这个过程会将pwd进行hash后比较
        user = auth.authenticate(username=username, password=pwd)
        print(username)
        print(pwd)
        print(user)

        # 如下直接调用 auth_user 表进行过滤,返回None,因为auth_user中对应的
        # passward字段是存的hash后的密文。
        # User.objects.filter(username=username,passward=pwd)

        if user:
            # @@@@@@@@@@@@@@@@@@@@@@@@
            auth.login(request, user)
            # 上面一行代码一执行,会生成 当前登录对象
            # request.user = user 并注册对应的 session 记录
            # 下次访问的时候直接用request.user就可以得到用户对象
            # 未登录状态,request.user为匿名用户 AnonymousUser

            # 基于用户认证装饰器,由于路径是写在请求头中的
            # 所以要通过从GET中获取!
            # (注意,这里并不与POST方法冲突,这里的GET只是请求中对应的字典)
            # 如果没有取到next,默认/index/
            next_url = request.GET.get("next", "/index/")
            return redirect(next_url)


    return render(request, "login.html")


# 基于用户认证组件的认证装饰器
@login_required
def index(request):
    print("request.user:", request.user)
    """
    未登录状态访问index,打印匿名用户  request.user: AnonymousUser
    
匿名用户:
    class models.AnonymousUser
    django.contrib.auth.models.AnonymousUser 类实现了django.contrib.auth.models.User 接口,但具有下面几个不同点:

    id 永远为None。
    username 永远为空字符串。
    get_username() 永远返回空字符串。
    is_staff 和 is_superuser 永远为False。
    is_active 永远为 False。
    groups 和 user_permissions 永远为空。
    is_anonymous() 返回True 而不是False。
    is_authenticated() 返回False 而不是True。
    set_password()、check_password()、save() 和delete() 引发 NotImplementedError。
    New in Django 1.8:
    新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。
    
    request.user为全局变量,可以不用通过render
    传递给模板直接在模板中使用就可以
    
    """
    # 如果是匿名用户则为空
    print("request.user.id:", request.user.id)
    # 判断当前是否为匿名用户
    print("匿名用户?", request.user.is_anonymous)

    # if request.user.is_anonymous:
    # if not request.user.is_authenticated:
    #     return redirect("/login/")
    """user对象的 is_authenticated()
    如果是真正的 User 对象,返回值恒为 True 。 用于检查用户
    是否已经通过了认证。通过认证并不意味着用户拥有任何权限,甚至
    也不检查该用户是否处于激活状态,这只是表明用户成功的通过了认证。 
    这个方法很重要, 在后台用request.user.is_authenticated()
    判断用户是否已经登录,如果true则可以向前台展示request.user.name
    """

    return render(request, "index.html")

# 注销

def logout(request):
    """
    auth.logout(request)注销功能
    """
    auth.logout(request)
    return redirect("/login/")


# 基于用户认证组件的注册用户功能
# from django.contrib.auth.models import User 这个User就是表类对象
# 对应 django迁移自动生成的 auth_user 表
def reg(request):
    if request.method == "POST":
        username = request.POST.get("user")
        pwd = request.POST.get("pwd")

        # 千万不要这样操作,原因是这样不会hash密码!
        # User.objects.create(username=username, password=pwd)
        # 应该如下操作
        user = User.objects.create_user(username=username, password=pwd)

        return redirect("/login/")
    else:
        return render(request,"reg.html")

# 第一次访问order,没登录,跳转到login,
# 此时路径变为 http://127.0.0.1:8000/login/?next=/order/
# 当登陆后要求跳转到order, 在当前逻辑下,可在login视图函数中中获取next键值对,进行跳转。
@login_required
def order(request):

    return HttpResponse("Hi, %s ,order welcome you!" % request.user.username)

templates/login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
        <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row text-center"><h2 style="color: rgba(15,159,99,0.94)">登录</h2></div>
        <div class="row" style="padding: 0 18%;margin-top:50px;">
            <form action="" method="post">
                {% csrf_token %}
              <div class="form-group">
                <label for="user">用户名</label>
                <input type="text" class="form-control" id="user" placeholder="用户名" name="user">
              </div>
              <div class="form-group">
                <label for="Password">密码</label>
                <input type="password" class="form-control" id="Password" placeholder="密码" name="pwd">
              </div>
              <button type="submit" class="btn btn-default">提交</button>
            </form>
        </div>
    </div>
</body>
</html>

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
        <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
    <div class="row">
         <a href="/logout/" class="pull-right">注销</a>
    <div class="row text-center">
            {# request.user为全局变量,可以直接使用#}
        <h2 style="color: rgba(15,159,99,0.94)">Hi, {{ request.user.username }}</h2>
    </div>
</body>
</html>

templates/reg.html

与login.html代码一样!
posted @ 2018-08-13 23:46  哈哈大圣  阅读(100)  评论(0编辑  收藏  举报