简介

由于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更合适

参考文章:https://blog.csdn.net/qq_34755081/article/details/82808537

Django 用Session和Cookie分别实现记住用户登录状态的更多相关文章

  1. iOS - 记住用户登录状态保存用户名密码

    我们在使用APP时常用的一个功能:用户第一次进入APP时自动进入登录注册页,提示用户注册登录,用户登录成功后才进入主页,再次进入APP时,不用再次登录就直接进到主页了,就算杀掉该APP进程再次进入,依 ...

  2. 浅析Django之session与cookie

    浅析Django之session与cookie 1 session与cookie概述 原理: 由于HTTP协议是无状态,无连接的,当用户发起网路请求时,需要服务端能标识用户ID,用以存储用户相关信息, ...

  3. Asp.Net使用加密cookie代替session验证用户登录状态 源码分享

    首先 session 和 cache 拥有各自的优势而存在.  他们的优劣就不在这里讨论了. 本实例仅存储用户id于用户名,对于多级权限的架构,可以自行修改增加权限字段   本实例采用vs2010编写 ...

  4. Java 之 cookie 记住用户登录时间案例

    需求: 1. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问. 2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串 分析: 1. 可以采用Cookie ...

  5. Asp.Net MVC记住用户登录信息 下次登录无需输入密码

    有的时候做网站,就需要记住用户登录信息,下次再登录网站时,不用重复输入用户名和密码,原理是浏览器的cookie把状态给记住了! 那么具体是怎么实现的呢?下面博主将一部分代码贴出来,想要完整版的Demo ...

  6. 基于cookie的用户登录状态管理

    cookie是什么 先来花5分钟看完这篇文章:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies 看完上文,相信大家对cookie已经有 ...

  7. django学习,session与cookie

    Cookies,某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密).Cookie最早是网景公司的前雇员Lou Montulli在1993年3月的发明.Cook ...

  8. django之Session、Cookie

    Session ·Session存在于服务器端 ·Session的设置: request.session['name'] = value ·Session的获取: dic = request.sess ...

  9. django使用session来保存用户登录状态

    先建好登录用的model,其次理解使用cookie和session的原理,一个在本机保存,一个在服务器保存 使用session好处,可以设置登录过期的时间, 编写views中login的函数 def ...

随机推荐

  1. KiCad:Cursor Ghosting

    造冰箱的大熊猫@cnblogs 2019/8/11 装下KiCad学习下,结果鼠标在界面上划过时,留下一串鼠标残影,原来英文管这个叫“cursor ghosting”. 解决方法:依旧粗暴简单,从官网 ...

  2. leetcode解题报告(9):Implement strStr()

    描述 Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if nee ...

  3. luogu 2515

    对于软件的依赖可以转化为图上点之间的边的关系发现对于一个强联通分量内的软件,一安则全安Tarjan缩点缩点后,从虚拟节点 0 向所有入度为 0 的点连边这样就构成了一棵树树形 dp$dp[i][j]$ ...

  4. [Luogu] 产生数

    题面:https://www.luogu.org/problemnew/show/P1037 题解:https://www.zybuluo.com/wsndy-xx/note/1145473

  5. k8s/Kubernetes常用组件Helm的部署

    Helm的安装 1.Helm的基本概念 Helm是Kubernetes的一个包管理工具,用来简化Kubernetes应用的部署和管理.可以把Helm比作CentOS的yum工具. Helm有如下几个基 ...

  6. 一、docker安装CentOS7

    一.安装步骤 前提条件 Docker运行在CentOS7上,要求系统64位.系统内核版本为3.10以上. Docker是一个进程,一启动就两个进程,一个服务,一个守护进程.占用资源就非常少,启动速度非 ...

  7. 十八、centos7网络属性配置

    一.为什么需要这个 服务器通常有多块网卡,有板载集成的,同时也有插在PCIe插槽的.Linux系统的命名原来是eth0,eth1这样的形式,但是这个编号往往不一定准确对应网卡接口的物理顺序.为解决这类 ...

  8. ubuntu上面Parity 安装

      sudo wget https://raw.githubusercontent.com/paritytech/parity/master/scripts/parity.service -O /et ...

  9. golang gorm框架的默认时区问题

    gorm框架的时区是在连接数据库时设置的, 如下

  10. 如何使用git cherry-pick将同一个仓库的某个分支的某些commit合并到当前分支?

    答: git cherry-pick <another-branch's commit-id>