COOKIE&SESSION
知识储备
由于 http 协议无法保持状态, 但实际情况, 我们却又需要保持状态, 因此 cookie 就是在这样一个场景下诞生
cookie 的工作原理是: 由服务器产生内容, 浏览器收到请求后保存在本地; 当浏览器再次访问时, 浏览器会自动带上 cookie, 这样服务器就能通过 cookie 的内容来判断这个是谁了
cookie 虽然在一定程度上解决了保持状态的需求, 但是由于 cookie 本身最大支持 4096 字节, 以及 cookie 本身保存在客户端, 可能被拦截或窃取, 因此就需要有一种新的东西, 它能支持更多的字节, 并且他保存在服务器, 有较高的安全性这就是 session
问题来了, 基于 http 协议的无状态特征, 服务器根本就不知道访问者是谁那么上述的 cookie 就起到桥接的作用
我们可以给每个客户端的 cookie 分配一个唯一的 id, 这样用户在访问时, 通过 cookie, 服务器就知道来的人是谁然后我们再根据不同的 cookie 的 id, 在服务器上保存一段时间的私密资料, 如账号密码等等
总结而言: cookie 弥补了 http 无状态的不足, 让服务器知道来的人是谁; 但是 cookie 以文本的形式保存在本地, 自身安全性较差; 所以我们就通过 cookie 识别不同的用户, 对应的在 session 里保存私密的信息以及超过 4096 字节的文本
Django 实现 COOKIE
设置 cookie
obj = HttpResponse(...) 或 obj= render(request, ...) 或 obj= redirect()
- obj.set_cookie(key,value,...)
- obj.set_signed_cookie(key,value,salt = 加密盐,...)
获取 cookie
- request.COOKIES.get(key)
- request.get_signed_cookie(key, default=RAISE_ERROR, salt=, max_age=None)
删除 cookie
response.delete_cookie("cookie_key",path="/",domain=name)
参数
key, 键
value=, 值
max_age=None, 超长时间
expires=None, 超长时间
path=/, Cookie 生效的路径, 浏览器只会把 cookie 回传给带有该路径的页面, 这样可以避免将 cookie 传给站点中的其他的应用 / 表示根路径, 特殊的: 根路径的 cookie 可以被任何 url 的页面访问
domain=None, Cookie 生效的域名你可用这个参数来构造一个跨站 cookie 如, domain=".example.com" 所构造的 cookie 对下面这些站点都是可读 www.example.com www2.example.com
和 an.other.sub.domain.example.com
如果该参数设置为 None ,cookie 只能由设置它的站点读取
secure=False, 如果设置为 True , 浏览器将通过 HTTPS 来回传 cookie
httponly=False 只能 http 协议传输, 无法被 JavaScript 获取
(不是绝对, 底层抓包可以获取到也可以被覆盖
$.cookie("key", value,{ path: / })
jquery 操作 cookie
Django 实现 SESSION
设置 Session
request.session[key]=value
实际进行的操作:
1. 检查请求是否有 sessionid, 且是否存在与数据库, 存在则对 session_data 进行更新
2. 若不等, 则创建随机字符串
3. set_cookie(sessionid, 随机字符串)
4. 在 session 表中添加记录
session-key session-data
随机字符串 {"key":"value"}------------- 进行处理后的
获取 Session
session_name=request.session[key]
实际进行了哪些操作:
1. 取随机字符串 request.COOKIE.get(sessionid)
2. 在 session 表中进行过滤:
- obj=django-session.objects.filter(session-key=random_str).first()
- obj.session-data.get("user")
其他
- # 删除 Sessions 值
- del request.session["session_name"]
- # 检测是否操作 session 值
- if "session_name" is request.session:
配置
Django 默认支持 Session, 并且默认是将 Session 数据存储在数据库中, 即: django_session 表中
a. 配置 settings.py
- SESSION_ENGINE = django.contrib.sessions.backends.db # 引擎 (默认)
- SESSION_COOKIE_NAME = "sessionid" # Session 的 cookie 保存在浏览器上时的 key, 即: sessionid = 随机字符串 (默认)
- SESSION_COOKIE_PATH = "/" # Session 的 cookie 保存的路径 (默认)
- SESSION_COOKIE_DOMAIN = None # Session 的 cookie 保存的域名 (默认)
- SESSION_COOKIE_SECURE = False # 是否 Https 传输 cookie(默认)
- SESSION_COOKIE_HTTPONLY = True # 是否 Session 的 cookie 只支持 http 传输 (默认)
- SESSION_COOKIE_AGE = 1209600 # Session 的 cookie 失效日期 (2 周)(默认)
- SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得 Session 过期 (默认)
- SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存 Session, 默认修改之后才保存 (默认
数据库配置 (配置)
a. 配置 settings.py
- SESSION_ENGINE = django.contrib.sessions.backends.cache # 引擎
- SESSION_CACHE_ALIAS = default # 使用的缓存别名 (默认内存缓存, 也可以是 memcache), 此处别名依赖缓存的设置
- SESSION_COOKIE_NAME = "sessionid" # Session 的 cookie 保存在浏览器上时的 key, 即: sessionid = 随机字符串
- SESSION_COOKIE_PATH = "/" # Session 的 cookie 保存的路径
- SESSION_COOKIE_DOMAIN = None # Session 的 cookie 保存的域名
- SESSION_COOKIE_SECURE = False # 是否 Https 传输 cookie
- SESSION_COOKIE_HTTPONLY = True # 是否 Session 的 cookie 只支持 http 传输
- SESSION_COOKIE_AGE = 1209600 # Session 的 cookie 失效日期 (2 周)
- SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得 Session 过期
- SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存 Session, 默认修改之后才保存
缓存配置
a. 配置 settings.py
- SESSION_ENGINE = django.contrib.sessions.backends.file # 引擎
- SESSION_FILE_PATH = None # 缓存文件路径, 如果为 None, 则使用 tempfile 模块获取一个临时地址 tempfile.gettempdir()
- SESSION_COOKIE_NAME = "sessionid" # Session 的 cookie 保存在浏览器上时的 key, 即: sessionid = 随机字符串
- SESSION_COOKIE_PATH = "/" # Session 的 cookie 保存的路径
- SESSION_COOKIE_DOMAIN = None # Session 的 cookie 保存的域名
- SESSION_COOKIE_SECURE = False # 是否 Https 传输 cookie
- SESSION_COOKIE_HTTPONLY = True # 是否 Session 的 cookie 只支持 http 传输
- SESSION_COOKIE_AGE = 1209600 # Session 的 cookie 失效日期 (2 周)
- SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得 Session 过期
- SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存 Session, 默认修改之后才保存
文件配置
- def login_session(request):
- if request.method==POST:
- user=request.POST.get(user)
- pwd=request.POST.get(pwd)
- ret=UserInfo.objects.filter(name=user,pwd=pwd)
- if ret:
- request.session[user]=user
- return redirect(/index_session/)
- return render(request,login.html)
- def index_session(request):
- user=request.session.get(user)
- if not user:
- return redirect(/login_session/)
- return render(request,index.html,locals())
- View Code
Django 的用户认证
auth
利用 auth 模块中的一些方法来进行认证
- from django.contrib import auth
- authenticate()
提供了用户认证, 即验证用户名以及密码是否正确, 一般需要 username password 两个关键字参数
如果认证信息有效, 会返回一个 User 对象 authenticate() 会在 User 对象上设置一个属性标识那种认证后端认证了该用户, 且该信息在后面的登录过程中是需要的当我们试图登陆一个从数据库中直接取出来不经过 authenticate() 的 User 对象会报错的
- user = authenticate(username=someone,password=somepassword)
- login(HttpRequest, user)
该函数接受一个 HttpRequest 对象, 以及一个认证了的 User 对象
此函数使用 django 的 session 框架给某个已认证的用户附加上 session id 等信息
- login(request, user)
- logout(request)
该函数接受一个 HttpRequest 对象, 无返回值当调用该函数时, 当前请求的 session 信息会全部清除该用户即使没有登录, 使用该函数也不会报错
logout(request)
User 对象
User 对象属性:
username, password(必填项)password 用哈希算法保存到数据库
is_staff : 用户是否拥有网站的管理权限.
is_active : 是否允许用户登录, 设置为 ``False``, 可以不用删除用户来禁止 用户登录
is_authenticated()
如果是真正的 User 对象, 返回值恒为 True 用于检查用户是否已经通过了认证
通过认证并不意味着用户拥有任何权限, 甚至也不检查该用户是否处于激活状态, 这只是表明用户成功的通过了认证 这个方法很重要, 在后台用 request.user.is_authenticated() 判断用户是否已经登录, 如果 true 则可以向前台展示 request.user.name
- if not request.user.is_authenticated():
- return redirect(%s?next=%s % (settings.LOGIN_URL, request.path))
django 自带用于此种情况的装饰器: login_requierd()
- from django.contrib.auth.decorators import login_required
- @login_required
- def my_view(request):
若用户没有登录, 则会跳转到 django 默认的 登录 URL /accounts/login/ (这个值可以在 settings 文件中通过 LOGIN_URL 进行修改) 并传递 当前访问 url 的绝对路径 (登陆成功后, 会重定向到该路径)
创建用户
- from django.contrib.auth.models import User
- user = User.objects.create_user(username=,password=,email=)
修改密码 set_password()
- user = User.objects.get(username=)
- user.set_password(password=)
- user.save
- check_password(passwd)
用户需要修改密码的时候 首先要让他输入原来的密码 , 如果给定的字符串通过了密码检查, 返回 True
基于 auth 认证实现登录:
def login(request):
登录验证
- :param request:
- :return:
- if request.method==POST:
- username=request.POST.get(username)
- pwd=request.POST.get(pwd)
- input_valid_code=request.POST.get(valid_code)
- valid_code=request.session.get(valid_code)
- login_response={user:None,error_msg:}
- #进行验证码的比较
- if valid_code.upper()==input_valid_code.upper():
- user=auth.authenticate(username=username,password=pwd)
- if user:
- auth.login(request,user)
- login_response[user]=user.username
- else:
login_response[error_msg]= 用户名或密码错误!
else:
login_response[error_msg]= 验证码错误!
- import json
- return HttpResponse(json.dumps(login_response))
- return render(request,login.html,locals())
来源: http://www.bubuko.com/infodetail-2513491.html