我的Django运维平台很不幸的被公司安全系统扫描出来了,给了我一个超级大警告。主要也怪我当时偷懒,只是在SLB层面做了IP访问限制但是没有给服务器nginx里做白名单,所以网站是可以通过“IP地址加端口”访问的。恰巧ping里面用了一个AES加解密的脚本,那个算法有问题,可以获取当前用户的权限,我特么的还是直接用root启动的nginx,而且这个机器里面还有ansible,当然后果很严重。
出了问题,不能消极对待而要积极解决,于是要先给网站做一个完善的用户登录鉴权系统。再一次背景介绍:
python:3.6.5
Django:2.1.1
Project:Kubernetes,文件夹路径就是/django/Kubernetes/
App:createyaml,文件夹路径就是/django/Kubernetes/createyaml
实现用户登录鉴权
首先,先编写一个index.html
的页面做登录界面,如下:
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<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>请先登录</title>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> #引入css样式
<link rel="icon" href="/static/pic/batman.ico" type="image/x-icon"> #引入一个标签图
</head>
<body background="/static/pic/easyplane.jpg"> #背景图片设置
<div style="margin-top: 200px">
<div style="text-align:center;">
<font color='brown'><h1>请输入您的账号密码</h1></font>
<div>
<div>
<form class="ui form" method="post" action="">
<div class="field">
<input type="text" name="username" placeholder="username"><br>
</div>
<div class="field">
<input type="password" name="password" placeholder="password"><br>
</div>
<font color=red>{{ error }}</font><br> #登录错误红色表示
<button class="btn btn-default" type="submit">登陆</button>
{% csrf_token %}
</form>
</div>
</div>
</div>
</div>
</body>
</html>
效果如下:
在Kubernetes这个app文件夹里的urls.py
里给这个鉴权网站添加一个路由:
1
2
3
4
5
6
7
8
9
10from django.contrib import admin
from django.urls import path,include
from . import views
urlpatterns = [
path('',views.login_action,name='login'), #首页就是login_action的函数
path('homepage.html',views.home,name='home'), #将原来的首页改成叫homepage.html
path('admin/', admin.site.urls),
...其余省略
]
在同级的views.py
里编写login_action
函数,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24from django.shortcuts import render,render_to_response
from django.http import HttpResponse,HttpResponseRedirect
from django.contrib import auth
#登陆
def login_action(request):
if request.method == 'POST': #通过post形式获取,get的话会在地址栏里看到账号密码
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password) #使用django自带方式鉴权
if user is not None:
auth.login(request, user) # 登录
request.session['user'] = username # 将session信息记录到浏览器
response = HttpResponseRedirect('homepage.html') #鉴权OK就跳转到homepage.html
return response
else:
return render(request,'index.html', {'error': '账号密码有误,请联系管理员!'})
else:
return render(request,'index.html')
#首页
def home(request):
context = {}
return render_to_response('homepage.html',context)
登陆的用户/密码就是django后台的账号/密码,可以用superuser来登陆。保存文件之后,系统会重启django,查看效果如图:
render和render_to_response的区别
上面的login_action
函数里,用了render
和render_to_response
,如果只用render_to_response
,同时把所有的render
改成render_to_response
,那么在访问首页的时候就会出现TemplateDoesNotExist at /
这样的错误:
明明他俩都是用来展示模板页面的。为什么会有模板不存在这样?原因是render_to_response()
的第一个参数必须是要使用的模板名称。如果要给定第二个参数,那么该参数必须是为该模板创建Context时所使用的字典。如果不提供第二个参数,render_to_response()
使用一个空字典。而render
第一个参数可以是request。
所以如果都要用render_to_response
,那么就要改成如下:
1
2
3
4else:
return render_to_response('index.html', {'error': '账号密码有误,请联系管理员!'},context_instance=RequestContext(request))
else:
return render_to_response('index.html')
但是这样的话,可能在登录的时候就会有csrf的错误,需要把csrf去掉。
实现登出功能
有了登录还得有登出,还是老套路,先编写路由如下:
1
path(r'logout/', views.logout,name="logout"),
然后对应去views.py里写logout这个函数:
1
2
3
4
5
6from django.http import HttpResponseRedirect
from django.contrib import auth #引入django默认的auth功能
#注销
def logout(request):
auth.logout(request)
return HttpResponseRedirect('/login') #跳转到登录页/login
然后就是在首页里添加一个登出的链接,链接指向就是/logout/
。测试一下效果: