0%

Django登录验证

之前开发的一套后台报表系统,现在页面越来越多,又搞了个内网域名,有的时候会被安全部的检查攻击,所以必须搞一个登录验证的功能。说起来也好写。因为毕竟Django有整套的解决方案。

  • 使用的是Django的(authentication)认证框架。
  • 没有写注册功能(因为根本不需要)
  • 没有写登出(好像也不需要)

Django拥有一个内置的认证(authentication)框架用来操作用户认证(authentication),会话(sessions),权限(permissions)以及用户组。这个认证(authentication)系统包含了一些普通用户的操作视图(views),例如:登录,登出,修改密码以及重置密码。

(authentication)框架位于django.contrib.auth,被其他Django的contrib包调用。所以我们只需要学会怎么使用。

这个认证(authentication)系统还包含了以下模型(models):

  • User:一个包含了基础字段的用户模型(model);这个模型(model)的主要字段有:username, password, email, first_name, last_name, is_active。
  • Group:一个组模型(model)用来分类用户
  • Permission:执行特定操作的标识
    这个框架还包含默认的认证(authentication)视图(views)和表单(forms),我们之后会用到。
    所以之后的工作可能还会涉及到权限认证,也要使用这个框架(到时候再说,反正都是我一个人搞🙄🙄)

开始accounts应用

新建一个应用取名accounts,(注意因为用到Django的登录框架所以取名稍微规范一点)

django-admin startapp accounts

在工程目录settings.pyINSTALLED_APPS 中添加accountsAPP

INSTALLED_APPS = (
    'account',
    # ...
)

执行migrate同步应用models到数据库。

python manage.py migrate

Forms表单

accounts下面新建一个forms.py, 写入以下内容

#-*- coding: UTF-8 -*-
from django import forms

class LoginForm(forms.Form):
    username = forms.CharField(label="用户名",
                    max_length="20")
    password = forms.CharField(label="密码", 
                    max_length="20",widget=forms.PasswordInput)

请注意我们使用PasswordInput控件来渲染HTML的Input元素。它包含type="password"属性,不用再定义。

views视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from django.http import HttpResponse
from django.shortcuts import render
from django.contrib.auth import authenticate, login
from .forms import LoginForm
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect


def user_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = authenticate(username=cd['username'],
password=cd['password'])
if user is not None:
if user.is_active:
login(request, user)
#return HttpResponse('Authenticated successfully')
return HttpResponseRedirect('/accounts/dashboard')
else:
return HttpResponse('Disabled accounts')
else:
return HttpResponse('Invalid login')
else:
form = LoginForm()
return render(request, 'accounts/login.html', {'form': form})

@login_required
def dashboard(request):
pass
return render(request,
'accounts/dashboard.html',
{'section': 'dashboard'})

解读一下以上内容。
login_in函数:
当一个GET请求调用user_login函数的时候。会直接实例化一个登录表单呈现给用户。
当用户POST提交这个表单的时候:

  1. 通过使用form=LoginForm(request.POST)使用用户提交的数据实例化form
  2. 检查form是否有效
  3. 使用authenticate()方法,通过数据库对这个用户进行验证,验证通过,通过login()方法集合用户到session中,并重定向到一个初始页面,没有通过,返回Invalid login

dashboard函数之后会提到。

accounts的urls.py

1
2
3
4
5
6
7
8
9
from django.conf.urls import url
from . import views

urlpatterns = [
# post views
url(r'^dashboard$', views.dashboard, name='dashboard'),
url(r'^login/$', views.user_login, name='login'),

]

注册了两个url /login为登录页,dashboard为初始页。

settings文件

添加了两行,

  • LOGIN_REDIRECT_URL:告诉Django用户登录成功后如果contrib.auth.views.login视图(view)没有获取到next参数将会默认重定向到哪个URL。
  • LOGIN_URL:重定向用户登录的URL(例如:使用login_required装饰器(decorator))。
1
2
LOGIN_REDIRECT_URL = '/accounts/dashboard'
LOGIN_URL = reverse_lazy('login')

前端页面

accounts-base.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>

<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<script src="/static/bootstrap-table-master/docs/assets/js/jquery.min.js"></script>
<script src="/static/bootstrap-3.3.7/docs/dist/js/bootstrap.min.js"></script>
<link href="{% static "/static/css/base.css" %}" rel="stylesheet">

</head>

<body>
<div id="header">
<h1 class="page-header"><span class="glyphicon glyphicon-user"></span> 用户登录</h1>
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>

accounts/login.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% extends "account-base.html" %}
{% block title %}Log-in{% endblock %}
{% block content %}
<div class="container">

<form class="form-line" action="." method="post">
{{ form.as_p }}
{% csrf_token %}
<div class="form-group">
<div class="col-md-5">
<input type="submit" class="btn btn-primary btn-block" value="登录" widget="40">
</div>
</div>
</form>
</div>
{% endblock %}

base.css
忽略了。。自己可以找些好看的样式。

最后

我们把之前相关的页面函数都加个login_required装饰器就可以了。如果没有登录直接访问这个页面就会重定向到登录页面。完美。

上一张登录页图片,哈哈

参考:
form表单设置标签样式
Django By Example翻译