对于一个登录系统来说,首页是一个登录页面
Django Page
发布会管理
Django Page
发布会管理
但是get方法对于信息传递是没有加密的,所以应该使用post方法
“CSRF verification failed. Request aborted.”
但是之后请求的时候会出现报错,这个是CSRF攻击,通过伪装成受信任用户的请求来利用受信任的网站,如果攻击者针对站点伪造链接,当该站点的用户点击该链接,且该站点使用的是持久化的cookies策略,攻击者就会获取用户认证信息,进行攻击,当然,这里也可以不用管。
所以这里使用了Django的模板标签(template tag)添加CSRF令牌,在form表单里面添加{% csrf_token %}
Django Page
发布会管理
这样在页面想Django服务器发送Post请求的时候,客户端会加上一个srfmiddlewaretoken字段,给当前会话ID加上密钥
from blog import views
urlpatterns = [
……
path(r'login_action/', views.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页面返回一个错误信息
这里使用了Django的模板语言 {{ error }},对应着之前render返回的字典中error的value
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 面页。
def event_manage(request):
return render(request,"event_manage.html")
path(r'event_manage/', views.login_action),
这里项目的源码更新到了github
这里可以看http协议基础
本节使用Cookie和Session来实现一个功能——
假如用户通过“zhangsan”登录,然后,在登录成功页显示“嘿,zhangsan 你好!
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!'})
def event_manage(request):
username = request.COOKIES.get('user', '') # 读取浏览器cookie(key)停留时间
return render(request, "event_manage.html", {"user": username})
Event Manage Page
Login Success!
然后登录成功的时候就可以展示登录成功的用户昵称
使用Cookie来存储数据显而易见是不够安全的,所以我们需要使用Session,把数据存在服务端,以防攻击者修改数据
修改
response.set_cookie('user', username, 3600)
成
request.session['user'] = username # 将session 信息记录到浏览器
修改
username = request.COOKIES.get('user', '')
成
username = request.session.get('user', '') # 读取浏览器session
但是还没完,需要补充数据表
对于session来说,服务端来存储用户的sessionId等数据,Django是一个服务端,所以我们需要一个django_session表来存储数据
python manage.py migrate
这里在setting文件中有一个默认配置DATABASES。
然后重新登录即可
通过Chrome浏览器的抓包工具可以看到,在登录的时候接口传递的由cookie变成了session
之前只是对登录的功能实现了验证,但是用户名密码是在代码中写死的,这里我们需要增加用户数据
首先先新建一个超级管理员帐户
python manage.py createsuperuser
Username (leave blank to use 'fnngj'): admin #输入用户名
Email address: admin #输入邮箱
Password: #输入密码
Password (again): #重复输入密码
Superuser created successfully.
然后就可以登录到admin页面
然后使用超级用户登录到对应的admin页面,增加用户组,增加用户,并设置用户状态,最后这个用户可以登录并到该页面
修改登录逻辑
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
在之前的设计中,可以直接通过路径跳转到登录成功的页面,我们需要对路径进行限制
下面是对登录页限制
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),
]