-
cookie与session
概念
因http协议无法保存状态,但是又需要保存状态,所以有了cookie。它不属于http协议范畴
工作原理:相当于一段标识数据。在访问服务器产生标识内容(cookie),加入到响应里返回,浏览器再次访问时会自动带上cookie。服务器就能识别出身份了。 数据缓存在浏览器中。减轻服务器端的压力。但安全性不高。
cookie随可实现保持状态,但其最大支持4096字节,且保存在客户端不安全,于是产生了支持更多字节,保存在服务端的机制--session。
session的机制:给客户端cookie加入不同的ID,访问时提供cookie,服务端根据ID拿出私密的数据,就可以识别出身份了。
但是cookie中内容被盗依然危险,所以有了失效时间。
总结:cookie与session要配合使用。cookie弥补了http无状态的不足,但存在客户端且安全性差。所以仅用cookie存标识号(sessionID),它对应服务端存的数据。
是开发界共通的概念
django实现cookie
- 获取cookie
request.COOKIES['key'] request.get_signed_cookie(key,default=RAISE_ERROR,salt='',max_age=None) default:默认值 salt:加密盐 max_age:过期时间
- 设置cookie
res = 任何一种响应方式实例对象。 res.set_cookie(key,value,……) res.set_signed_cookie(key,value,salt='加密盐',……)
def set_cookie(self, key, 键 value='', 值 max_age=None, 超长时间 expires=None, 超长时间 path='/', Cookie生效的路径,浏览器只会把cookie回传给带有该路径的页面,这样可以避免将cookie传给站点中的其他的应用。 / 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问 domain=None, Cookie生效的域名 你可用这个参数来构造一个跨站cookie。 如, domain=".example.com" 所构造的cookie对下面这些站点都是可读的: www2.example.com 和an.other.sub.domain.example.com 。 如果该参数设置为 None ,cookie只能由设置它的站点读取。 secure=False, 如果设置为 True ,浏览器将通过HTTPS来回传cookie。 httponly=False 只能http协议传输,无法被JavaScript获取 (不是绝对,底层抓包可以获取到也可以被覆盖) ): pass
由于cookie保存在客户端,所以,JavaScript和jquery也可以操作cookie。
<script src='/static/js/jquery.cookie.js'> </script> $.cookie("key", value,{ path: '/' });
- 删除cookie res.delete_cookie("cookie_key",path="/",domain=name)
Django实现session
设置session值 request.session['sname']="root" 获取session值 sname = request.session['sname'] 删除session值 del request.session['sname'] 检测是否操作session值 if "sname" is request.session .get .pop .keys .items .setdefault .flush 删数据和cookie .session_key .clear_expired .exists .delete 删数据 .set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
流程解析图
- 登录后生产个字典,字典存入session库,key是随机标识。value是数据字典
- 在value中存信息。
- 把Key写入cookie中返回,request.session看到的是value。
总结:Django中用session时,cookie由服务端生成,写到请求里返回给浏览器。浏览器会缓存。cookie是寻找用户信息的唯一标识。
session函数示例
def log_in(request): if request.method=="POST": username=request.POST['user'] password=request.POST['pwd'] user=UserInfo.objects.filter(username=username,password=password) if user: #设置session内部的字典内容 request.session['is_login']='true' request.session['username']=username #登录成功就将url重定向到后台的url return redirect('/backend/') #登录不成功或第一访问就停留在登录页面 return render(request,'login.html') def backend(request): print(request.session,"------cookie") print(request.COOKIES,'-------session') """ 这里必须用读取字典的get()方法把is_login的value缺省设置为False, 当用户访问backend这个url先尝试获取这个浏览器对应的session中的 is_login的值。如果对方登录成功的话,在login里就已经把is_login 的值修改为了True,反之这个值就是False的 """ is_login=request.session.get('is_login',False) #如果为真,就说明用户是正常登陆的 if is_login: #获取字典的内容并传入页面文件 cookie_content=request.COOKIES session_content=request.session username=request.session['username'] return render(request,'backend.html',locals()) else: """ 如果访问的时候没有携带正确的session, 就直接被重定向url回login页面 """ return redirect('/login/') def log_out(request): """ 直接通过request.session['is_login']回去返回的时候, 如果is_login对应的value值不存在会导致程序异常。所以 需要做异常处理 """ try: #删除is_login对应的value值 del request.session['is_login'] # OR---->request.session.flush() # 删除django-session表中的对应一行记录 except KeyError: pass #点击注销之后,直接重定向回登录页面 return redirect('/login/')
===================================login.html================== <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/login/" method="post"> <p>用户名: <input type="text" name="user"></p> <p>密码: <input type="password" name="pwd"></p> <p><input type="submit"></p> </form> </body> </html> ===================================backend.html================== <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>hello {{ username }}</h3> <a href="/logout/">注销</a> </body> </html>
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,默认修改之后才保存
用户认证
auth模块
导入
from django.contrib import auth
authenticate
用户认证,需要user和password关键字参数,认证有效会返回user对象,该对象会在后续的登录过程中使用。
login
认证成功后登录并返回页面 接收一个HttpRequest对象,以及认证后生成的user对象。
会给已认证的用户附加上sessionID等信息。logout
注销用户 接收一个HttpRequest对象,无返回值。
调用后,当前请求的session信息会全部清除。
即使用户没登录调用这个函数也不会报错。login认证后user对象的is_authenticated
判断认证是否通过。 不验证权限和激活状态。
实现未登录跳到登录,登录后再跳回来。
使用auth模块的 decorators的login_required方法。
若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' (在settings文件中通过LOGIN_URL进行修改)。并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。auth.models的user对象
is_staff 是否有管理权限 is_active 是否允许登录
创建用户create_user
user = User.objects.create_user(username='',password='',email='')
密码验证check_password
接收密码字符串。
用户需要修改密码的时候 首先要让他输入原来的密码 ,如果给定的字符串通过了密码检查,返回 True修改密码set_password
user = User.objects.get(username='') user.set_password(password='') user.save
示例
注册
def sign_up(request): state = None if request.method == 'POST': password = request.POST.get('password', '') repeat_password = request.POST.get('repeat_password', '') email=request.POST.get('email', '') username = request.POST.get('username', '') if User.objects.filter(username=username): state = 'user_exist' else: new_user = User.objects.create_user(username=username, password=password,email=email) new_user.save() return redirect('/book/') content = { 'state': state, 'user': None, } return render(request, 'sign_up.html', content)
改密码
@login_required def set_password(request): user = request.user state = None if request.method == 'POST': old_password = request.POST.get('old_password', '') new_password = request.POST.get('new_password', '') repeat_password = request.POST.get('repeat_password', '') if user.check_password(old_password): if not new_password: state = 'empty' elif new_password != repeat_password: state = 'repeat_error' else: user.set_password(new_password) user.save() return redirect("/log_in/") else: state = 'password_error' content = { 'user': user, 'state': state, } return render(request, 'set_password.html', content)