cookie和session
知识内容:
1.cookie
2.session
3.flask中的cookie和session
4.Django中的cookie和session
参考:http://www.cnblogs.com/liwenzhou/p/8343243.html
一、cookie
1.cookie由来
因为http请求是无状态的,每一次请求是独立的(对于服务端来说,一切均如初见!),很难实现保存状态
2.cookie是什么
Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息
cookie说简单点就是保持在浏览器上的键值对,服务端控制着响应,在响应里可以让浏览器在本地保存这个键值对(cookie),下次请求的时候发送的时候自动携带这个cookie
注意:cookie是服务端设置,但是浏览器(客户端)可以设置cookie(禁用cookie),另外cookie默认关闭浏览器就失效
例如:
1 cookie: _ga=GA1.2.1054004464.1521898033; __gads=ID=e13aa7dde32c5592:T=1526655541:S=ALNI_MZZ6P4iXCRX7EKM9IiKRBTv75Txmw; uaid=2b0dae04996e4d1b9de87d71f6f08088; .CNBlogsCookie=BEA8AC1412C8986DF38732BCAA2D291BAB1AAF7C686923F855A33A923BB8C8F6BE2F84B80CFEC7BBE6A83F23B865AB87D25FED9E10640E1E34269A641C1B0562C85CDD083B46DCC63FC52BF67D409F90936DAD38; .Cnblogs.AspNetCore.Cookies=CfDJ8FHXRRtkJWRFtU30nh_M9mCEXAQL_UyHvUyPS0oSzb3-whvexkm5XnGWepX0a6XLb-6kRfEDb1UgmfX2cmCIy2xLqCn3X8EAAV8GHySMlOc8vyx-_rBZXSgdfdyeUxliaVUUrljH5Y0Y6kO8I4qfemj7rSEWL9COZzWaOwNWlqGYE0Y55r1TUkAZ6W7ZVgsIaeatSFrSEBcsdvF8NdmsWLkPapTH_8qegCV1Sp3beSdaymrdZ4WPiSa1PGGT6jyr-l-Ddt2tKQzrYB_Txu16wSbZqe_xWD1GNATahXlw6AA1qn-sZz9NmkxTuLVvPOaF9Q; _gid=GA1.2.1318394338.1528273714
如何在浏览器上查看cookie(以谷歌浏览器为例):
选择页面右键点开选项选择检查,如下选择即可:
cookie从服务器发送到客户端的具体原理:在服务器发送给客户端的响应中如果有一个字段Set-Cookie,浏览器将会保存这个Set-Cookie对应的值,在下次向浏览器请求时带上这个值
3.cookie应用
问题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么cookie就起到桥接的作用
我们可以给每个客户端的cookie分配一个唯一的id,这样用户在访问时,通过cookie,服务器就知道来的人是“谁”。然后我们再根据不同的cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等
具体应用场景如下:
1 登录、七天免登录 2 记录用户的浏览习惯 3 简单的投票限制
二、session
1.session的由来
cookie虽然在一定程度上解决了“保持状态”的需求,但是由于cookie本身最大支持4096字节,以及cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是session
2.session是什么
session:保存在服务端的键值对
session必须依赖cookie,如下所示:
3. cookie和session比较
cookie:存储数据小、安全性差
session:存储数据大、安全性好
总结而言:cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过cookie识别不同的用户,对应的在session里保存私密的信息以及超过4096字节的文本
另外,上述所说的cookie和cookie其实是共通性的东西,不限于语言和框架。
三、flask中的cookie和session
(1)flask的cookie
1 # flask写入 cookie, 必须使用 make_response 函数 2 # 然后再用 set_cookie 来设置 cookie 3 r = make_response(template) 4 r.set_cookie('cookie_name', 'wyb') 5 return r
(2)flask的session
flask中有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥:
- 设置:session['username'] = 'xxx'
- 取出session值:session.get('username', None)
- 删除:session.pop('username', None)
基本使用(没有登录就让其登录,登录了页面显示登录成功,点击logout注销回到登录页面):
1 from flask import Flask, session, redirect, url_for, escape, request 2 3 app = Flask(__name__) 4 # set the secret key. keep this really secret: 5 app.secret_key = 'abcdefghyjklmnopqrstasdfu280975298165=-' 6 7 # escape(session['username']), session.get("username", None)是两种取session中值的方法 8 @app.route('/') 9 def index(): 10 if 'username' in session: 11 return 'Logged in as %s(%s), %s' % (escape(session['username']), session.get("username", None), "<a href='/logout'>注销</a>") 12 return redirect(url_for("login")) 13 14 @app.route('/login', methods=['GET', 'POST']) 15 def login(): 16 if request.method == 'POST': 17 session['username'] = request.form['username'] 18 return redirect(url_for('index')) 19 return ''' 20 <form action="" method="post"> 21 <p><input type=text name=username> 22 <p><input type=submit value=Login> 23 </form> 24 ''' 25 26 @app.route('/logout') 27 def logout(): 28 # remove the username from the session if it's there 29 session.pop('username', None) 30 return redirect(url_for('login')) 31 32 if __name__ == '__main__': 33 app.run(debug=True)
四、Django中的cookie和session
(1) django中的cookie
1 # Cookie: 保存在浏览器端的键值对 2 3 # 为什么要有Cookie: 因为HTTP请求是无状态的 4 5 # Cookie的原理: 6 """ 7 服务端可以在返回响应的时候 做手脚 8 在浏览器上写入键值对(Cookie) 9 10 浏览器发送请求的时候会自动携带该网站保存在我浏览器的键值对(Cookie) 11 """ 12 13 # Django 从请求携带的Cookie中取值: 14 request.COOKIES.get("is_login") 15 request.get_signed_cookie(key, default=None, salt="xxx") 16 # Django中设置Cookie:(针对的是响应对象) 17 rep = HttpResponse()/render(request, "test.html)/redirect() 18 rep.set_cookie(key, value) 19 # rep.set_signed_cookie(key, value, salt="xxx", max_age=7) 20 # Django中删除Cookie:(注销) 21 rep.delete_cookie(key)
删除cookie实现注销:
1 def logout(request): 2 rep = redirect("/login/") 3 rep.delete_cookie("user") # 删除用户浏览器上之前设置的usercookie值 4 return rep
cookie实现登陆验证:
1 def check_login(func): 2 @wraps(func) 3 def inner(request, *args, **kwargs): 4 next_url = request.get_full_path() 5 if request.get_signed_cookie("login", salt="SSS", default=None) == "yes": 6 # 已经登录的用户... 7 return func(request, *args, **kwargs) 8 else: 9 # 没有登录的用户,跳转刚到登录页面 10 return redirect("/login/?next={}".format(next_url)) 11 return inner 12 13 14 def login(request): 15 if request.method == "POST": 16 username = request.POST.get("username") 17 passwd = request.POST.get("password") 18 if username == "xxx" and passwd == "xxx": 19 next_url = request.GET.get("next") 20 if next_url and next_url != "/logout/": 21 response = redirect(next_url) 22 else: 23 response = redirect("/index/") 24 response.set_signed_cookie("login", "yes", salt="xxx") 25 return response 26 return render(request, "login.html")
(2)django中的session
1 # Session保存在服务端的键值对,另外Session依赖于Cookie 2 3 """ 4 Session原理: 5 用户数据: 6 xasdfvxs: {"is_login": 1, "name": "xiaohei", "age":18} 7 safsdfsdf: {"is_login": 1, "name": "xiaobai", "age":20} 8 wergasfd: {"is_login": 0, "name": "xiaohui", "age":48} 9 10 给浏览器写入Cookie: 11 sessionid: wergasfd 12 13 1. 从用户发来的请求的Cookie中 根据 sessionid 取值, 取到一个随机字符串 14 2. 根据这个随机字符串找到对应的 Session 数据 --> {"is_login": 0, "name": "xiaohui", "age":48} 15 3. request.session.get("is_login") --> 从Session取值 16 """ 17 18 19 # Django中设置Session: 20 request.session["is_login"] = 1 21 22 # Django设置session和cookie的超时时间 (Cookie和Session数据的) 23 request.session.set_expiry(7) 24 # 如果value是个整数,session会在些秒数后失效。 25 # 如果value是个datatime或timedelta,session就会在这个时间后失效。 26 # 如果value是0,用户关闭浏览器session就会失效。 27 # 如果value是None,session会依赖全局session失效策略。 28 29 # Django中取出session中的值 30 request.session.get("is_login") 31 32 # 在settings.py中设置,每次请求都刷新Session超时时间 33 SESSION_SAVE_EVERY_REQUEST = True 34 35 # Django中删除Session: 36 request.session.delete() # 只删除session 37 request.session.flush() # 清除Cookie和Session数据 38 request.session.clear_expired() 将所有Session失效日期小于当前日期的数据删除
(3)django中的session配置
1 1. 数据库Session 2 SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) 3 4 2. 缓存Session 5 SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎 6 SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置 7 8 3. 文件Session 9 SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎 10 SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 11 12 4. 缓存+数据库 13 SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎 14 15 5. 加密Cookie Session 16 SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎 17 18 其他公用设置项: 19 SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认) 20 SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认) 21 SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认) 22 SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认) 23 SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认) 24 SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认) 25 SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认) 26 SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认) 27 28 Django中Session相关设置
(4)Django中CBV使用装饰器实现登陆验证
要在CBV视图中使用我们上面的check_login装饰器,需要使用以下的django内置的方法:
1 from django.utils.decorators import method_decorator
当然关于这个方法的使用有以下三种方式:
1. 加在CBV视图的get或post方法上:
1 from django.utils.decorators import method_decorator 2 3 class HomeView(View): 4 def dispatch(self, request, *args, **kwargs): 5 return super(HomeView, self).dispatch(request, *args, **kwargs) 6 7 def get(self, request): 8 return render(request, "home.html") 9 10 @method_decorator(check_login) 11 def post(self, request): 12 print("Home View POST method...") 13 return redirect("/index/")
2. 加在dispatch方法上:
1 from django.utils.decorators import method_decorator 2 3 class HomeView(View): 4 @method_decorator(check_login) 5 def dispatch(self, request, *args, **kwargs): 6 return super(HomeView, self).dispatch(request, *args, **kwargs) 7 8 def get(self, request): 9 return render(request, "home.html") 10 11 def post(self, request): 12 print("Home View POST method...") 13 return redirect("/index/") 14 15 # 因为CBV中首先执行的就是dispatch方法,所以这么写相当于给get和post方法都加上了登录校验
3. 直接加在视图类上:
1 # 如果get方法和post方法都需要登录校验的话就写两个装饰器 2 # 注意method_decorator必须传name关键字参数 3 4 from django.utils.decorators import method_decorator 5 6 @method_decorator(check_login, name="get") 7 @method_decorator(check_login, name="post") 8 class HomeView(View): 9 def dispatch(self, request, *args, **kwargs): 10 return super(HomeView, self).dispatch(request, *args, **kwargs) 11 12 def get(self, request): 13 return render(request, "home.html") 14 15 def post(self, request): 16 print("Home View POST method...") 17 return redirect("/index/")