一、cookie
1.1 什么是cookie?
cookie
技术产生源于HTTP
协议在互联网上的急速发展,在浏览器发展初期,为了适应用户的需求,技术上推出了各种保持web浏览状态的手段,为什么要保持web浏览器的状态呢?
一般web
通信是基于HTTP
的,HTTP
是无状态的协议,也就是说,在一次请求响应结束后,服务器不会留下任何有关于对方状态信息,所以需要保持web浏览器的状态。
比如:对于有些web应用来说,客户端的某些信息必须被记住。比如用户登录过后跳转页面依然要保持登录的状态,进行其他的业务访问,而当这个登录过的用户再次访问web服务器的时候,web服务器并不知道这个用户已经登录过了,所以无法进行其他需要权限的业务访问。所以cookie
技术的出现就是为了解决这个问题。
cookie
的具体实现过程:当一个用户访问web
服务器后,web服务器会获取用户的状态并且返回一些数据(cookie)给浏览器,浏览器会自动储存这些数据(cookie),当用户再次访问web服务器,浏览器会把cookie放到请求报文中发送给web服务器,web服务器就会获取到了用户的状态。基于这次用户的状态方便用户进行其他业务的访问,并且web服务器可以设置浏览器保存cookie的时间,cookie是有域名的概念,只有访问同一个域名的时候才会把之前相同域名返回的cookie携带给该web服务器。
附注:1993年,网景公司雇员Lou Montulli为了提升用户体验,进一步实现了个人化网络。发明了今天广泛使用的Cookie。
关键词:
web
通讯一般基于HTTP
协议,HTTP
是无状态协议。Cookie
技术是用来保持web
访问状态,Cookie
技术通过在请求和响应报文中添加Cookie数据来保存客户端的状态信息- 服务器可以设置
cookie
的有效期,浏览器会自动清除过期的cookie。
cookie
有域名的概念,只有访问同一个域名,才会把之前相同域名返回的cookie携带给该服务器。
这里补充一下跨域的知识:
跨域问题来源于JavaScript
的"同源策略"
,即只有 协议+主机名+端口号
(如同在)都相同。则允许相互访问,也就是说JavaScript只能访问和操作自己域名下的资源,不能访问和操作其他域名下的资源
,跨域问题是针对JS
和jax
的,html
本身没有跨域问题
eg:
域名跨域:
http://www.abc.com/a/b 调用 http://www.abc.com/z/c (非跨域)
http://www.abc.com/a/b 调用 http://www.def.com/a/b (跨域: 域名不一致,abc与def)
端口跨域:
http://www.abc.com:8080/a/b 调用 http://www.def.com:8080/z/c (非跨域)
http://www.abc.com:8080/a/b 调用 http://www.def.com:9090/z/c (跨域: 端口不一致,8080与9090)
协议跨域:
http://www.abc.com/a/b 调用 https://www.def.com/a/b (跨域:协议不一致,http与https)
注意:localhost 和127.0.0.1 虽然都指向本机,但也是属于跨域的
跨域报错提示:
[ https://xx.xx.xx ] has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
1.2 如何在flask中使用cookie?
1.2.1 设置cookie
设置cookie
的时候是由我们web
服务器设置,也就是在Flask
项目中生成cookie
,经由响应报文返回给浏览器保存cookie
,下次浏览器再访问web服务器的时会在请求报文中把cookie
携带过来,所以cookie
产生的起点是在web
服务器中,也就是我们的Flask
项目中。
在Flask
中如果想要在响应中添加一个cookie
,最方便的做法是使用内置的Response
类提供的set_cookie()
方法。
表-2.2.1.1 set_cookie()方法的参数
属性 | 说明 |
---|---|
key | cookie的键(名称) |
value | cookie的值 |
max_age | cookie被保存的时间数,单位为秒。 |
expires | 具体的过期时间,一个datetime对象或UNIX时间戳 |
path | 限制cookie只在给定的路径可用,默认为整个域名下路径都可用 |
domain | 设置cookie可用的域名,默认是当前域名,子域名需要利用通配符domain=.当前域名 |
secure | 如果设为True,只有通过HTTPS才可以用 |
httponly | 如果设为True,进制客户端JavaScript获取cookie |
1.2.2 实例:设置cookie
项目目录
│ app.py
|
├─static # 文件夹
└─templates # 文件夹
app.py
from flask import Flask, Response
# 首先导入Flask内置的Response类,用于在响应报文中设置cookie
app = Flask(__name__)
@app.route('/')
def hello_world():
resp = Response('设置cookie给浏览器')
resp.set_cookie('user_name', 'mark')
return resp
if __name__ == '__main__':
app.run()
解读 app.py:
(1)在视图函数实例化Response
类并传入返回的内容,Response
类实例化出的对象调用set_cookie()
方 法,set_cookie内的第一个参数是设置cookie的key
,第二个参数是用来设置cookie的value,然后返回该对象,就会携带着设置好的cookie
返回给浏览器保存。
@app.route('/')
def hello_world():
resp = Response('设置cookie给浏览器')
resp.set_cookie('user_name', 'mark')
return resp
1.2.3 在浏览器中查看cookie的三种方式(以Chrome浏览器为例)
第一种: 右键检查----->Network---->找到访问的域名---->找到Response Headers---->Set-Cookie
第二种: 点击url输入框左边的信息icon,然后找到响应的域名,展开查看cookie。
第三种: 设置---->高级---->内容设置---->Cookie---->查看所有cookie设置----->根据域名搜索对应的cookie信息
注意:Flask服务器默认设置cookie有效期为关闭浏览器后cookie失效。
1.2.4 设置cookie的有效期
1.2.4.1 基于max_age参数设置cookie有效期
再设置cookie
的调用set_cookie()
时候传入关键字实参 max_age= 值
,这个值代表多少秒后过期。
注意:max_age参数设置过期时间不兼容IE8一下的浏览器
...
@app.route('/')
def hello_world():
resp = Response('设置cookie给浏览器')
resp.set_cookie('user_name', 'mark',max_age=60)
return resp
...
1.2.4.2 基于expires参数设置cookie有效期
再设置cookie
的调用set_cookie()
时候传入关键字实参 expires= 值
,这个值代具体的过期时间,一个datetime
对象或UNIX时间戳。
使用expires参数,就必须会用格林尼治时间(也就是相对北京时间少8个小时,因为浏览器会默认把服务器传来的时间值当做标准格林尼治时间,并根据当地的时区做调整 。
@app.route('/expires_demo/')
def expires_demo():
resp = Response('设置cookie给浏览器, cookie设置过期时间为一个月后')
expires = datetime.now()+timedelta(days=30, hours=16)
resp.set_cookie('user_name', 'mark', expires=expires)
return resp
和上面截图中一样,可继续查看过期时间,不在截图显示。
1.3、在Flask中查询cookie
1.3.1 查询cookie
查询cookie
是通过请求对象的cookies
属性读取,读取的过程是使用设置cookie
时的key
来读取到设置cookie
的value
...
@app.route('/get_cookie/')
def get_cookie():
user_name = request.cookies.get('user_name')
if user_name == 'mark':
return '{}的信息'.format(user_name)
return 'cookie验证失败'
...
1.3.2 删除cookie
删除cookie
是通过Flask
内置的Response
类实例化出的对象调用delete_cookie('key')
,删除的过程是使用设置cookie
时的key
来删除cookie
信息。
@app.route('/del/')
def del_cookie():
resp = Response('删除cookie')
resp.delete_cookie('user_name')
return resp
二、session
2.1 什么是session?
session的基本概念:session又称之为安全的cookie,session是一个思路、是一个概念、一个服务器存储授权信息的解决方案,不同的服务器,不同的框架,不同的语言有不同的实现,session的目的和cookie完全一致,cookie在客户端和服务端处理的非常粗糙,cookie在浏览器保存的时候以及传输的过程均使用明文,导致了很多安全隐患问题,session的出现就是为了解决cookie存储数据不安全的问题。
注意:session是一个思路一个概念,session的实现是基于cookie的,session并不像cookie是一项真实存在的技术,可以简单的理解为把粗糙的cookie在服务端通过加密,永久化等方式提高cookie的安全级别。
2.2、实现session的两种思路
第一种
- 客户端携带用户信息请求服务端验证。
- 服务端验证成功后生成随机的session_id与用户信息建立映射后存储到数据库中(注意:数据库可以是任意永久化保存数据的机制,如redis、memcached、mysql、甚至是文件等等)。
- 服务端把刚刚生成的session_id作为cookie信息返回给客户端。
- 客户端收到以session_id为内容的cookie信息保存到本地。
- 客户端再次请求的时候会携带以session_id为内容的cookie去访问服务端,服务端取出session_id去数据库校验得到用户信息。
第二种
- 客户端携带用户信息请求服务端验证。
- 服务端收到用户信息验证成功后,服务端再把用户信息经过严格的加密加盐生成session信息。并且把刚刚生成的session信息作为cookie的内容返回给客户端。
- 客户端收到以session信息为内容的cookie保存到本地。
- 客户端再次请求的时候会携带以session信息为内容的cookie去访问服务端,服务端取出session信息经过解密得到用户的信息。
注意:flask使用的就是第二种思路,利用加密解密的方式实现session,实现安全的cookie,服务端并不会做永久化的储存。
2.3 如何在flask中实现session?
2.3.1 设置session
Flask提供了session对象用来将cookie加密储存,session通过秘钥对数据进行签名以加密数据。
from flask import Flask, session
import os
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24) # 配置session使用的秘钥
@app.route('/')
def set_session_info():
session['username'] = 'mark' # 使用用户信息配置sesion信息作为cookie,并添加到响应体中
return '设置session信息'
解读
通过app对象 通过SECRET_KEY配置session使用的加密秘钥
app.config['SECRET_KEY'] = os.urandom(24) # 配置session使用的秘钥
session对象像可以字典一样操作,内部是把字典的信息进行加密操作然后添加到相应体中作为cookie,响应的时候会自动返回给浏览器。
session['username'] = 'mark'
session['userphone'] = '123456' # 可以指定多条session信息,统一放到响应的cookie中返回给浏览器
2.3.2 设置session有效期
后端Flask
跟浏览器交互默认情况下,session cookie
会在用户关闭浏览器时清除。通过将session.permanent属性设为True可以将session
的有效期延长为31天
,也可以通过操作app
的配置PERMANENT_SESSION_LIFETIME
来设置session
过期时间。
案例1 :开启指定session过期时间模式
from flask import Flask, session
import os
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)
@app.route('/')
def set_session_info():
session['username'] = 'mark'
session['userphone'] = '123456'
session.permanent = True # 开启设置有效期,默认为31天后过期
return 'Hello World!'
...
案例2: 开启session指定过期时间模式后指定具体的过期时间
基于上面的代码,通过设置PERMANENT_SESSION_LIFETIME
指定具体的过期时间
from datetime import timedelta
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=1) # 设置为1小时候过期
2.3.3 获取session
在Flask中
获取设置的session信息
通过session对象
获取,session对象是继承了字典类,所以获取的时候是字典的取值方式。其内部会把浏览器传过来的session信息解密。
@app.route('/get_session/')
def get_session():
username = session.get('username')
userphone = session.get('userphone')
if username or userphone:
return "{},{}".format(username, userphone)
return "session为空"
2.3.4 删除session
1、session
对象调用pop()
可以根据具体的session
的key清除掉指定的session信息。
2、session
对象调用clear()
可以清除此次请求的浏览器关于本域名的所有session信息
@app.route('/del_session/')
def del_session():
session.pop('username')
# session.clear()
return '删除成功'
原文来自:https://www.cnblogs.com/zhulipeng-1998/p/12863800.html#1221_max_agecookie_132