码迷,mamicode.com
首页 > 其他好文 > 详细

16 django用户认证组件

时间:2019-08-17 11:01:41      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:bug   als   变量   action   接受   index   nim   cti   event   

django用户认证组件

思考:

  前一篇提到的seesion,当用户登录后会保存session。

  浏览器再次访问会带上服务器返回的session:sessionid ---> 登录时随机生成的key

  服务器拿到sessionid后去数据库匹配,匹配到后拿到一个字典数据:{a:b,c:d}

  当数据有变化时,会更新某个值,如 c:d --> c:e ,那么直接更新数据库 {a:b,c:e},sessionid并不会变化,然后将原来的sessionid继续回传给浏览器。

  这样的处理机制存在什么样的问题呢?

问题:

  A在浏览器登录,登录信息是A用户的,比如服务器的一些权限控制,角色控制信息,这个时候保存在seesion库里,当B又用浏览器登录,因为用一个浏览器,传给服务器的sessionid是一样的,那么在更新B的数据的时候,可能部分A的信息,并不会删掉,服务器会在A的基础上做更新,那么就存在数据错乱的风险,B获得A的敏感信息。

解决:

  判断是不是同一个用户,不同用户,同一个sessionid,先清空A的信息,再写入B的信息。

  我们当然可以自己做一套,但是django已经帮我们实现了,我们直接用就好,这就是用户认证组件。

 

先settings配置好数据库,然后运行以下命令进行数据库初始化,因为要用到其中的session表。

技术图片
  1 """
  2 Django settings for auther project.
  3 
  4 Generated by ‘django-admin startproject‘ using Django 2.2.3.
  5 
  6 For more information on this file, see
  7 https://docs.djangoproject.com/en/2.2/topics/settings/
  8 
  9 For the full list of settings and their values, see
 10 https://docs.djangoproject.com/en/2.2/ref/settings/
 11 """
 12 
 13 import os
 14 
 15 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 17 
 18 
 19 # Quick-start development settings - unsuitable for production
 20 # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
 21 
 22 # SECURITY WARNING: keep the secret key used in production secret!
 23 SECRET_KEY = 6y-h4%y^%+2^@_2y7xyz0fc98faozkvh(xp!)h4)q8n0hsx+ee
 24 
 25 # SECURITY WARNING: don‘t run with debug turned on in production!
 26 DEBUG = True
 27 
 28 ALLOWED_HOSTS = []
 29 
 30 
 31 # Application definition
 32 
 33 INSTALLED_APPS = [
 34     django.contrib.admin,
 35     django.contrib.auth,
 36     django.contrib.contenttypes,
 37     django.contrib.sessions,
 38     django.contrib.messages,
 39     django.contrib.staticfiles,
 40     auth_app01,
 41 ]
 42 
 43 MIDDLEWARE = [
 44     django.middleware.security.SecurityMiddleware,
 45     django.contrib.sessions.middleware.SessionMiddleware,
 46     django.middleware.common.CommonMiddleware,
 47     django.middleware.csrf.CsrfViewMiddleware,
 48     django.contrib.auth.middleware.AuthenticationMiddleware,
 49     django.contrib.messages.middleware.MessageMiddleware,
 50     django.middleware.clickjacking.XFrameOptionsMiddleware,
 51 ]
 52 
 53 ROOT_URLCONF = auther.urls
 54 
 55 TEMPLATES = [
 56     {
 57         BACKEND: django.template.backends.django.DjangoTemplates,
 58         DIRS: [os.path.join(BASE_DIR, templates)],
 59         APP_DIRS: True,
 60         OPTIONS: {
 61             context_processors: [
 62                 django.template.context_processors.debug,
 63                 django.template.context_processors.request,
 64                 django.contrib.auth.context_processors.auth,
 65                 django.contrib.messages.context_processors.messages,
 66             ],
 67         },
 68     },
 69 ]
 70 
 71 WSGI_APPLICATION = auther.wsgi.application
 72 
 73 
 74 # Database
 75 # https://docs.djangoproject.com/en/2.2/ref/settings/#databases
 76 
 77 # DATABASES = {
 78 #     ‘default‘: {
 79 #         ‘ENGINE‘: ‘django.db.backends.sqlite3‘,
 80 #         ‘NAME‘: os.path.join(BASE_DIR, ‘db.sqlite3‘),
 81 #     }
 82 # }
 83 
 84 
 85 # Password validation
 86 # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
 87 
 88 AUTH_PASSWORD_VALIDATORS = [
 89     {
 90         NAME: django.contrib.auth.password_validation.UserAttributeSimilarityValidator,
 91     },
 92     {
 93         NAME: django.contrib.auth.password_validation.MinimumLengthValidator,
 94     },
 95     {
 96         NAME: django.contrib.auth.password_validation.CommonPasswordValidator,
 97     },
 98     {
 99         NAME: django.contrib.auth.password_validation.NumericPasswordValidator,
100     },
101 ]
102 
103 
104 # Internationalization
105 # https://docs.djangoproject.com/en/2.2/topics/i18n/
106 
107 LANGUAGE_CODE = en-us
108 
109 TIME_ZONE = UTC
110 
111 USE_I18N = True
112 
113 USE_L10N = True
114 
115 USE_TZ = True
116 
117 
118 # Static files (CSS, JavaScript, Images)
119 # https://docs.djangoproject.com/en/2.2/howto/static-files/
120 
121 STATIC_URL = /static/
122 STATICFILES_DIRS = [
123     os.path.join(BASE_DIR, statics)
124 ]
125 
126 LOGIN_URL = /app01/login
127 
128 DATABASES = {
129     default: {
130         ENGINE: django.db.backends.mysql,
131         NAME:auth,# 要连接的数据库,连接前需要创建好
132         USER:root,# 连接数据库的用户名
133         PASSWORD:‘‘,# 连接数据库的密码
134         HOST:127.0.0.1,# 连接主机,默认本级
135         PORT:3308 #  端口 默认3306
136     }
137 }
138 
139 LOGGING = {
140     version: 1,
141     disable_existing_loggers: False,
142     handlers: {
143         console:{
144             level:DEBUG,
145             class:logging.StreamHandler,
146         },
147     },
148     loggers: {
149         django.db.backends: {
150             handlers: [console],
151             propagate: True,
152             level:DEBUG,
153         },
154     }
155 }
settings

python manage.py makemigrations

python manage.py migrate

 

视图函数

  1 from django.shortcuts import render, redirect, HttpResponse
  2 from auth_app01.myforms import Form, LoginForm
  3 from django.contrib import auth
  4 from django.contrib.auth.models import User
  5 from django.contrib.auth import authenticate, login, logout
  6 from django.contrib.auth.decorators import login_required
  7 from auther import settings
  8 
  9 
 10 def index(request):
 11     if not request.user.is_authenticated:
 12         print(request.user)
 13     else:
 14         print(no user)
 15     return render(request, index.html)
 16 
 17 
 18 def regist(request):
 19     if request.method == POST:
 20         form = Form(request.POST)
 21         if form.is_valid():
 22             print(form.cleaned_data)
 23             username = form.cleaned_data[name]
 24             email = form.cleaned_data[email]
 25             pwd = form.cleaned_data[pwd]
 26             user = None
 27 
 28             # 注意创建用户的时候要用create_user方法  用create的话不会对密码进行加密
 29             res = User.objects.create_user(username=username,email=email,password=pwd)
 30 
 31             # 注册完成之后 调用 authenticate() 进行认证得到一个  User  对象
 32             if res:
 33                 user = authenticate(username=username, password=pwd)
 34 
 35             # login函数接受一个HttpRequest对象,以及一个认证了的User对象
 36             # login函数使用django的session框架给某个已认证的用户附加上sessionid等信息
 37             # 链接跳转到index后 会带上sessionid信息,且 request.user 定义成了一个全局变量任何地方都可以用,包括模板
 38             if user:
 39                 login(request, user)
 40 
 41             return redirect(/app01/index/)
 42         else:
 43             print(form.cleaned_data)
 44             print(form.errors)
 45         return render(request, regist.html, locals())
 46     else:
 47         form = Form()
 48         return render(request, regist.html, locals())
 49 
 50 
 51 def mylogin(request):
 52     if request.method == POST:
 53         form = LoginForm(request.POST)
 54         if form.is_valid():
 55             print(form.cleaned_data)
 56             username = form.cleaned_data.get(name)
 57             pwd = form.cleaned_data.get(pwd)
 58             user = auth.authenticate(username=username,password=pwd)
 59             if user:
 60                 login(request, user)
 61                 # next_url 用户请求可能是其他请求重定向过来的,登录完成后,根据next值返回到相应的url
 62                 next_url = request.GET.get(next, /app01/index)
 63                 return redirect(next_url)
 64             else:
 65                 error = 用户名或密码错误!
 66                 return render(request, login.html, locals())
 67     else:
 68         form = LoginForm()
 69         return render(request, login.html, locals())
 70 
 71 
 72 def mylogout(request):
 73     # 接受一个HttpRequest对象,无返回值。调用时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
 74     logout(request)
 75     return redirect( /app01/index/)
 76 
 77 
 78 # 上面通过auth已经实现了简单的登录注册以及首页之间的跳转 但是实际场景存在这样的情况:
 79 # 1  用户登陆后才能访问某些页面,
 80 # 2  如果用户没有登录就访问该页面的话直接跳到登录页面
 81 # 3  用户在跳转的登陆界面中完成登陆后,自动访问跳转到之前访问的地址
 82 
 83 # 方式一
 84 def secret(request):
 85     if request.user.is_authenticated:
 86         my_secret = secret
 87         return render(request, secret.html,locals())
 88     else:
 89         return redirect("%s?next=%s" % (settings.LOGIN_URL, request.path))
 90 
 91 # 方式二  login_required 装饰器
 92 #若用户没有登录,则会跳转到django默认的 登录URL ‘/accounts/login/ ‘ (这个值可以在settings文件中通过LOGIN_URL进行修改)。
 93 # 并传递  当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。
 94 @login_required
 95 def mimi(request):
 96     my_secret = mimi
 97     return render(request, secret.html,locals())
 98 
 99 
100 # 修改密码
101 @login_required
102 def set_password(request):
103     user = request.user
104     state = None
105     if request.method == POST:
106         old_password = request.POST.get(old_password, ‘‘)
107         new_password = request.POST.get(new_password, ‘‘)
108         repeat_password = request.POST.get(repeat_password, ‘‘)
109         if user.check_password(old_password):
110             if not new_password:
111                 state = empty
112             elif new_password != repeat_password:
113                 state = repeat_error
114             else:
115                 user.set_password(new_password)
116                 user.save()
117                 return redirect("/app01/login/")
118         else:
119             state = password_error
120     content = {
121         user: user,
122         state: state,
123     }
124     return render(request, password.html, content)

 

forms组件

 1 from django import forms
 2 from django.forms import widgets
 3 from django.core.exceptions import ValidationError
 4 from django.contrib.auth.models import User
 5 
 6 
 7 name_widget = widgets.TextInput(attrs={class:form-control})
 8 pwd_widget = widgets.PasswordInput(attrs={class:form-control})
 9 
10 
11 class Form(forms.Form):
12     name = forms.CharField(min_length=4, max_length=16, widget=name_widget, label=用户名)
13     pwd = forms.CharField(min_length=4, max_length=16, widget=pwd_widget, label=密码)
14     email = forms.EmailField(widget=name_widget, label=邮箱)
15 
16     def clean_name(self):
17         val = self.cleaned_data.get(name)
18         res = User.objects.filter(username=val).exists()
19         if not res:
20             return val
21         else:
22             raise ValidationError(用户名已存在!)
23 
24 
25 class LoginForm(forms.Form):
26     name = forms.CharField(min_length=4, max_length=16, widget=name_widget, label=用户名)
27     pwd = forms.CharField(min_length=4, max_length=16, widget=pwd_widget, label=密码)

 

url分发器

from django.urls import path, re_path
from auth_app01 import views


urlpatterns = [
    path(index/, views.index),
    path(regist/, views.regist),
    path(login/, views.mylogin),
    path(logout/, views.mylogout),
    path(secret/, views.secret),
    path(mimi/, views.mimi),
]

 

index.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>index</title>
 6     <link rel="stylesheet" href="/static/bootstrap.min.css">
 7 </head>
 8 <body>
 9 <div class="container">
10     <div class="row">
11         <div class="col-md-6 col-md-offset-3">
12             <h3>欢迎进入首页</h3>
13             {% if not request.user.is_authenticated %}
14                 <a href="/app01/login" class="btn btn-success">登录</a>
15                 <a href="/app01/regist" class="btn btn-success">注册</a>
16             {% else %}
17                 <h4>hi,{{ request.user }}</h4>
18                 <a href="/app01/logout" class="btn btn-success">注销</a>
19             {% endif %}
20         </div>
21     </div>
22 </div>
23 </body>
24 </html>

 

login.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>login</title>
 6     <link rel="stylesheet" href="/static/bootstrap.min.css">
 7 </head>
 8 <body>
 9 
10 <div class="container">
11     <div class="row">
12         <div class="col-md-6 col-md-offset-3">
13             <h4>登录</h4>
14             <form action="" method="post">
15                 {% csrf_token %}
16                 {% for field in form %}
17                     <div class="form-group">
18                         <label for="">{{ field.label }}</label>
19                         {{ field }}
20                         <span class="pull-right" style="color: red">{{ field.errors.0 }}</span>
21                     </div>
22                 {% endfor %}
23                 <input type="submit" class="btn btn-success">
24                 <span class="pull-right" style="color: red">{{ error }}</span>
25             </form>
26         </div>
27     </div>
28 </div>
29 
30 </body>
31 </html>

 

regist.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>regist</title>
    <link rel="stylesheet" href="/static/bootstrap.min.css">
</head>
<body>

<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h4>注册</h4>
            <form action="" method="post">
                {% csrf_token %}
                {% for field in form %}
                    <div class="form-group">
                        <label for="">{{ field.label }}</label>
                        {{ field }}
                        <span class="pull-right" style="color: red">{{ field.errors.0 }}</span>
                    </div>
                {% endfor %}
                <input type="submit" class="btn btn-success">
            </form>
        </div>
    </div>
</div>

</body>
</html>

 

secret.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>secret</title>
</head>
<body>

{{ my_secret }}
<h3>你很帅!</h3>

</body>
</html>

 

16 django用户认证组件

标签:bug   als   变量   action   接受   index   nim   cti   event   

原文地址:https://www.cnblogs.com/znyyy/p/11367463.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!