【Django】Day3-视图-登录功能

Django视图

一.登录系统

1.写一个表格

对于一个登录系统来说,首页是一个登录页面

<html>
<head>
<title>Django Page</title>
</head>
<body>
<h1>发布会管理</h1>
<form>
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password"><br>
<button id="btn" type="submit">登录</button>
</form>
</body>
</html>
  • 增加get方法
<html>
<head>
<title>Django Page</title>
</head>
<body>
<h1>发布会管理</h1>
<form method="get">
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password"><br>
<button id="btn" type="submit">登录</button>
</form>
</body>
</html>

但是get方法对于信息传递是没有加密的,所以应该使用post方法

  • 增加post方法
    把表格请求的方法换成post
“CSRF verification failed. Request aborted.”

但是之后请求的时候会出现报错,这个是CSRF攻击,通过伪装成受信任用户的请求来利用受信任的网站,如果攻击者针对站点伪造链接,当该站点的用户点击该链接,且该站点使用的是持久化的cookies策略,攻击者就会获取用户认证信息,进行攻击,当然,这里也可以不用管。

  • Django对CSRF的保护
    Django 针对CSRF 的保护措施是在生成的每个表单中放置一个自动生成的令牌,通过这个令牌判断POST请求是否来自同一个网站。

所以这里使用了Django的模板标签(template tag)添加CSRF令牌,在form表单里面添加{% csrf_token %}

<html>
<head>
<title>Django Page</title>
</head>
<body>
<h1>发布会管理</h1>
<form action="/login_action/">
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password"><br>
<button id="btn" type="submit">登录</button>
    {% csrf_token %}
</form>
</body>
</html>

这样在页面想Django服务器发送Post请求的时候,客户端会加上一个srfmiddlewaretoken字段,给当前会话ID加上密钥

2.处理登录请求

  • 指定提交路径
    对于form表单提交的数据,我们需要指定提交路径,修改form的路径
<form method="post" action="/login_action/">
  • 新增login_action路由
    打开urls.py文件
from blog import views
urlpatterns = [
……
path(r'login_action/', views.login_action),
]
  • 新增视图函数
    在view文件中增加login_action函数
def login_action(request):
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        if username == 'test' and password == 'test123':
            return HttpResponse('login success!')
        else:
            return render(request,'index.html', {'error': 'username or password error!'})
    else:
        return render(request, 'index.html', {'error': 'username or password error!'})

这里通过HttpResponse类返回一个登录成功的信息;然后通过render方法给login页面返回一个错误信息

  • 在index页面增加错误提示
<form method="post" action="/login_action/">
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password"><br>
{{ error }}<br>
<button id="btn" type="submit">登录</button>
{% csrf_token %}
</form>

这里使用了Django的模板语言 {{ error }},对应着之前render返回的字典中error的value

3.登录成功页

  • 修改login sucess
    这里要修改成一个新的函数来处理登录成功的信息,修改登录成功的操作
def login_action(request):
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        if username == 'test' and password == 'test123':
            return HttpResponseRedirect('/event_manage/')
        else:
            return render(request,'index.html', {'error': 'username or password error!'})
    else:
        return render(request, 'index.html', {'error': 'username or password error!'})

这里使用的是HttpResponseRedirect类,对页面进行重定向,可以将之前登录成功的结果重定向到/event_manage/路径,然后可以创建event_manage 函数,用于返回发布会管理event_manage.html 面页。

  • 在view中新增函数
def event_manage(request):
    return render(request,"event_manage.html")
  • 在urls中新增event_manage路由
path(r'event_manage/', views.login_action),

4.代码更新

这里项目的源码更新到了github

二.Cookie 和Session

1.Cookie 和Session基本概念

这里可以看http协议基础

2.使用Cookie增加一个用户名

本节使用Cookie和Session来实现一个功能——
假如用户通过“zhangsan”登录,然后,在登录成功页显示“嘿,zhangsan 你好!

  • 获取暱称
    这里是修改login_action,传递数据
def login_action(request):
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        if username == 'test' and password == 'test123':
            response = HttpResponseRedirect('/event_manage/')
            # 添加浏览器cookie(key value 过期时间)
            response.set_cookie('user', username, 3600)
            return response
        else:
            return render(request,'index.html', {'error': 'username or password error!'})
  • 得到暱称
    修改event_manage来获取数据
def event_manage(request):
    username = request.COOKIES.get('user', '')  # 读取浏览器cookie(key)停留时间
    return render(request, "event_manage.html", {"user": username})

  • 展示暱称
    这里需要修改获取的数据的模板event_manage.html
<html>
<head>
<title>Event Manage Page</title>
</head>
<body>
<h1>Login Success!</h1>
<div style="float:right;">
<a>嘿!{{ user }} 欢迎</a><hr/>
</div>
</body>
</html>

然后登录成功的时候就可以展示登录成功的用户暱称

3.修改成Session展示

使用Cookie来存储数据显而易见是不够安全的,所以我们需要使用Session,把数据存在服务端,以防攻击者修改数据

login_action修改

修改

response.set_cookie('user', username, 3600)

request.session['user'] = username # 将session 信息记录到浏览器
event_manage修改

修改

username = request.COOKIES.get('user', '')

username = request.session.get('user', '') # 读取浏览器session

但是还没完,需要补充数据表

创建django_session表

对于session来说,服务端来存储用户的sessionId等数据,Django是一个服务端,所以我们需要一个django_session表来存储数据

  • 生成数据表,通过“migrate”命令进行数据迁移
python manage.py migrate

这里在setting文件中有一个默认配置DATABASES。

然后重新登录即可

通过Chrome浏览器的抓包工具可以看到,在登录的时候接口传递的由cookie变成了session

三.Django认证系统

之前只是对登录的功能实现了验证,但是用户名密码是在代码中写死的,这里我们需要增加用户数据

1.配置用户

首先先新建一个超级管理员帐户

python manage.py createsuperuser
Username (leave blank to use 'fnngj'): admin #输入用户名
Email address: admin #输入邮箱
Password: #输入密码
Password (again): #重复输入密码
Superuser created successfully.

然后就可以登录到admin页面

然后使用超级用户登录到对应的admin页面,增加用户组,增加用户,并设置用户状态,最后这个用户可以登录并到该页面

2.引用Django的认证登录

修改登录逻辑

from django.contrib import auth

def login_action(request):
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        user = auth.authenticate(username=username,password=password)
        if user is not None:
            # 新增登录验证逻辑
            auth.login(request, user)
            request.session['user'] = username
            response = HttpResponseRedirect('/event_manage/')
            return response
        else:
            return render(request,'index.html', {'error': 'username or password error!'})

使用authenticate方法,用户名存在的话返回一个User对象,不存在会返回None;如果返回的不是就会返回None

3.加上登录限制

在之前的设计中,可以直接通过路径跳转到登录成功的页面,我们需要对路径进行限制

下面是对登录页限制

from django.contrib.auth.decorators import login_required

@login_required
def event_manage(request):
username = request.session.get('user', '')
return render(request,"event_manage.html",{"user":username})

增加之后,之间通过浏览器请求http://127.0.0.1:8000/event_manage/页面将会返回一个失败提示。
可以看到这里配置的accounts/login是一个默认路径跳转

http://localhost:8000/accounts/login/?next=/event_manage/

然后把这个跳转等价

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/',views.archive),
    path('index/',views.index),
    path('accounts/login/',views.index),
    path('login_action/', views.login_action),
    path('event_manage/', views.event_manage),
]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章