Django Session和Cookie分别实现记住用户登录状态操作


Posted in Python onJuly 02, 2020

简介

由于http协议的请求是无状态的。故为了让用户在浏览器中再次访问该服务端时,他的登录状态能够保留(也可翻译为该用户访问这个服务端其他网页时不需再重复进行用户认证)。我们可以采用Cookie或Session这两种方式来让浏览器记住用户。

Cookie与Session说明与实现

Cookie

说明

Cookie是一段小信息(数据格式一般是类似key-value的键值对),由服务器生成,并发送给浏览器让浏览器保存(保存时间由服务端定夺)。当浏览器下次访问该服务端时,会将它保存的Cookie再发给服务器,从而让服务器根据Cookie知道是哪个浏览器或用户在访问它。(由于浏览器遵从的协议,它不会把该服务器的Cookie发送给另一个不同host的服务器)。

Django中实现Cookie

from django.shortcuts import render, redirect

# 设置cookie
"""
key: cookie的名字
value: cookie对应的值
max_age: cookie过期的时间
"""
response.set_cookie(key, value, max_age)
# 为了安全,有时候我们会调用下面的函数来给cookie加盐
response.set_signed_cookie(key,value,salt='加密盐',...)

# 获取cookie 
request.COOKIES.get(key)
request.get_signed_cookie(key, salt="加密盐", default=None)

# 删除cookie
reponse.delete_cookie(key)

下面就是具体的代码实现了

views.py

# 编写装饰器检查用户是否登录
def check_login(func):
 def inner(request, *args, **kwargs):
 next_url = request.get_full_path()
 # 假设设置的cookie的key为login,value为yes
 if request.get_signed_cookie("login", salt="SSS", default=None) == 'yes':
  # 已经登录的用户,则放行
  return func(request, *args, **kwargs)
 else:
  # 没有登录的用户,跳转到登录页面
  return redirect(f"/login?next={next_url}")
 return inner

# 编写用户登录页面的控制函数
@csrf_exempt
def login(request):
 if request.method == "POST":
 username = request.POST.get("username")
 passwd = request.POST.get("password")
 next_url = request.POST.get("next_url")

 # 对用户进行验证,假设用户名为:aaa, 密码为123
 if username === 'aaa' and passwd == '123':
  # 执行其他逻辑操作,例如保存用户信息到数据库等
  # print(f'next_url={next_url}')
  # 登录成功后跳转,否则直接回到主页面
  if next_url and next_url != "/logout/":
  response = redirect(next_url)
  else:
  response = redirect("/index/")
  # 若登录成功,则设置cookie,加盐值可自己定义取,这里定义12小时后cookie过期
  response.set_signed_cookie("login", 'yes', salt="SSS", max_age=60*60*12)
  return response
 else:
  # 登录失败,则返回失败提示到登录页面
  error_msg = '登录验证失败,请重新尝试'
  return render(request, "app/login.html", {
  'login_error_msg': error_msg,
  'next_url': next_url,
  })
 # 用户刚进入登录页面时,获取到跳转链接,并保存
 next_url = request.GET.get("next", '')
 return render(request, "app/login.html", {
 'next_url': next_url
 })

# 登出页面
def logout(request):
 rep = redirect("/login/")
 # 删除用户浏览器上之前设置的cookie
 rep.delete_cookie('login')
 return rep

# 给主页添加登录权限认证
@check_login
def index(request):
 return render(request, "app/index.html")

由上面看出,其实就是在第一次用户登录成功时,设置cookie,用户访问其他页面时进行cookie验证,用户登出时删除cookie。另外附上前端的login.html部分代码

<form action="{% url 'login' %}" method="post">
  <h1>请使xx账户登录</h1>
  <div>
  <input id="user" type="text" class="form-control" name="username" placeholder="账户" required="" />
  </div>
  <div>
  <input id="pwd" type="password" class="form-control" name="password" placeholder="密码" required="" />
  </div>
  <div style="display: none;">
   <input id="next" type="text" name="next_url" value="{{ next_url }}" />
  </div>
  {% if login_error_msg %}
   <div id="error-msg">
   <span style="color: rgba(255,53,49,0.8); font-family: cursive;">{{ login_error_msg }}</span>
   </div>
  {% endif %}
  <div>
   <button type="submit" class="btn btn-default" style="float: initial; margin-left: 0px">登录</button>
  </div>
  </form>

Session

Session说明

Session则是为了保证用户信息的安全,将这些信息保存到服务端进行验证的一种方式。但它却依赖于cookie。具体的过程是:服务端给每个客户端(即浏览器)设置一个cookie(从上面的cookie我们知道,cookie是一种”key, value“形式的数据,这个cookie的value是服务端随机生成的一段但唯一的值)。

当客户端下次访问该服务端时,它将cookie传递给服务端,服务端得到cookie,根据该cookie的value去服务端的Session数据库中找到该value对应的用户信息。(Django中在应用的setting.py中配置Session数据库)。

根据以上描述,我们知道Session把用户的敏感信息都保存到了服务端数据库中,这样具有较高的安全性。

Django中Session的实现

# 设置session数据, key是字符串,value可以是任何值
request.session[key] = value
# 获取 session
request.session.get[key]
# 删除 session中的某个数据
del request.session[key]
# 清空session中的所有数据
request.session.delete()

下面就是具体的代码实现了:

首先就是设置保存session的数据库了。这个在setting.py中配置:(注意我这里数据库用的mongodb,并使用了django_mongoengine库;关于这个配置请根据自己使用的数据库进行选择,具体配置可参考官方教程)

SESSION_ENGINE = 'django_mongoengine.sessions'

SESSION_SERIALIZER = 'django_mongoengine.sessions.BSONSerializer'

views.py

# 编写装饰器检查用户是否登录
def check_login(func):
 def inner(request, *args, **kwargs):
 next_url = request.get_full_path()
 # 获取session判断用户是否已登录
 if request.session.get('is_login'):
  # 已经登录的用户...
  return func(request, *args, **kwargs)
 else:
  # 没有登录的用户,跳转刚到登录页面
  return redirect(f"/login?next={next_url}")
 return inner

@csrf_exempt
def login(request):
 if request.method == "POST":
 username = request.POST.get("username")
 passwd = request.POST.get("password")
 next_url = request.POST.get("next_url")
 # 若是有记住密码功能
 # remember_sign = request.POST.get("check_remember")
 # print(remember_sign)

 # 对用户进行验证
 if username == 'aaa' and passwd == '123':
  # 进行逻辑处理,比如保存用户与密码到数据库

  # 若要使用记住密码功能,可保存用户名、密码到session
  # request.session['user_info'] = {
  # 'username': username,
  # 'password': passwd
  # }
  request.session['is_login'] = True
  # 判断是否勾选了记住密码的复选框
  # if remember_sign == 'on':
  # request.session['is_remember'] = True
  # else:
  # request.session['is_remember'] = False

  # print(f'next_url={next_url}')
  if next_url and next_url != "/logout/":
  response = redirect(next_url)
  else:
  response = redirect("/index/")
  return response
 else:
  error_msg = '登录验证失败,请重新尝试'
  return render(request, "app/login.html", {
  'login_error_msg': error_msg,
  'next_url': next_url,
  })
 next_url = request.GET.get("next", '')
 # 检查是否勾选了记住密码功能
 # password, check_value = '', ''
 # user_session = request.session.get('user_info', {})
 # username = user_session.get('username', '')
 # print(user_session)
 #if request.session.get('is_remember'):
 # password = user_session.get('password', '')
 # check_value = 'checked'
 # print(username, password)
 return render(request, "app/login.html", {
 'next_url': next_url,
 # 'user': username,
 # 'password': password,
 # 'check_value': check_value
 })

def logout(request):
 rep = redirect("/login/")
 # request.session.delete()
 # 登出,则删除掉session中的某条数据
 if 'is_login' in request.session:
 del request.session['is_login']
 return rep

@check_login
def index(request):
 return render(request, "autotest/index.html")

另附login.html部分代码:

<form action="{% url 'login' %}" method="post">
  <h1>请使xxx账户登录</h1>
  <div>
  <input id="user" type="text" class="form-control" name="username" placeholder="用户" required="" value="{{ user }}" />
  </div>
  <div>
  <input id="pwd" type="password" class="form-control" name="password" placeholder="密码" required="" value="{{ password }}" />
  </div>
  <div style="display: none;">
   <input id="next" type="text" name="next_url" value="{{ next_url }}" />
  </div>
  {% if login_error_msg %}
   <div id="error-msg">
   <span style="color: rgba(255,53,49,0.8); font-family: cursive;">{{ login_error_msg }}</span>
   </div>
  {% endif %}
  // 若设置了记住密码功能
  // <div style="float: left">
  // <input id="rmb-me" type="checkbox" name="check_remember" {{ check_value }}/>记住密码
  // </div>
  <div>
   <button type="submit" class="btn btn-default" style="float: initial; margin-right: 60px">登录</button>
  </div>
  </form>

总的来看,session也是利用了cookie,通过cookie生成的value的唯一性,从而在后端数据库session表中找到这value对应的数据。session的用法可以保存更多的用户信息,并使这些信息不易被暴露。

总结

session和cookie都能实现记住用户登录状态的功能,如果为了安全起见,还是使用session更合适

以上这篇Django Session和Cookie分别实现记住用户登录状态操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
归纳整理Python中的控制流语句的知识点
Apr 14 Python
Python实现LRU算法的2种方法
Jun 24 Python
Python subprocess模块功能与常见用法实例详解
Jun 28 Python
python爬虫自动创建文件夹的功能
Aug 01 Python
Python3爬虫爬取百姓网列表并保存为json功能示例【基于request、lxml和json模块】
Dec 05 Python
Python3.4学习笔记之常用操作符,条件分支和循环用法示例
Mar 01 Python
Python基础学习之函数方法实例详解
Jun 18 Python
pytorch torch.expand和torch.repeat的区别详解
Nov 05 Python
Django框架中间件定义与使用方法案例分析
Nov 28 Python
python对文件的操作方法汇总
Feb 28 Python
python3跳出一个循环的实例操作
Aug 18 Python
pytorch 如何使用amp进行混合精度训练
May 24 Python
django 装饰器 检测登录状态操作
Jul 02 #Python
详解用Python爬虫获取百度企业信用中企业基本信息
Jul 02 #Python
django 实现后台从富文本提取纯文本
Jul 02 #Python
详解用Python调用百度地图正/逆地理编码API
Jul 02 #Python
基于django2.2连oracle11g解决版本冲突的问题
Jul 02 #Python
解决django migrate报错ORA-02000: missing ALWAYS keyword
Jul 02 #Python
使用PyWeChatSpy自动回复微信拍一拍功能的实现代码
Jul 02 #Python
You might like
php中根据变量的类型 选择echo或dump
2012/07/05 PHP
神奇的代码 通杀各种网站-可随意修改复制页面内容
2008/07/17 Javascript
Moment.js 不容错过的超棒Javascript日期处理类库
2012/04/15 Javascript
javascript模拟select,jselect的方法实现
2012/11/08 Javascript
javascript学习笔记--数字格式类型
2014/05/22 Javascript
JavaScript Sort 的一个错误用法示例
2015/03/20 Javascript
举例详解JavaScript中Promise的使用
2015/06/24 Javascript
JavaScript正则表达式的分组匹配详解
2016/02/13 Javascript
JavaScript常用数组算法小结
2016/02/13 Javascript
HTML5canvas 绘制一个圆环形的进度表示实例
2016/12/16 Javascript
基本DOM节点操作
2017/01/17 Javascript
微信小程序 数据交互与渲染实例详解
2017/01/21 Javascript
Kindeditor单独调用多图上传实例
2017/07/31 Javascript
深入浅析Vue中的 computed 和 watch
2018/06/06 Javascript
layui table数据修改的回显方法
2019/09/04 Javascript
LayUI数据接口返回实体封装的例子
2019/09/12 Javascript
node.js域名解析实现方法详解
2019/11/05 Javascript
[01:08:57]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第二场
2014/05/24 DOTA
[01:12:53]完美世界DOTA2联赛PWL S2 Forest vs SZ 第一场 11.25
2020/11/26 DOTA
python使用scrapy解析js示例
2014/01/23 Python
Python正则表达式非贪婪、多行匹配功能示例
2017/08/08 Python
python中的闭包函数
2018/02/09 Python
python书籍信息爬虫实例
2018/03/19 Python
解决python中使用plot画图,图不显示的问题
2018/07/04 Python
Python的条件锁与事件共享详解
2019/09/12 Python
Python退出时强制运行一段代码的实现方法
2020/04/29 Python
详解Python中的编码问题(encoding与decode、str与bytes)
2020/09/30 Python
CSS3实现可翻转的hover效果
2018/05/23 HTML / CSS
仿CSDN Blog返回页面顶部功能实现原理及代码
2013/06/30 HTML / CSS
为娇小女性量身打造:Petite Studio
2018/11/01 全球购物
Unix如何添加新的用户
2014/08/20 面试题
乡镇庆八一活动方案
2014/02/02 职场文书
数控技校生自我鉴定
2014/03/02 职场文书
软件专业毕业生个人自我鉴定
2014/04/17 职场文书
学雷锋标兵事迹材料
2014/08/18 职场文书
python3 删除所有自定义变量的操作
2021/04/08 Python