一、登录
1.1 HTTP是无状态协议,无法保存用户的登录状态
可以用cookie 存储用户的信息 -- 但是这种方式并不安全
所以后面采用 cookie + session 解决这种不安全,同时可以保持用户登录状态
登录时需要向cookie中设置一个随机字符串(token)令牌
token令牌: 是在用户登录成功后服务器返回的一个标识符,但是令牌有有效时间限制
1.2 如何向cookie中存数据(令牌)
在Django中可以从用户的请求中获取cookie值,下面采用登录注册为实例说明cookie的应用
当用户发出登录请求时,服务器获取请求,如果登录成功服务器会向用户返回一个响应,并将登录的令牌一同返回回去
#获取响应
res = HttpResponse()
# 设置cookie
res.set_cookie('token', value,有效时间(秒)) 如: res.set_cookie('token', '123123',600)
参数解释:
绑定参数到cookie中
key表示设置的名称 value表示设置的值 max_age表示多少秒后过期
expires表示datetime类型的日期, 表示多久过期
1.3 如何做令牌校验
做令牌校验需要先获取cookie值
在了解如何会获取cookie值前我们需要先了解request请求中的内容主要有哪些
字段 | 说明 |
---|---|
COOKIE | 传递客户端中的cookie内容 |
GET | 获取HTTP GET请求中传递的参数。如:127.0.0.1/xxx/id=1 |
POST | 获取HTTP POST请求中传递的参数 |
FILES | 获取请求页面中的文件 |
path | 获取当前请求的url路径 |
method | 获取请求方式 |
获取cookie值: 由于请求中的cookie值是以字典的形式传给服务器,服务器可以通过字典取值的方式获取值,但推荐用get方式获取(但键不存在时不会报错)
# GET 请求获取
token = request.GET.get('token')
# POST 请求获取
token = request.POST.get('token')
要做保持用户登录状态,则需要保存用户的cookie值,由于用户和cookie值之间是一对一的关系,可以考虑建一张token表用于保存用户cookie值,并做一对一关联
class TokenUser(models.Model):
token = models.CharField(max_length=30)
user = models.OneToOneField(MyUser)
但是由于每个用户登录后都会获取不同的cookie值,我们可以运用随机函数(random)产生,在开发中像这样的功能函数我们可以创建一个文件夹来保存这些工具(函数)。
在项目文件夹下创建一个名为utils的文件夹,我们把一些共用的函数放在这个文件夹下,同时还需要创建一个__init__.py文件(目的是告诉解释器把这个文件看成一个python包)
1.4 令牌校验成功与否后的操作
假设登录后才能访问首页,要判断用户是否登录则需要在cookie有效时间内判断用户的请求是否有有效的cookie值,该cookie可以在数据中读取。
def my_index(request):
# 当访问127.0.0.1/my_index/ 时如果用户登录过,并且cookie有效,则跳转到index.html页面,否则返回登录页面
if request.method == 'GET':
token = request.COOKIES.get('token')
user_token = TokenUser.objects.filter(token=token)
if user_token:
return render(request, 'index.html')
else:
return HttpResponseRedirect('/login/')
注意: 当用render()返回页面时,浏览器的url不会改变成相应的url,所有这里需要用跳转
如:
return render(request, 'index.html')
return HttpResponseRedirect('/login/')
二、简单用户注册和登录
用户注册:通过前端form表单向服务器提交用户注册信息,服务器通过request请求获取对应的信息,并在后端进行用户信息校验,并做出不同的响应。
用户登录:用户通过前端form表单向服务器提交登录信息,服务器通过request请求获取对应的登录信息,并在后端做用户登录信息校验,做出不同的响应,并返回用户此次登录的cookie值,用于保存用户登录状态。
用户注册:
def register(request):
if request.method == 'GET':
# GET 访问 127.0.0.1/redister/
return render(request, 'register.html')
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
password2 = request.POST.get('password2')
# 判断用户名是否注册
re = MyUser.objects.filter(username=username).first()
if re:
err_name = '该用户已经被注册!'
return render(request, 'register.html', {'err_name': err_name})
# 判断密码和确认密码是否相同
if password and password2:
if password != password2:
err_pwd = '两次密码输入不一致!'
return render(request, 'register.html', {'err_name': err_pwd})
else:
# 如果用户名存在,且密码和确认密码相同,则注册保存
MyUser.objects.create(username=username, password=password)
# return render(request, 'login.html')
# 跳转指定的地址页面
return HttpResponseRedirect('/login/')
else:
err_pwd = '密码不能为空!'
return render(request, 'register.html', {'err_name': err_pwd})
用户登录:
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
if request.method == 'POST':
# 获取用户账号密码信息
username = request.POST.get('username')
password = request.POST.get('password')
# 验证是否输入账号密码
if not (username and password):
return render(request, 'login.html', {'err_name': '用户名或密码不能为空!'})
# 判断是否有该用户的信息
user = MyUser.objects.filter(username=username, password=password).first()
if not user:
return render(request, 'login.html', {'err_name': '该用户未注册!'})
# 登录验证并给他一个令牌
res = HttpResponseRedirect('/my_index/')
token = get_cookie_token()
res.set_cookie('token', token, 600)
token_user = TokenUser.objects.filter(user=user).first()
if token_user:
token_user.token = token
else:
TokenUser.objects.create(user=user, token=token)
return res