Django利用Session机制实现唯一登录与Cookie对比详解
本文详解Django中利用Session机制实现账号唯一登录的方法,并对比Cookie实现登录状态的区别。通过配置数据库、生成Session表及编写视图函数,展示如何确保同一账号仅单设备在线。同时介绍Cookie与Session在安全性、存储位置及Django中的具体代码实现,帮助开发者选择更合适的用户状态管理方案。
Django Session唯一登录配置与实现
首先需要完成数据库连接的配置工作,确保Django项目能够正确访问后端数据库。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '数据库名称',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '10.18.62.2',
'PORT': '3306',
}
}
接着需要生成用于存储Session数据的数据库表,以便系统能够持久化保存用户的会话信息。
执行以下命令来创建并应用数据库迁移: python manage.py makemigrations python manage.py migrate
在用户登录流程中,需要编写逻辑以保存用户的登录状态信息,通常涉及将用户标识存入Session或Cookie。
# 登录验证
def login_ver(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
'''
# 用前端输入的用户名,密码去数据库里找到用户的信息
user=数据库(username,password)
'''
# 数据库中得有一张users表
user = list(Users.objects.filter(username=username,password=password).values())
# 用户信息记录在session中
request.session['user'] = user
# 创建session,否则key为None
if not request.session.session_key:
request.session.create()
# 获取session_key
key = request.session.session_key
# 当另一机器登录时,本机器应该被挤下即当前sessionkey失效,后登录的用户的session可用,之前的sessionkey从数据库中删除
# 获取指定key的session_data,下面用的ORM模型去数据库中取数据
session_data = list(DjangoSession.objects.filter(session_key=key).values_list('session_data'))[0][0]
# 删除key不为当前key,session_data等于当前session_data的session记录,从而达到一个账号只能一台机器登录的目的
models.DjangoSession.objects.filter(session_data=session_data).exclude(session_key=key).delete()
Cookie与Session实现登录状态对比
补充知识:Django 用Session和Cookie分别实现记住用户登录状态
简介
HTTP协议本身是无状态的,这意味着服务器无法自动识别多次请求是否来自同一用户。为了在用户再次访问网站时保持登录状态,避免重复认证,通常采用Cookie或Session机制来让浏览器记住用户身份。
Cookie与Session说明与实现
Cookie
说明
Cookie是服务器生成并发送给浏览器的小型数据片段,通常以键值对(key-value)形式存在。服务器设定其过期时间,浏览器保存后,在后续访问同一服务器时会自动携带该Cookie。这使得服务器能够识别是哪个浏览器或用户在访问。需要注意的是,浏览器遵循同源策略,不会将某服务器的Cookie发送给其他不同域名的服务器。
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的有效性;用户登出时删除对应的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机制详解与Django代码实现
Session
Session说明
Session旨在提高用户信息的安全性,将敏感数据保存在服务端进行验证。尽管Session依赖于Cookie工作,但其核心区别在于数据存储位置。具体流程是:服务端为每个客户端(浏览器)生成一个唯一的Cookie值(Session ID),该值作为访问服务端Session数据的钥匙。
当客户端再次访问服务端时,会将包含Session ID的Cookie发送给服务器。服务器根据该ID在服务端的Session数据库中查找对应的用户信息。在Django项目中,这需要在应用的setting.py文件中配置Session的存储后端。
基于上述机制,Session将用户的敏感信息存储在服务端数据库中,相比Cookie直接存储在客户端,具有更高的安全性,不易被窃取或篡改。
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 ID)在后端数据库的Session表中检索对应的数据。Session能够存储更多的用户信息,且由于数据保存在服务端,有效防止了信息暴露,安全性更高。
总结
Session和Cookie都能实现记住用户登录状态的功能,但如果从安全性角度考虑,使用Session更为合适。
以上这篇django-利用session机制实现唯一登录的例子就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













